diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index 2b8e6e4..9c0e940 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -50,73 +50,6 @@ static void armv8_set_registers(void *arch_load_info, - - - -/** - * TODO(M2): Implement this function. - * \brief Spawn a new dispatcher called 'argv[0]' with 'argc' arguments. - * - * This function spawns a new dispatcher running the ELF binary called - * 'argv[0]' with 'argc' - 1 additional arguments. It fills out 'si' - * and 'pid'. - * - * \param argc The number of command line arguments. Must be > 0. - * \param argv An array storing 'argc' command line arguments. - * \param si A pointer to the spawninfo struct representing - * the child. It will be filled out by this function. Must not be NULL. - * \param pid A pointer to a domainid_t variable that will be - * assigned to by this function. Must not be NULL. - * \return Either SYS_ERR_OK if no error occured or an error - * indicating what went wrong otherwise. - */ -errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, - domainid_t *pid) { - // TODO: Implement me - // - Initialize the spawn_info struct - // - Get the module from the multiboot image - // and map it (take a look at multiboot.c) - // - Setup the child's cspace - // - Setup the child's vspace - // - Load the ELF binary - // - Setup the dispatcher - // - Setup the environment - // - Make the new dispatcher runnable - - // afeer: script page 84/85 - cnode_create_l1(&si->cspace_l1_cnode_cap, &si->cspace_l1_cnode_info); - - cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_TASKCN, &si->cspace_l2_cnode_taskcn); - - // afeer: (script page 84) is this correct? - si->cspace_cap_selfep.cnode = si->cspace_l2_cnode_taskcn; - si->cspace_cap_selfep.slot = TASKCN_SLOT_SELFEP; - - si->cspace_cap_dispatcher.cnode = si->cspace_l2_cnode_taskcn; - si->cspace_cap_dispatcher.slot = TASKCN_SLOT_DISPATCHER; - - si->cspace_cap_rootcn.cnode = si->cspace_l2_cnode_taskcn; - si->cspace_cap_rootcn.slot = TASKCN_SLOT_ROOTCN; - - si->cspace_cap_dispframe.cnode = si->cspace_l2_cnode_taskcn; - si->cspace_cap_dispframe.slot = TASKCN_SLOT_DISPFRAME; - - si->cspace_cap_argspage.cnode = si->cspace_l2_cnode_taskcn; - si->cspace_cap_argspage.slot = TASKCN_SLOT_ARGSPAGE; - - cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC0, &si->cspace_l2_cnode_slot_alloc_0); - cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC1, &si->cspace_l2_cnode_slot_alloc_1); - cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC2, &si->cspace_l2_cnode_slot_alloc_2); - cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_BASE_PAGE_CN, &si->cspace_l2_cnode_base_pagecn); - cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_PAGECN, &si->cspace_l2_cnode_pagecn); // < afeer: TODO: script page 85: fill this with pagetable capabilities - - // afeer: populate some capabilities - dispatcher_create(si->cspace_cap_dispatcher); - cap_retype(si->cspace_cap_selfep, si->cspace_cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1); - - return LIB_ERR_NOT_IMPLEMENTED; -} - struct allocate_state { // TODO: add fields }; @@ -152,11 +85,131 @@ static errval_t elf_allocate( // TODO: Map into child address space + // TODO: Keep track of the mapped regions, so you can unmap them later. + return SYS_ERR_OK; } + /** - * TODO(M2): Implement this function. + * (M2): Implement this function. + * \brief Spawn a new dispatcher called 'argv[0]' with 'argc' arguments. + * + * This function spawns a new dispatcher running the ELF binary called + * 'argv[0]' with 'argc' - 1 additional arguments. It fills out 'si' + * and 'pid'. + * + * \param argc The number of command line arguments. Must be > 0. + * \param argv An array storing 'argc' command line arguments. + * \param si A pointer to the spawninfo struct representing + * the child. It will be filled out by this function. Must not be NULL. + * \param pid A pointer to a domainid_t variable that will be + * assigned to by this function. Must not be NULL. + * \return Either SYS_ERR_OK if no error occured or an error + * indicating what went wrong otherwise. + */ +errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, + domainid_t *pid) { + errval_t err; + // - Initialize the spawn_info struct + // TODO + + // - Get the module from the multiboot image + // and map it (take a look at multiboot.c) + + assert(argc > 0); + struct mem_region *module = multiboot_find_module(bi, argv[0]); + if (module == NULL) return SPAWN_ERR_FIND_MODULE; + size_t elf_bytes = module->mrmod_size; + + // Get the frame of the ELF + struct capref child_frame = { + .cnode = cnode_module, + .slot = module->mrmod_slot, + }; + + struct capability c; + err = cap_direct_identify(child_frame, &c); + if (err_is_fail(err)) return err; + gensize_t frame_size = get_size(&c); + if (frame_size < elf_bytes) return SPAWN_ERR_MODULE_FRAME_TOO_SMALL; + + // Map the ELF into the current address space + char *elf_base; + err = paging_map_frame_attr( + get_current_paging_state(), (void **)&elf_base, + frame_size, child_frame, VREGION_FLAGS_READ + ); + if (err_is_fail(err)) return err_push(err, SPAWN_ERR_MAP_MODULE); + + debug_printf("SPAWN: mapped %s, size: %"PRIuPTR", magic: %"PRIx8" %c%c%c\n", + argv[0], elf_bytes, elf_base[0], elf_base[1], elf_base[2], elf_base[3]); + + // - Setup the child's cspace + + // afeer: script page 84/85 + cnode_create_l1(&si->cspace_l1_cnode_cap, &si->cspace_l1_cnode_info); + + cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_TASKCN, &si->cspace_l2_cnode_taskcn); + + // afeer: (script page 84) is this correct? + si->cspace_cap_selfep.cnode = si->cspace_l2_cnode_taskcn; + si->cspace_cap_selfep.slot = TASKCN_SLOT_SELFEP; + + si->cspace_cap_dispatcher.cnode = si->cspace_l2_cnode_taskcn; + si->cspace_cap_dispatcher.slot = TASKCN_SLOT_DISPATCHER; + + si->cspace_cap_rootcn.cnode = si->cspace_l2_cnode_taskcn; + si->cspace_cap_rootcn.slot = TASKCN_SLOT_ROOTCN; + + si->cspace_cap_dispframe.cnode = si->cspace_l2_cnode_taskcn; + si->cspace_cap_dispframe.slot = TASKCN_SLOT_DISPFRAME; + + si->cspace_cap_argspage.cnode = si->cspace_l2_cnode_taskcn; + si->cspace_cap_argspage.slot = TASKCN_SLOT_ARGSPAGE; + + cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC0, &si->cspace_l2_cnode_slot_alloc_0); + cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC1, &si->cspace_l2_cnode_slot_alloc_1); + cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC2, &si->cspace_l2_cnode_slot_alloc_2); + cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_BASE_PAGE_CN, &si->cspace_l2_cnode_base_pagecn); + cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_PAGECN, &si->cspace_l2_cnode_pagecn); // < afeer: TODO: script page 85: fill this with pagetable capabilities + + // afeer: populate some capabilities + dispatcher_create(si->cspace_cap_dispatcher); + cap_retype(si->cspace_cap_selfep, si->cspace_cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1); + + // - Setup the child's vspace + // TODO + + // - Load the ELF binary + struct allocate_state st = {}; + genvaddr_t entry; + err = elf_load(EM_AARCH64, elf_allocate, &st, (lvaddr_t)elf_base, elf_bytes, &entry); + if (err_is_fail(err)) return err_push(err, SPAWN_ERR_ELF_LOAD); + + uint64_t got_addr = 0; + struct Elf64_Shdr* got_shdr = + elf64_find_section_header_name((lvaddr_t)elf_base, elf_bytes, ".got"); + if (got_shdr) { + got_addr = got_shdr->sh_addr; + } + + // - Setup the dispatcher + // TODO + + // - Setup the environment + // TODO + + // - Make the new dispatcher runnable + // TODO + + + + return LIB_ERR_NOT_IMPLEMENTED; +} + +/** + * (M2): Implement this function. * \brief Spawn a new dispatcher executing 'binary_name' * * \param binary_name The name of the binary. @@ -173,40 +226,17 @@ errval_t spawn_load_by_name(char *binary_name, struct spawninfo * si, errval_t err; // - Get the mem_region from the multiboot image - struct mem_region *module = multiboot_find_module(bi, binary_name); - if (module == NULL) return SPAWN_ERR_FIND_MODULE; - - // - Get the frame of the ELF - struct capref child_frame = { - .cnode = cnode_module, - .slot = module->mrmod_slot, - }; - - struct capability c; - err = cap_direct_identify(child_frame, &c); - if (err_is_fail(err)) return err; - gensize_t frame_size = get_size(&c); - if (frame_size < module->mrmod_size) return SPAWN_ERR_MODULE_FRAME_TOO_SMALL; - - // - Map the ELF into the current addess space - char *module_data; - err = paging_map_frame_attr( - get_current_paging_state(), (void **)&module_data, - frame_size, child_frame, VREGION_FLAGS_READ - ); - if (err_is_fail(err)) return err_push(err, SPAWN_ERR_MAP_MODULE); - - debug_printf("SPAWN: mapped %s, size: %"PRIx64", magic: %"PRIx8" %c%c%c\n", - binary_name, module->mrmod_size, module_data[0], module_data[1], module_data[2], module_data[3]); - - // - Parse the ELF - struct allocate_state st = {}; - genvaddr_t entry; - err = elf_load(EM_AARCH64, elf_allocate, &st, (lvaddr_t)module_data, module->mrmod_size, &entry); - if (err_is_fail(err)) return err_push(err, SPAWN_ERR_ELF_LOAD); + // TODO // - Fill in argc/argv from the multiboot command line - // - Call spawn_load_argv + // TODO + int argc = 1; + char *argv[1]; + argv[0] = binary_name; - return LIB_ERR_NOT_IMPLEMENTED; + // - Call spawn_load_argv + err = spawn_load_argv(argc, argv, si, pid); + if (err_is_fail(err)) return err; + + return SYS_ERR_OK; }