static struct dcb *spawn_init_common(const char *name, int argc, const char *argv[], lpaddr_t bootinfo_phys, alloc_phys_func alloc_phys, alloc_phys_aligned_func alloc_phys_aligned) { struct dispatcher_shared_generic *disp; struct dispatcher_shared_aarch64 *disp_aarch64; MSG("spawn_init_common %s\n", name); lvaddr_t paramaddr; struct dcb *init_dcb = spawn_module(&spawn_state, name, argc, argv, bootinfo_phys, INIT_ARGS_VBASE, alloc_phys, alloc_phys_aligned, ¶maddr); /* initialize page tables */ init_page_tables(); init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_l0); spawn_init_map(init_l3, ARMV8_INIT_VBASE, INIT_ARGS_VBASE, spawn_state.args_page, ARGS_SIZE, INIT_PERM_RW); /* Map dispatcher */ spawn_init_map(init_l3, ARMV8_INIT_VBASE, INIT_DISPATCHER_VBASE, mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE, INIT_PERM_RW); disp = get_dispatcher_shared_generic(init_dcb->disp); disp_aarch64 = get_dispatcher_shared_aarch64(init_dcb->disp); /* Initialize dispatcher */ disp->disabled = true; strncpy(disp->name, argv[0], DISP_NAME_LEN); /* Tell init the vspace addr of its dispatcher. */ disp->udisp = INIT_DISPATCHER_VBASE; /* TODO: write the contet ID for init */ /* Set the thread ID register to point to the shared structure. */ disp_aarch64->enabled_save_area.named.x0 = paramaddr; disp_aarch64->enabled_save_area.named.spsr = AARCH64_MODE_USR | CPSR_I_MASK; sysreg_write_tpidrro_el0((uint64_t)disp->udisp); dump_dispatcher(disp); return init_dcb; }
static struct dcb *spawn_init_common(const char *name, int argc, const char *argv[], lpaddr_t bootinfo_phys, alloc_phys_func alloc_phys) { printf("spawn_init_common %s\n", name); lvaddr_t paramaddr; struct dcb *init_dcb = spawn_module(&spawn_state, name, argc, argv, bootinfo_phys, INIT_ARGS_VBASE, alloc_phys, ¶maddr); init_page_tables(); printf("about to call mem_to_local_phys with lvaddr=%"PRIxLVADDR"\n", init_l1); init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_l1); spawn_init_map(init_l2, INIT_VBASE, INIT_ARGS_VBASE, spawn_state.args_page, ARGS_SIZE, INIT_PERM_RW); // Map dispatcher spawn_init_map(init_l2, INIT_VBASE, INIT_DISPATCHER_VBASE, mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE, INIT_PERM_RW); /* * we create the capability to the devices at this stage and store it * in the TASKCN_SLOT_IO, where on x86 the IO capability is stored for * device access on PCI. PCI is not available on the pandaboard so this * should not be a problem. */ struct cte *iocap = caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO); errval_t err = caps_create_new(ObjType_DevFrame, 0x40000000, 30, 30, iocap); assert(err_is_ok(err)); struct dispatcher_shared_generic *disp = get_dispatcher_shared_generic(init_dcb->disp); struct dispatcher_shared_arm *disp_arm = get_dispatcher_shared_arm(init_dcb->disp); /* Initialize dispatcher */ disp->disabled = true; strncpy(disp->name, argv[0], DISP_NAME_LEN); /* tell init the vspace addr of its dispatcher */ disp->udisp = INIT_DISPATCHER_VBASE; disp_arm->enabled_save_area.named.r0 = paramaddr; #ifndef __ARM_ARCH_7M__ //the armv7-m profile does not have such a mode field disp_arm->enabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK; #endif disp_arm->enabled_save_area.named.rtls = INIT_DISPATCHER_VBASE; disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE; printf("spawn_init_common: starting from=%"PRIxLVADDR"\n"); return init_dcb; }
spawn_init(const char* name, int32_t kernel_id, const uint8_t* initrd_base, size_t initrd_bytes) { assert(0 == kernel_id); // Create page table for init init_l1 = (uintptr_t*)alloc_mem_aligned(INIT_L1_BYTES, ARM_L1_ALIGN); memset(init_l1, 0, INIT_L1_BYTES); init_l2 = (uintptr_t*)alloc_mem_aligned(INIT_L2_BYTES, ARM_L2_ALIGN); memset(init_l2, 0, INIT_L2_BYTES); STARTUP_PROGRESS(); /* Allocate bootinfo */ lpaddr_t bootinfo_phys = alloc_phys(BOOTINFO_SIZE); memset((void *)local_phys_to_mem(bootinfo_phys), 0, BOOTINFO_SIZE); STARTUP_PROGRESS(); /* Construct cmdline args */ char bootinfochar[16]; snprintf(bootinfochar, sizeof(bootinfochar), "%u", INIT_BOOTINFO_VBASE); const char *argv[] = { "init", bootinfochar }; lvaddr_t paramaddr; struct dcb *init_dcb = spawn_module(&spawn_state, name, ARRAY_LENGTH(argv), argv, bootinfo_phys, INIT_ARGS_VBASE, alloc_phys, ¶maddr); STARTUP_PROGRESS(); /* * Create a capability that allows user-level applications to * access device memory. This capability will be passed to Kaluga, * split up into smaller pieces and distributed to among device * drivers. * * For armv5, this is currently a dummy capability. We do not * have support for user-level device drivers in gem5 yet, so we * do not allocate any memory as device memory. Some cap_copy * operations in the bootup code fail if this capability is not * present. */ struct cte *iocap = caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO); errval_t err = caps_create_new(ObjType_IO, 0, 0, 0, my_core_id, iocap); assert(err_is_ok(err)); struct dispatcher_shared_generic *disp = get_dispatcher_shared_generic(init_dcb->disp); struct dispatcher_shared_arm *disp_arm = get_dispatcher_shared_arm(init_dcb->disp); assert(NULL != disp); STARTUP_PROGRESS(); /* Initialize dispatcher */ disp->udisp = INIT_DISPATCHER_VBASE; STARTUP_PROGRESS(); init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_l1); STARTUP_PROGRESS(); /* Page table setup */ /* Map pagetables into page CN */ int pagecn_pagemap = 0; /* * ARM has: * * L1 has 4096 entries (16KB). * L2 Coarse has 256 entries (256 * 4B = 1KB). * * CPU driver currently fakes having 1024 entries in L1 and * L2 with 1024 entries by treating a page as 4 consecutive * L2 tables and mapping this as a unit in L1. */ caps_create_new( ObjType_VNode_ARM_l1, mem_to_local_phys((lvaddr_t)init_l1), vnode_objbits(ObjType_VNode_ARM_l1), 0, my_core_id, caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++) ); STARTUP_PROGRESS(); // Map L2 into successive slots in pagecn size_t i; for (i = 0; i < INIT_L2_BYTES / BASE_PAGE_SIZE; i++) { size_t objbits_vnode = vnode_objbits(ObjType_VNode_ARM_l2); assert(objbits_vnode == BASE_PAGE_BITS); caps_create_new( ObjType_VNode_ARM_l2, mem_to_local_phys((lvaddr_t)init_l2) + (i << objbits_vnode), objbits_vnode, 0, my_core_id, caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++) ); } /* * Initialize init page tables - this just wires the L1 * entries through to the corresponding L2 entries. */ STATIC_ASSERT(0 == (INIT_VBASE % ARM_L1_SECTION_BYTES), ""); for (lvaddr_t vaddr = INIT_VBASE; vaddr < INIT_SPACE_LIMIT; vaddr += ARM_L1_SECTION_BYTES) { uintptr_t section = (vaddr - INIT_VBASE) / ARM_L1_SECTION_BYTES; uintptr_t l2_off = section * ARM_L2_TABLE_BYTES; lpaddr_t paddr = mem_to_local_phys((lvaddr_t)init_l2) + l2_off; paging_map_user_pages_l1((lvaddr_t)init_l1, vaddr, paddr); } paging_make_good((lvaddr_t)init_l1, INIT_L1_BYTES); STARTUP_PROGRESS(); printf("XXX: Debug print to make Bram's code work\n"); paging_context_switch(mem_to_local_phys((lvaddr_t)init_l1)); STARTUP_PROGRESS(); // Map cmdline arguments in VSpace at ARGS_BASE STATIC_ASSERT(0 == (ARGS_SIZE % BASE_PAGE_SIZE), ""); STARTUP_PROGRESS(); spawn_init_map(init_l2, INIT_VBASE, INIT_ARGS_VBASE, spawn_state.args_page, ARGS_SIZE, INIT_PERM_RW); STARTUP_PROGRESS(); // Map bootinfo spawn_init_map(init_l2, INIT_VBASE, INIT_BOOTINFO_VBASE, bootinfo_phys, BOOTINFO_SIZE, INIT_PERM_RW); struct startup_l2_info l2_info = { init_l2, INIT_VBASE }; genvaddr_t init_ep, got_base; load_init_image(&l2_info, initrd_base, initrd_bytes, &init_ep, &got_base); // Set startup arguments (argc, argv) disp_arm->enabled_save_area.named.r0 = paramaddr; disp_arm->enabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK; disp_arm->enabled_save_area.named.rtls = INIT_DISPATCHER_VBASE; disp_arm->enabled_save_area.named.r10 = got_base; disp_arm->got_base = got_base; struct bootinfo* bootinfo = (struct bootinfo*)INIT_BOOTINFO_VBASE; bootinfo->regions_length = 0; STARTUP_PROGRESS(); create_modules_from_initrd(bootinfo, initrd_base, initrd_bytes); debug(SUBSYS_STARTUP, "used %"PRIuCSLOT" slots in modulecn\n", spawn_state.modulecn_slot); STARTUP_PROGRESS(); create_phys_caps(&spawn_state.physaddrcn->cap, bootinfo); STARTUP_PROGRESS(); bootinfo->mem_spawn_core = ~0; // Size of kernel if bringing up others // Map dispatcher spawn_init_map(init_l2, INIT_VBASE, INIT_DISPATCHER_VBASE, mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE, INIT_PERM_RW); STARTUP_PROGRESS(); // NB libbarrelfish initialization sets up the stack. disp_arm->disabled_save_area.named.pc = init_ep; disp_arm->disabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK; disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE; disp_arm->disabled_save_area.named.r10 = got_base; #ifdef __XSCALE__ cp15_disable_cache(); #endif printf("Kernel ready.\n"); pit_start(); // On to userland... STARTUP_PROGRESS(); dispatch(init_dcb); panic("Not reached."); }
static struct dcb *spawn_init_common(struct spawn_state *st, const char *name, int argc, const char *argv[], lpaddr_t bootinfo_phys, alloc_phys_func alloc_phys) { errval_t err; /* Perform arch-independent spawn */ lvaddr_t paramaddr; struct dcb *init_dcb = spawn_module(st, name, argc, argv, bootinfo_phys, ARGS_BASE, alloc_phys, ¶maddr); /* Init page tables */ init_page_tables(st, alloc_phys); /* Map dispatcher R/W into VSpace starting at vaddr 0x204000 * (Starting after Bootinfo pages)*/ #ifdef CONFIG_PAE paging_x86_32_map_pdpte(&init_pdpte[X86_32_PDPTE_BASE(DISPATCHER_BASE)], mem_to_local_phys((lvaddr_t)init_pdir)); #endif paging_x86_32_map_table(&init_pdir[X86_32_PDIR_BASE(DISPATCHER_BASE)], mem_to_local_phys((lvaddr_t)init_ptable)); for (int i = 0; i < DISPATCHER_SIZE / BASE_PAGE_SIZE; i++) { paging_x86_32_map(&init_ptable[X86_32_PTABLE_BASE(DISPATCHER_BASE) + i], mem_to_local_phys(init_dcb->disp) + i * BASE_PAGE_SIZE, INIT_PAGE_BITMAP | paging_elf_to_page_flags(PF_R | PF_W)); } struct dispatcher_shared_generic *init_disp = get_dispatcher_shared_generic(init_dcb->disp); struct dispatcher_shared_x86_32 *init_disp_x86_32 = get_dispatcher_shared_x86_32(init_dcb->disp); registers_set_param(&init_disp_x86_32->enabled_save_area, paramaddr); // Map IO cap in task cnode struct cte *iocap = caps_locate_slot(CNODE(st->taskcn), TASKCN_SLOT_IO); err = caps_create_new(ObjType_IO, 0, 0, 0, my_core_id, iocap); assert(err_is_ok(err)); /* Set fields in DCB */ // Set Vspace #ifdef CONFIG_PAE init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_pdpte); #else init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_pdir); #endif /* Initialize dispatcher */ init_disp->disabled = true; strncpy(init_disp->name, argv[0], DISP_NAME_LEN); /* tell init the vspace addr of its dispatcher */ init_disp->udisp = DISPATCHER_BASE; init_disp_x86_32->disabled_save_area.edi = DISPATCHER_BASE; init_disp_x86_32->disabled_save_area.fs = 0; init_disp_x86_32->disabled_save_area.gs = 0; init_disp_x86_32->disabled_save_area.cs = USER_CS; init_disp_x86_32->disabled_save_area.ss = USER_SS; init_disp_x86_32->disabled_save_area.eflags = USER_EFLAGS; return init_dcb; }