context_t act_init(context_t own_context, init_info_t* info, size_t init_base, size_t init_entry) { KERNEL_TRACE("init", "activation init"); internel_if.message_send = kernel_seal(act_send_message_get_trampoline(), act_ref_type); internel_if.message_reply = kernel_seal(act_send_return_get_trampoline(), act_sync_ref_type); setup_syscall_interface(&internel_if); kernel_next_act = 0; // This is a dummy. Our first context has already been created reg_frame_t frame; bzero(&frame, sizeof(struct reg_frame)); // Register the kernel (exception) activation act_t * kernel_act = &kernel_acts[0]; act_register(&frame, &kernel_queue.queue, "kernel", status_terminated, NULL, cheri_getbase(cheri_getpcc())); /* The kernel context already exists and we set it here */ kernel_act->context = own_context; // Create and register the init activation KERNEL_TRACE("act", "Retroactively creating init activation"); /* Not a dummy here. We will subset our own c0/pcc for init. init is loaded directly after the kernel */ bzero(&frame, sizeof(struct reg_frame)); size_t length = cheri_getlen(cheri_getdefault()) - init_base; frame.cf_c0 = cheri_setbounds(cheri_setoffset(cheri_getdefault(), init_base), length); capability pcc = cheri_setbounds(cheri_setoffset(cheri_getpcc(), init_base), length); KERNEL_TRACE("act", "assuming init has virtual entry point %lx", init_entry); frame.cf_c12 = frame.cf_pcc = cheri_setoffset(pcc, init_entry); /* provide config info to init. c3 is the conventional register */ frame.cf_c3 = info; act_t * init_act = &kernel_acts[namespace_num_boot]; act_register_create(&frame, &init_queue.queue, "init", status_alive, NULL); /* The boot activation should be the current activation */ sched_schedule(init_act); return init_act->context; }
int act_terminate(act_control_t * ctrl) { ctrl->status = status_terminated; KERNEL_TRACE("act", "Terminating %s", ctrl->name); /* This will never return if this is a self terminate. We will be removed from the queue and descheduled */ sched_delete(ctrl); if(ctrl == kernel_curr_act) { /* terminated itself */ kernel_panic("Should not reach here"); } return 0; }
void kernel_interrupt(void) { register_t ipending = cp0_cause_ipending_get(); register_t toprocess = ipending & get_others_interrupts_mask(); KERNEL_TRACE("interrupt", "%x %x", ipending, toprocess); if (ipending & MIPS_CP0_CAUSE_IP_TIMER) { kernel_timer(); } if(toprocess) { kernel_interrupt_others(toprocess); } }
void kernel_interrupts_init(int enable_timer) { KERNEL_TRACE("init", "enabling interrupts"); kernel_assert(cp0_status_ie_get() == 0); cp0_status_ie_enable(); if(enable_timer) { /* Start timer */ kernel_timer_init(); cp0_status_im_enable(MIPS_CP0_STATUS_IM_TIMER); } }
status_e act_get_status(act_control_t *ctrl) { KERNEL_TRACE("get status", "%s", ctrl->name); return ctrl->status; }
act_t * act_register(reg_frame_t *frame, queue_t *queue, const char *name, status_e create_in_status, act_control_t *parent, size_t base) { (void)parent; KERNEL_TRACE("act", "Registering activation %s", name); if(kernel_next_act >= MAX_ACTIVATIONS) { kernel_panic("no act slot"); } act_t * act = kernel_acts + kernel_next_act; act->image_base = base; //TODO bit of a hack. the kernel needs to know what namespace service to use if(kernel_next_act == namespace_num_namespace) { KERNEL_TRACE("act", "found namespace"); ns_ref = act_create_sealed_ref(act); } #ifndef __LITE__ /* set name */ kernel_assert(ACT_NAME_MAX_LEN > 0); int name_len = 0; if(VCAP(name, 1, VCAP_R)) { name_len = imin(cheri_getlen(name), ACT_NAME_MAX_LEN-1); } for(int i = 0; i < name_len; i++) { char c = name[i]; act->name[i] = c; /* todo: sanitize the name if we do not trust it */ } act->name[name_len] = '\0'; #endif /* set status */ act->status = create_in_status; /*Some "documentation" for the interface between the kernel and activation start * * These fields are setup by the caller of act_register * * * * a0 : user GP argument (goes to main) * * c3 : user Cap argument (goes to main) * * * * These fields are setup by act_register itself. Although the queue is an argument to the function * * * * c21 : self control reference * * c23 : namespace reference (may be null for init and namespace) * * c24 : kernel interface table * * c25 : queue */ /* set namespace */ frame->cf_c21 = (capability)act_create_sealed_ctrl_ref(act); frame->cf_c23 = (capability)ns_ref; frame->cf_c24 = (capability)get_if(); frame->cf_c25 = (capability)queue; /* set queue */ msg_queue_init(act, queue); /* set expected sequence to not expecting */ act->sync_state.sync_token = 0; act->sync_state.sync_condition = 0; /* set scheduling status */ sched_create(act); /*update next_act */ kernel_next_act++; KERNEL_TRACE("register", "image base of %s is %lx", act->name, act->image_base); KERNEL_TRACE("act", "%s OK! ", __func__); return act; }