Barrelfish (standard config) boots with 1 mapping per cap copy.
authorSimon Gerber <simugerber@student.ethz.ch>
Thu, 22 Nov 2012 14:53:15 +0000 (15:53 +0100)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Tue, 29 Jan 2013 10:31:00 +0000 (11:31 +0100)
12 files changed:
errors/errno.fugu
include/barrelfish_kpi/init.h
include/spawndomain/spawndomain.h
kernel/arch/x86_64/page_mappings_arch.c
kernel/syscall.c
lib/barrelfish/target/x86_64/pmap_target.c
lib/elf/elf64.c
lib/spawndomain/arch/x86/spawn_arch.c
lib/spawndomain/multiboot.c
lib/spawndomain/spawn.c
usr/init/init.c
usr/monitor/arch/x86/boot.c

index aeed8a7..e6ca1c8 100644 (file)
@@ -135,6 +135,9 @@ errors libcaps CAPS_ERR_ {
     // mdb operation errors
     failure MDB_DUPLICATE_ENTRY "Inserted entry already present",
     failure MDB_ENTRY_NOTFOUND  "Removed entry not found",
+
+    // search errors
+    failure CAP_NOT_FOUND       "Did not find a matching capability",
 };
 
 // errors generated by libbarrelfish code
index 5348905..31258e4 100644 (file)
 #define TASKCN_SLOT_SESSIONID   12  ///< Session ID domain belongs to
 #define TASKCN_SLOT_FDSPAGE     13  ///< cap for inherited file descriptors
 #define TASKCN_SLOT_PERF_MON    14  ///< cap for performance monitoring
-#define TASKCN_SLOTS_USER       15  ///< First free slot in taskcn for user
+#define TASKCN_SLOT_DISPFRAME2  15  ///< Copy of dispatcher frame cap (mapped into spawn vspace)
+#define TASKCN_SLOT_ARGSPAGE2   16  ///< Copy of environment cap (mapped into spawn vspace)
+#define TASKCN_SLOTS_USER       17  ///< First free slot in taskcn for user
 
 /// Address bits resolved for the standard CNodes (taskcn, supercn, base_page_cn)
 #define DEFAULT_CN_ADDR_BITS    (CPTR_BITS - DEFAULT_CNODE_BITS)
index 327916b..4f60dee 100644 (file)
@@ -70,6 +70,8 @@ errval_t spawn_load_image(struct spawninfo *si, lvaddr_t binary,
 errval_t spawn_run(struct spawninfo *si);
 errval_t spawn_free(struct spawninfo *si);
 
+errval_t multiboot_cleanup_mapping(void);
+
 /* spawn_vspace.c */
 errval_t spawn_vspace_init(struct spawninfo *si, struct capref vnode,
                            enum cpu_type cpu_type);
@@ -91,6 +93,7 @@ struct mem_region *multiboot_find_module_containing(struct bootinfo *bi,
                                                    const char *containing);
 errval_t spawn_map_module(struct mem_region *module, size_t *retsize,
                           lvaddr_t *retaddr, genpaddr_t *retpaddr);
+errval_t spawn_unmap_module(lvaddr_t mapped_addr);
 errval_t spawn_map_bootinfo(struct spawninfo *si, genvaddr_t *retvaddr);
 const char *getopt_module(struct mem_region *module);
 
index 7b77bee..d111e57 100644 (file)
@@ -16,6 +16,8 @@
 #include <dispatch.h>
 #include <target/x86_64/paging_kernel_target.h>
 #include <target/x86_64/offsets_target.h>
+#include <mdb/mdb_tree.h>
+#include <string.h>
 
 /// Map within a x86_64 pml4
 static errval_t x86_64_pml4(struct capability *dest, cslot_t slot,
@@ -191,6 +193,10 @@ static mapping_handler_t handler[ObjType_Num] = {
     [ObjType_VNode_x86_64_ptable] = x86_64_ptable,
 };
 
+
+#define DIAGNOSTIC_ON_ERROR 1
+#define RETURN_ON_ERROR 1
+
 /// Create page mappings
 errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
                             struct cte *src_cte, uintptr_t param1,
@@ -209,19 +215,27 @@ errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
 
     if (mapped_pages >= src_cte->mapping_info.page_count) {
         // exceeded allowed page count for this mapping
+#if DIAGNOSTIC_ON_ERROR
         printf("caps_copy_to_vnode: exceeded allowed page count for this mapping\n");
         printf("                    mapped_pages = %zd, mapping_info.page_count = %zd\n",
                 mapped_pages, src_cte->mapping_info.page_count);
+#endif
+#if RETURN_ON_ERROR
         return SYS_ERR_VM_MAP_SIZE;
+#endif
     }
 
     if ((param2 - src_cte->mapping_info.offset)/BASE_PAGE_SIZE >= src_cte->mapping_info.page_count) {
         // requested map offset exceeds mapping region
+#if DIAGNOSTIC_ON_ERROR
         printf("caps_copy_to_vnode: requested map offset exceeds mapping region\n");
         printf("                    offset = %zd, mapping_info.offset = %zd, page_count = %zd",
                 param2, src_cte->mapping_info.offset,
                 src_cte->mapping_info.page_count);
+#endif
+#if RETURN_ON_ERROR
         return SYS_ERR_VM_MAP_OFFSET;
+#endif
     }
 
     errval_t r = handler_func(dest_cap, dest_slot, src_cap, param1, param2, &pte);
@@ -239,6 +253,9 @@ errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
 {
     assert(type_is_vnode(pgtable->type));
 
+    // XXX: temporary
+    genpaddr_t paddr;
+
     switch (pgtable->type) {
     case ObjType_VNode_x86_64_pml4: {
         genpaddr_t gp = pgtable->u.vnode_x86_64_pml4.base;
@@ -246,6 +263,7 @@ errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
         lvaddr_t   lv = local_phys_to_mem(lp);
         union x86_64_pdir_entry *entry =
             (union x86_64_pdir_entry *)lv + slot;
+        paddr = entry->d.base_addr << BASE_PAGE_BITS;
         entry->raw = X86_64_PTABLE_CLEAR;
         break;
     }
@@ -255,6 +273,7 @@ errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
         lvaddr_t   lv = local_phys_to_mem(lp);
         union x86_64_pdir_entry *entry =
             (union x86_64_pdir_entry *)lv + slot;
+        paddr = entry->d.base_addr << BASE_PAGE_BITS;
         entry->raw = X86_64_PTABLE_CLEAR;
         break;
     }
@@ -264,6 +283,7 @@ errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
         lvaddr_t   lv = local_phys_to_mem(lp);
         union x86_64_pdir_entry *entry =
             (union x86_64_pdir_entry *)lv + slot;
+        paddr = entry->d.base_addr << BASE_PAGE_BITS;
         entry->raw = X86_64_PTABLE_CLEAR;
         break;
     }
@@ -273,6 +293,7 @@ errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
         lvaddr_t   lv = local_phys_to_mem(lp);
         union x86_64_ptable_entry *entry =
             (union x86_64_ptable_entry *)lv + slot;
+        paddr = entry->base.base_addr << BASE_PAGE_BITS;
         entry->raw = X86_64_PTABLE_CLEAR;
         break;
     }
@@ -280,6 +301,16 @@ errval_t page_mappings_unmap(struct capability *pgtable, size_t slot)
         assert(!"Should not get here");
     }
 
+    // XXX: temporary
+    // TODO: fix lookup to choose correct cap
+    struct cte *mem;
+    errval_t err = mdb_find_cap_for_address(paddr, &mem);
+    if (err_is_fail(err)) {
+        return err;
+    }
+    // clear mapping info
+    memset(&mem->mapping_info, 0, sizeof(struct mapping_info));
+
     // XXX: FIXME: Going to reload cr3 to flush the entire TLB.
     // This is inefficient.
     // The current implementation is also not multicore safe.
index 768fbef..7920544 100644 (file)
@@ -343,7 +343,6 @@ sys_modify_mapping(struct capability *mem, size_t page_count, uint64_t off)
 {
     /* find cte belonging to cap */
     struct cte *mem_cap = cte_for_cap(mem);
-    printf("0x%p, 0x%p\n", mem_cap, mem);
 
     if (!type_is_vnode(mem->type) && mem->type != ObjType_Frame && mem->type != ObjType_DevFrame){
         // this only works for mappable memory
index b6570bd..7ca1074 100644 (file)
@@ -131,7 +131,7 @@ static errval_t alloc_vnode(struct pmap_x86 *pmap, struct vnode *root,
     }
 
     // Map it
-    printf("\talloc_vnode calling vnode_map()\n");
+    //printf("\talloc_vnode calling vnode_map()\n");
     err = vnode_map(root->u.vnode.cap, newvnode->u.vnode.cap, entry,
                     PTABLE_ACCESS_DEFAULT, 0);
     if (err_is_fail(err)) {
@@ -259,7 +259,7 @@ static errval_t do_map(struct pmap_x86 *pmap, genvaddr_t vaddr,
 
         // Map entry into the page table in the kernel
         uint32_t entry = X86_64_PTABLE_BASE(vaddr);
-        printf("\tdo_map calling vnode_map()\n");
+        //printf("\tdo_map calling vnode_map()\n");
         err = vnode_map(ptable->u.vnode.cap, frame, entry, pmap_flags, i);
         if (err_is_fail(err)) {
             return err_push(err, LIB_ERR_VNODE_MAP);
@@ -495,7 +495,7 @@ static errval_t modify_flags(struct pmap *pmap, genvaddr_t vaddr, size_t size,
 
         // Remap with changed flags
         paging_x86_64_flags_t pmap_flags = vregion_to_pmap_flag(flags);
-        printf("\tmodify_flags calling vnode_map()\n");
+        //printf("\tmodify_flags calling vnode_map()\n");
         err = vnode_map(ptable->u.vnode.cap, vn->u.frame.cap, vn->entry,
                         pmap_flags, vn->u.frame.offset);
         if (err_is_fail(err)) {
index f96f1d8..55e8f2c 100644 (file)
@@ -335,7 +335,7 @@ errval_t elf64_load(uint16_t em_machine, elf_allocator_fn allocate_func,
         struct Elf64_Phdr *p = &phead[i];
 
         if (p->p_type == PT_LOAD) {
-            //printf("Loading segment: start=0x%lx, size=%lu, flags=%d\n",
+            //printf("Loading segment: start=0x%"PRIx64", size=%"PRIu64", flags=%d\n",
             //p->p_vaddr, p->p_memsz, p->p_flags);
 
             // Map segment in user-space memory
index 186b7d4..68c302d 100644 (file)
@@ -65,7 +65,6 @@ static errval_t elf_allocate(void *state, genvaddr_t base, size_t size,
     size = ROUND_UP(size, BASE_PAGE_SIZE);
 
     cslot_t vspace_slot = si->elfload_slot;
-    cslot_t spawn_vspace_slot = si->elfload_slot;
 
     // Allocate the frames
     size_t sz = 0;
@@ -81,6 +80,27 @@ static errval_t elf_allocate(void *state, genvaddr_t base, size_t size,
         }
     }
 
+    cslot_t spawn_vspace_slot = si->elfload_slot;
+    cslot_t new_slot_count = si->elfload_slot - vspace_slot;
+
+    // create copies of the frame capabilities for spawn vspace
+    for (int copy_idx = 0; copy_idx < new_slot_count; copy_idx++) {
+        struct capref frame = {
+            .cnode = si->segcn,
+            .slot = vspace_slot + copy_idx,
+        };
+        struct capref spawn_frame = {
+            .cnode = si->segcn,
+            .slot = si->elfload_slot++,
+        };
+        err = cap_copy(spawn_frame, frame);
+        if (err_is_fail(err)) {
+            // TODO: make debug printf
+            printf("cap_copy failed for src_slot = %d, dest_slot = %d\n", frame.slot, spawn_frame.slot);
+            return err_push(err, LIB_ERR_CAP_COPY);
+        }
+    }
+
     /* Map into my vspace */
     struct memobj *memobj = malloc(sizeof(struct memobj_anon));
     if (!memobj) {
@@ -129,12 +149,12 @@ static errval_t elf_allocate(void *state, genvaddr_t base, size_t size,
     }
     for (lvaddr_t offset = 0; offset < size; offset += sz) {
         sz = 1UL << log2floor(size - offset);
-        struct capref frame = {
+        struct capref spawn_frame = {
             .cnode = si->segcn,
-            .slot  = spawn_vspace_slot++,
+            .slot = spawn_vspace_slot++,
         };
         genvaddr_t genvaddr = vspace_lvaddr_to_genvaddr(offset);
-        err = memobj->f.fill(spawn_memobj, genvaddr, frame, sz);
+        err = memobj->f.fill(spawn_memobj, genvaddr, spawn_frame, sz);
         if (err_is_fail(err)) {
             return err_push(err, LIB_ERR_MEMOBJ_FILL);
         }
@@ -166,6 +186,8 @@ errval_t spawn_arch_load(struct spawninfo *si,
         .cnode = si->rootcn,
         .slot  = ROOTCN_SLOT_SEGCN,
     };
+    // XXX: this code assumes that elf_load never needs more than 32 slots for 
+    // text frame capabilities.
     err = cnode_create_raw(cnode_cap, &si->segcn, DEFAULT_CNODE_SLOTS, NULL);
     if (err_is_fail(err)) {
         return err_push(err, SPAWN_ERR_CREATE_SEGCN);
index f712369..ab73a13 100644 (file)
@@ -114,6 +114,10 @@ errval_t spawn_map_module(struct mem_region *module, size_t *retsize,
     return SYS_ERR_OK;
 }
 
+errval_t spawn_unmap_module(lvaddr_t mapped_addr)
+{
+    return vspace_unmap((void *)mapped_addr);
+}
 
 /// Returns a raw pointer to the modules string area string
 const char *multiboot_module_rawstring(struct mem_region *region)
@@ -149,6 +153,17 @@ const char *multiboot_module_rawstring(struct mem_region *region)
     return multiboot_strings + region->mrmod_data;
 }
 
+errval_t multiboot_cleanup_mapping(void)
+{
+    errval_t err = vspace_unmap(multiboot_strings);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "multiboot_cleanup_mapping: vspace_unmap() failed\n");
+        return err_push(err, LIB_ERR_VSPACE_REMOVE_REGION);
+    }
+    multiboot_strings = NULL;
+    return SYS_ERR_OK;
+}
+
 
 /// returns the basename without arguments of a multiboot module
 // XXX: returns pointer to static buffer. NOT THREAD SAFE
@@ -220,3 +235,4 @@ struct mem_region *multiboot_find_module_containing(struct bootinfo *bi,
 
     return NULL;
 }
+
index 46b7f2f..2e9ea56 100644 (file)
@@ -290,10 +290,18 @@ static errval_t spawn_setup_dispatcher(struct spawninfo *si,
     /* 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;
@@ -303,7 +311,7 @@ static errval_t spawn_setup_dispatcher(struct spawninfo *si,
         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, si->dispframe,
+    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);
@@ -452,14 +460,22 @@ static errval_t spawn_setup_env(struct spawninfo *si,
     // 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, si->argspg, ARGS_SIZE);
+    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);
     }
@@ -892,6 +908,9 @@ errval_t spawn_load_with_bootinfo(struct spawninfo *si, struct bootinfo *bi,
     }
     free(multiboot_args);
 
+    // unmap bootinfo module pages
+    spawn_unmap_module(binary);
+
     return SYS_ERR_OK;
 }
 
index bb7da57..9d354b8 100644 (file)
@@ -153,6 +153,13 @@ static errval_t bootstrap(int argc, char *argv[])
         return err_push(err, INIT_ERR_SPAWN_MONITOR);
     }
 
+    /* unmap bootinfo mem */
+    err = multiboot_cleanup_mapping();
+    if (err_is_fail(err)) {
+        //return err_push(err, INIT_ERR_UNMAP_BOOTINFO);
+        return err;
+    }
+
     /* Initialize monitor */
     err = initialize_monitor(&monitor_si);
     if (err_is_fail(err)) {
index f05868e..61eca9a 100644 (file)
@@ -381,10 +381,6 @@ errval_t spawn_xcore_monitor(coreid_t coreid, int hwid, enum cpu_type cpu_type,
     }
 
     /* Clean up */ // XXX: Should not delete the remote cap
-    err = cap_destroy(cpu_memory_cap);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "cap_destroy failed");
-    }
     err = cap_destroy(spawn_memory_cap);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "cap_destroy failed");
@@ -393,6 +389,10 @@ errval_t spawn_xcore_monitor(coreid_t coreid, int hwid, enum cpu_type cpu_type,
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "vspace unmap CPU driver memory failed");
     }
+    err = cap_destroy(cpu_memory_cap);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "cap_destroy failed");
+    }
 
     return SYS_ERR_OK;
 }