static void load_init_image( struct startup_l3_info* l3i, const char *name, genvaddr_t* init_ep, genvaddr_t* got_base ) { lvaddr_t elf_base; size_t elf_bytes; errval_t err; *init_ep = *got_base = 0; /* Load init ELF64 binary */ struct multiboot_header_tag *multiboot = (struct multiboot_header_tag *) local_phys_to_mem( armv8_glbl_core_data->multiboot_image.base); struct multiboot_tag_module_64 *module = multiboot2_find_module_64( multiboot, armv8_glbl_core_data->multiboot_image.length, name); if (module == NULL) { panic("Could not find init module!"); } elf_base = local_phys_to_mem(module->mod_start); elf_bytes = MULTIBOOT_MODULE_SIZE(*module); debug(SUBSYS_STARTUP, "load_init_image %p %08x\n", elf_base, elf_bytes); printf("load_init_image %p %08x\n", elf_base, elf_bytes); err = elf_load(EM_AARCH64, startup_alloc_init, l3i, elf_base, elf_bytes, init_ep); if (err_is_fail(err)) { //err_print_calltrace(err); panic("ELF load of " BSP_INIT_MODULE_NAME " failed!\n"); } // TODO: Fix application linkage so that it's non-PIC. struct Elf64_Shdr* got_shdr = elf64_find_section_header_name((lvaddr_t)elf_base, elf_bytes, ".got"); if (got_shdr) { *got_base = got_shdr->sh_addr; } }
/// Setup the module cnode, which contains frame caps to all multiboot modules void create_module_caps(struct spawn_state *st) { errval_t err; /* Create caps for multiboot modules */ struct multiboot_modinfo *module = (struct multiboot_modinfo *)local_phys_to_mem(glbl_core_data->mods_addr); // Allocate strings area lpaddr_t mmstrings_phys = bsp_alloc_phys(BASE_PAGE_SIZE); lvaddr_t mmstrings_base = local_phys_to_mem(mmstrings_phys); lvaddr_t mmstrings = mmstrings_base; // create cap for strings area in first slot of modulecn assert(st->modulecn_slot == 0); err = caps_create_new(ObjType_Frame, mmstrings_phys, BASE_PAGE_BITS, BASE_PAGE_BITS, caps_locate_slot(CNODE(st->modulecn), st->modulecn_slot++)); assert(err_is_ok(err)); /* Walk over multiboot modules, creating frame caps */ for (int i = 0; i < glbl_core_data->mods_count; i++) { struct multiboot_modinfo *m = &module[i]; // Set memory regions within bootinfo struct mem_region *region = &bootinfo->regions[bootinfo->regions_length++]; genpaddr_t remain = MULTIBOOT_MODULE_SIZE(*m); genpaddr_t base_addr = local_phys_to_gen_phys(m->mod_start); region->mr_type = RegionType_Module; region->mr_base = base_addr; region->mrmod_slot = st->modulecn_slot; // first slot containing caps region->mrmod_size = remain; // size of image _in bytes_ region->mrmod_data = mmstrings - mmstrings_base; // offset of string in area // round up to page size for caps remain = ROUND_UP(remain, BASE_PAGE_SIZE); // Create max-sized caps to multiboot module in module cnode while (remain > 0) { assert((base_addr & BASE_PAGE_MASK) == 0); assert((remain & BASE_PAGE_MASK) == 0); // determine size of next chunk uint8_t block_size = bitaddralign(remain, base_addr); assert(st->modulecn_slot < (1UL << st->modulecn->cap.u.cnode.bits)); // create as DevFrame cap to avoid zeroing memory contents err = caps_create_new(ObjType_DevFrame, base_addr, block_size, block_size, caps_locate_slot(CNODE(st->modulecn), st->modulecn_slot++)); assert(err_is_ok(err)); // Advance by that chunk base_addr += ((genpaddr_t)1 << block_size); remain -= ((genpaddr_t)1 << block_size); } // Copy multiboot module string to mmstrings area strcpy((char *)mmstrings, MBADDR_ASSTRING(m->string)); mmstrings += strlen(MBADDR_ASSTRING(m->string)) + 1; assert(mmstrings < mmstrings_base + BASE_PAGE_SIZE); } }
struct dcb *spawn_bsp_init(const char *name, alloc_phys_func alloc_phys) { errval_t err; /* Only the first core can run this code */ assert(apic_is_bsp()); /* Allocate bootinfo */ lpaddr_t bootinfo_phys = alloc_phys(BOOTINFO_SIZE); memset((void *)local_phys_to_mem(bootinfo_phys), 0, BOOTINFO_SIZE); /* Construct cmdline args */ char bootinfochar[16]; snprintf(bootinfochar, sizeof(bootinfochar), "%"PRIuLPADDR, BOOTINFO_BASE); const char *argv[6] = { "init", bootinfochar }; int argc = 2; #ifdef __scc__ if(glbl_core_data->urpc_frame_base != 0) { char coreidchar[10]; snprintf(coreidchar, sizeof(coreidchar), "%d", glbl_core_data->src_core_id); argv[argc++] = coreidchar; char chan_id_char[30]; snprintf(chan_id_char, sizeof(chan_id_char), "chanid=%"PRIu32, glbl_core_data->chan_id); argv[argc++] = chan_id_char; char urpc_frame_base_char[30]; snprintf(urpc_frame_base_char, sizeof(urpc_frame_base_char), "frame=%" PRIuGENPADDR, glbl_core_data->urpc_frame_base); argv[argc++] = urpc_frame_base_char; } #endif struct dcb *init_dcb = spawn_init_common(&spawn_state, name, argc, argv, bootinfo_phys, alloc_phys); /* Map bootinfo R/W into VSpace at vaddr 0x200000 (BOOTINFO_BASE) */ #ifdef CONFIG_PAE paging_x86_32_map_pdpte(&init_pdpte[0], mem_to_local_phys((lvaddr_t)init_pdir)); paging_x86_32_map_table(&init_pdir[1], mem_to_local_phys((lvaddr_t)init_ptable)); for (int i = 0; i < BOOTINFO_SIZE / BASE_PAGE_SIZE; i++) { paging_x86_32_map(&init_ptable[i], bootinfo_phys + i * BASE_PAGE_SIZE, INIT_PAGE_BITMAP | paging_elf_to_page_flags(PF_R|PF_W)); } #else paging_x86_32_map_table(&init_pdir[0], mem_to_local_phys((lvaddr_t)init_ptable)); for (int i = 0; i < BOOTINFO_SIZE / BASE_PAGE_SIZE; i++) { paging_x86_32_map(&init_ptable[i + 512], bootinfo_phys + i * BASE_PAGE_SIZE, INIT_PAGE_BITMAP | paging_elf_to_page_flags(PF_R|PF_W)); } #endif /* Load init ELF32 binary */ struct multiboot_modinfo *module = multiboot_find_module(name); if (module == NULL) { panic("Could not find init module!"); } genvaddr_t init_ep; err = elf_load(EM_386, startup_alloc_init, &spawn_state, local_phys_to_mem(module->mod_start), MULTIBOOT_MODULE_SIZE(*module), &init_ep); if (err_is_fail(err)) { //err_print_calltrace(err); panic("ELF load of init module failed!"); } struct dispatcher_shared_x86_32 *init_disp_x86_32 = get_dispatcher_shared_x86_32(init_dcb->disp); init_disp_x86_32->disabled_save_area.eip = init_ep; /* Create caps for init to use */ create_module_caps(&spawn_state); lpaddr_t init_alloc_end = alloc_phys(0); // XXX create_phys_caps(init_alloc_end); /* Fill bootinfo struct */ bootinfo->mem_spawn_core = NEEDED_KERNEL_SPACE; // Size of kernel /* for (int i = 0; i < bootinfo->regions_length; i++) { */ /* printf("%d region %d: 0x%09" PRIxPTR " - 0x%09lx (%lu MB, %u bits)\n", */ /* bootinfo->regions[i].mr_type, i, bootinfo->regions[i].mr_base, */ /* bootinfo->regions[i].mr_base + (1UL<<bootinfo->regions[i].mr_bits), */ /* bootinfo->regions[i].mr_bits >= 20 */ /* ? 1UL << (bootinfo->regions[i].mr_bits - 20) : 0, */ /* bootinfo->regions[i].mr_bits); */ /* } */ #if 0 // If app core, map (static) URPC channel if(kernel_scckernel != 0) { printf("SCC app kernel, frame at: 0x%x\n", kernel_scckernel); #define TASKCN_SLOT_MON_URPC (TASKCN_SLOTS_USER+6) ///< Frame cap for urpc comm. err = caps_create_new(ObjType_Frame, kernel_scckernel, 13, 13, caps_locate_slot(CNODE(taskcn), TASKCN_SLOT_MON_URPC)); assert(err_is_ok(err)); } #endif return init_dcb; }