void handle_irq(arch_registers_state_t* save_area, uintptr_t fault_pc, uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) { uint32_t irq = 0; /* The assembly stub leaves the first 4 registers, the stack pointer, and * the exception PC for us to save, as it's run out of room for the * necessary instructions. */ save_area->named.x0 = x0; save_area->named.x1 = x1; save_area->named.x2 = x2; save_area->named.x3 = x3; save_area->named.stack = sysreg_read_sp_el0(); save_area->named.pc = fault_pc; irq = gic_get_active_irq(); debug(SUBSYS_DISPATCH, "IRQ %"PRIu32" while %s\n", irq, dcb_current ? (dcb_current->disabled ? "disabled": "enabled") : "in kernel"); if (dcb_current != NULL) { dispatcher_handle_t handle = dcb_current->disp; if (save_area == dispatcher_get_disabled_save_area(handle)) { assert(dispatcher_is_disabled_ip(handle, fault_pc)); dcb_current->disabled = true; } else { /* debug(SUBSYS_DISPATCH, "save_area=%p, dispatcher_get_enabled_save_are(handle)=%p\n", save_area, dispatcher_get_enabled_save_area(handle)); */ assert(save_area == dispatcher_get_enabled_save_area(handle)); assert(!dispatcher_is_disabled_ip(handle, fault_pc)); dcb_current->disabled = false; } } if (pit_handle_irq(irq)) { // Timer interrupt, pit_handle_irq acks it at the timer. assert(kernel_ticks_enabled); kernel_now += kernel_timeslice; wakeup_check(kernel_now); dispatch(schedule()); } /* This is the (still) unacknowledged startup interrupt sent by the BSP. * We just acknowledge it here. */ else if(irq == 1) { gic_ack_irq(irq); dispatch(schedule()); } else { gic_ack_irq(irq); send_user_interrupt(irq); panic("Unhandled IRQ %"PRIu32"\n", irq); } }
/** * \brief Setup arguments and environment * * \param argv Command-line arguments, NULL-terminated * \param envp Environment, NULL-terminated */ static errval_t spawn_setup_env(struct spawninfo *si, char *const argv[], char *const envp[]) { errval_t err; // Create frame (actually multiple pages) for arguments si->argspg.cnode = si->taskcn; si->argspg.slot = TASKCN_SLOT_ARGSPAGE; struct capref spawn_argspg = { .cnode = si->taskcn, .slot = TASKCN_SLOT_ARGSPAGE2, }; err = frame_create(si->argspg, ARGS_SIZE, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_ARGSPG); } err = cap_copy(spawn_argspg, si->argspg); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_ARGSPG); } /* Map in args frame */ genvaddr_t spawn_args_base; err = spawn_vspace_map_one_frame(si, &spawn_args_base, spawn_argspg, ARGS_SIZE); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_ARGSPG_TO_NEW); } void *argspg; err = vspace_map_one_frame(&argspg, ARGS_SIZE, si->argspg, NULL, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_ARGSPG_TO_SELF); } /* Layout of arguments page: * struct spawn_domain_params; // contains pointers to other fields * char buf[]; // NUL-terminated strings for arguments and environment * vspace layout data follows the string data */ struct spawn_domain_params *params = argspg; char *buf = (char *)(params + 1); size_t buflen = ARGS_SIZE - (buf - (char *)argspg); /* Copy command-line arguments */ int i; size_t len; for (i = 0; argv[i] != NULL; i++) { len = strlen(argv[i]) + 1; if (len > buflen) { return SPAWN_ERR_ARGSPG_OVERFLOW; } strcpy(buf, argv[i]); params->argv[i] = buf - (char *)argspg + (char *)(lvaddr_t)spawn_args_base; buf += len; buflen -= len; } assert(i <= MAX_CMDLINE_ARGS); int argc = i; params->argv[i] = NULL; /* Copy environment strings */ for (i = 0; envp[i] != NULL; i++) { len = strlen(envp[i]) + 1; if (len > buflen) { return SPAWN_ERR_ARGSPG_OVERFLOW; } strcpy(buf, envp[i]); params->envp[i] = buf - (char *)argspg + (char *)(lvaddr_t)spawn_args_base; buf += len; buflen -= len; } assert(i <= MAX_ENVIRON_VARS); params->envp[i] = NULL; /* Serialise vspace data */ // XXX: align buf to next word char *vspace_buf = (char *)ROUND_UP((lvaddr_t)buf, sizeof(uintptr_t)); buflen -= vspace_buf - buf; // FIXME: currently just the pmap is serialised err = si->vspace->pmap->f.serialise(si->vspace->pmap, vspace_buf, buflen); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_SERIALISE_VSPACE); } /* Setup environment pointer and vspace pointer */ params->argc = argc; params->vspace_buf = (char *)vspace_buf - (char *)argspg + (char *)(lvaddr_t)spawn_args_base; params->vspace_buf_len = buflen; // Setup TLS data params->tls_init_base = (void *)vspace_genvaddr_to_lvaddr(si->tls_init_base); params->tls_init_len = si->tls_init_len; params->tls_total_len = si->tls_total_len; arch_registers_state_t *enabled_area = dispatcher_get_enabled_save_area(si->handle); registers_set_param(enabled_area, (uintptr_t)spawn_args_base); return SYS_ERR_OK; } /** * Copies caps from inheritcnode into destination cnode, * ignores caps that to not exist. * * \param inheritcn Source cnode * \param inherit_slot Source cnode slot * \param destcn Target cnode * \param destcn_slot Target cnode slot * * \retval SYS_ERR_OK Copy to target was successful or source cap * did not exist. * \retval SPAWN_ERR_COPY_INHERITCN_CAP Error in cap_copy */ static errval_t spawn_setup_inherited_cap(struct cnoderef inheritcn, capaddr_t inherit_slot, struct cnoderef destcn, capaddr_t destcn_slot) { errval_t err; struct capref src; src.cnode = inheritcn; src.slot = inherit_slot;; // Create frame (actually multiple pages) for fds struct capref dest; dest.cnode = destcn; dest.slot = destcn_slot; err = cap_copy(dest, src); if (err_no(err) == SYS_ERR_SOURCE_CAP_LOOKUP) { // there was no fdcap to inherit, continue return SYS_ERR_OK; } else if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_COPY_INHERITCN_CAP); } return SYS_ERR_OK; }
/** * \brief Setup the dispatcher frame */ static errval_t spawn_setup_dispatcher(struct spawninfo *si, coreid_t core_id, const char *name, genvaddr_t entry, void* arch_info) { errval_t err; /* Create dispatcher frame (in taskcn) */ si->dispframe.cnode = si->taskcn; si->dispframe.slot = TASKCN_SLOT_DISPFRAME; struct capref spawn_dispframe = { .cnode = si->taskcn, .slot = TASKCN_SLOT_DISPFRAME2, }; err = frame_create(si->dispframe, (1 << DISPATCHER_FRAME_BITS), NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_DISPATCHER_FRAME); } err = cap_copy(spawn_dispframe, si->dispframe); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_DISPATCHER_FRAME); } /* Map in dispatcher frame */ dispatcher_handle_t handle; err = vspace_map_one_frame((void**)&handle, 1ul << DISPATCHER_FRAME_BITS, si->dispframe, NULL, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_DISPATCHER_TO_SELF); } genvaddr_t spawn_dispatcher_base; err = spawn_vspace_map_one_frame(si, &spawn_dispatcher_base, spawn_dispframe, 1UL << DISPATCHER_FRAME_BITS); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_DISPATCHER_TO_NEW); } /* Set initial state */ // XXX: Confusion address translation about l/gen/addr in entry struct dispatcher_shared_generic *disp = get_dispatcher_shared_generic(handle); struct dispatcher_generic *disp_gen = get_dispatcher_generic(handle); arch_registers_state_t *enabled_area = dispatcher_get_enabled_save_area(handle); arch_registers_state_t *disabled_area = dispatcher_get_disabled_save_area(handle); /* Place core_id */ disp_gen->core_id = core_id; /* place eh information */ disp_gen->eh_frame = si->eh_frame; disp_gen->eh_frame_size = si->eh_frame_size; disp_gen->eh_frame_hdr = si->eh_frame_hdr; disp_gen->eh_frame_hdr_size = si->eh_frame_hdr_size; /* Setup dispatcher and make it runnable */ disp->udisp = spawn_dispatcher_base; disp->disabled = 1; disp->fpu_trap = 1; #ifdef __k1om__ disp->xeon_phi_id = disp_xeon_phi_id(); #endif // Copy the name for debugging const char *copy_name = strrchr(name, '/'); if (copy_name == NULL) { copy_name = name; } else { copy_name++; } strncpy(disp->name, copy_name, DISP_NAME_LEN); spawn_arch_set_registers(arch_info, handle, enabled_area, disabled_area); registers_set_entry(disabled_area, entry); si->handle = handle; return SYS_ERR_OK; } errval_t spawn_map_bootinfo(struct spawninfo *si, genvaddr_t *retvaddr) { errval_t err; struct capref src = { .cnode = cnode_task, .slot = TASKCN_SLOT_BOOTINFO }; struct capref dest = { .cnode = si->taskcn, .slot = TASKCN_SLOT_BOOTINFO }; err = cap_copy(dest, src); if (err_is_fail(err)) { return err_push(err, LIB_ERR_CAP_COPY); } err = spawn_vspace_map_one_frame(si, retvaddr, dest, BOOTINFO_SIZE); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_BOOTINFO); } return SYS_ERR_OK; } /** * \brief Retrive the commandline args of #name * * The arguments are malloced into a new space so need to be freed after use */ errval_t spawn_get_cmdline_args(struct mem_region *module, char **retargs) { assert(module != NULL && retargs != NULL); /* Get the cmdline args */ const char *args = getopt_module(module); /* Allocate space */ *retargs = malloc(sizeof(char) * strlen(args)); if (!retargs) { return LIB_ERR_MALLOC_FAIL; } /* Copy args */ strcpy(*retargs, args); return SYS_ERR_OK; }
/* * \brief handler pretty much any usermode IRQ except system calls */ void handle_irq(uint32_t irq, arch_registers_state_t* save_area) { /* printf("handle_irq: registers:\n");//dump content for debugging reasons for(uint32_t i = 0; i<NUM_REGS; i++){ printf("0x%x\n", save_area->regs[i]); }*/ /* uint32_t regval; __asm volatile ("mrs %[regval], xpsr" : [regval] "=r"(regval)); printf("current XPSR register: 0x%x\n", regval); printf("M3 MMU address: 0x%x\n", *((uint32_t*) &mmu)); printf("M3 MMU_FAULT_AD register: 0x%x\n", omap44xx_mmu_fault_ad_rd(&mmu)); printf("M3 MMU_FAULT_STATUS register: 0x%x\n", omap44xx_mmu_fault_status_rd(&mmu)); printf("M3 MMU_FAULT_PC register: 0x%x\n", omap44xx_mmu_fault_pc_rd(&mmu)); printf("M3 MMU_IRQSTATUS register: 0x%x\n", omap44xx_mmu_irqstatus_rd(&mmu)); printf("ICTR: 0x%x\n", omap44xx_cortex_m3_nvic_ICTR_rd(&nvic)); printf("CPUID_BASE: 0x%x\n", omap44xx_cortex_m3_nvic_CPUID_BASE_rd(&nvic)); printf("ICSR: 0x%x\n", omap44xx_cortex_m3_nvic_ICSR_rd(&nvic)); printf("VTOR: 0x%x\n", omap44xx_cortex_m3_nvic_VTOR_rd(&nvic)); printf("AIRCR: 0x%x\n", omap44xx_cortex_m3_nvic_AIRCR_rd(&nvic)); printf("CCR: 0x%x\n", omap44xx_cortex_m3_nvic_CCR_rd(&nvic)); printf("SHCSR: 0x%x\n", omap44xx_cortex_m3_nvic_SHCSR_rd(&nvic)); printf("CFSR: 0x%x\n", omap44xx_cortex_m3_nvic_CFSR_rd(&nvic)); printf("BFAR: 0x%x\n", omap44xx_cortex_m3_nvic_BFAR_rd(&nvic)); printf("SYSTICK_CTRL: 0x%x\n", omap44xx_cortex_m3_nvic_SYSTICK_CTRL_rd(&nvic)); printf("SYSTICK_CALV: 0x%x\n", omap44xx_cortex_m3_nvic_SYSTICK_CALV_rd(&nvic)); */ uintptr_t fault_pc = save_area->named.pc;//read faulting pc from pushed context debug(SUBSYS_DISPATCH, "IRQ %"PRIu32" while %s\n", irq, dcb_current ? (dcb_current->disabled ? "disabled": "enabled") : "in kernel"); if (dcb_current != NULL) { dispatcher_handle_t handle = dcb_current->disp; if (save_area == dispatcher_get_disabled_save_area(handle)) { assert(dispatcher_is_disabled_ip(handle, fault_pc)); dcb_current->disabled = true; } else { /* debug(SUBSYS_DISPATCH, "save_area=%p, dispatcher_get_enabled_save_are(handle)=%p\n", save_area, dispatcher_get_enabled_save_area(handle)); */ assert(save_area == dispatcher_get_enabled_save_area(handle)); assert(!dispatcher_is_disabled_ip(handle, fault_pc)); dcb_current->disabled = false; } } //TODO: heteropanda: make a case distinction on the type of interrupt, and //actually handle it if (irq == ARM_7M_EVECTOR_SYSTICK) { // Timer interrupt assert(kernel_ticks_enabled); kernel_now += kernel_timeslice; wakeup_check(kernel_now); printf(".");//to see how many we get & their distribution, without spamming lines dispatch(schedule()); } else { // send_user_interrupt(irq); panic("Unhandled IRQ %"PRIu32"\n", irq); } }