T121: Create "real" BSP KCB cap for x86.
authorSimon Gerber <simon.gerber@inf.ethz.ch>
Mon, 15 Jun 2015 09:16:25 +0000 (11:16 +0200)
committerMoritz Hoffmann <moritz.hoffmann@inf.ethz.ch>
Tue, 16 Jun 2015 11:37:41 +0000 (13:37 +0200)
Signed-off-by: Simon Gerber <simon.gerber@inf.ethz.ch>

include/barrelfish_kpi/init.h
kernel/arch/x86/startup_x86.c
kernel/arch/x86_64/init.c
kernel/startup.c
usr/init/spawn.c

index 2928270..5ee12bd 100644 (file)
@@ -97,7 +97,8 @@
 #define ROOTCN_SLOT_SLOT_ALLOC1  8   ///< Root of slot alloc1
 #define ROOTCN_SLOT_SLOT_ALLOC2  9   ///< Root of slot alloc2
 #define ROOTCN_SLOT_ARGCN        10  ///< Argcn slot in root cnode
-#define ROOTCN_SLOTS_USER        11  ///< First free slot in root cnode for user
+#define ROOTCN_SLOT_BSPKCB       11  ///< BSP KCB cap to fix reverse lookup issues
+#define ROOTCN_SLOTS_USER        12  ///< First free slot in root cnode for user
 
 /* Size of CNodes in Root CNode if not the default size */
 #define SLOT_ALLOC_CNODE_BITS   (DEFAULT_CNODE_BITS * 2)
index 8360d18..70d3ae4 100644 (file)
@@ -550,9 +550,16 @@ void kernel_startup(void)
         /* Initialize the location to allocate phys memory from */
         bsp_init_alloc_addr = glbl_core_data->start_free_ram;
 
+        /* allocate initial KCB */
+        kcb_current = (struct kcb *) local_phys_to_mem(bsp_alloc_phys(sizeof(*kcb_current)));
+        assert(kcb_current);
+
         /* spawn init */
         init_dcb = spawn_bsp_init(BSP_INIT_MODULE_PATH, bsp_alloc_phys);
     } else {
+        kcb_current = (struct kcb *)
+            local_phys_to_mem((lpaddr_t) kcb_current);
+
         start_ap_signal();
         // if we have a kernel control block, use it
         if (kcb_current && kcb_current->is_valid) {
index 7f4e2a0..7a8b5c9 100644 (file)
@@ -458,9 +458,6 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
         panic("error while mapping physical memory!");
     }
 
-    kcb_current = (struct kcb *)
-        local_phys_to_mem((lpaddr_t) kcb_current);
-
     /*
      * Also reset the global descriptor table (GDT), so we get
      * segmentation again and can catch interrupts/exceptions (the IDT
@@ -645,9 +642,6 @@ void arch_init(uint64_t magic, void *pointer)
         glbl_core_data->mmap_length = mb->mmap_length;
         glbl_core_data->mmap_addr = mb->mmap_addr;
 
-        extern struct kcb bspkcb;
-        memset(&bspkcb, 0, sizeof(bspkcb));
-        kcb_current = &bspkcb;
     } else { /* No multiboot info, use the core_data struct */
         struct x86_core_data *core_data =
             (struct x86_core_data*)(dest - BASE_PAGE_SIZE);
index f23664c..c60555a 100644 (file)
@@ -25,9 +25,6 @@
 #include <mdb/mdb_tree.h>
 #include <trace/trace.h>
 
-// HACK! Remove and don't reference this, kcb points here in case we're bsp
-// This should be exposed as regular cap.
-struct kcb bspkcb; 
 struct kcb *kcb_current;
 
 coreid_t my_core_id;
@@ -142,10 +139,11 @@ struct dcb *spawn_module(struct spawn_state *st,
 #endif
 
     /* Set up root cnode and the caps it contains */
-    // must be static, because this CTE will be entered into the MDB!
-    // don't want this to be static, as the memory backing the data section of
-    // the kernel can and will disappear when we reboot a core with a
-    // different kernel but want to restore the state
+    // Has to be valid after leaving this stack frame, because this CTE will
+    // be entered into the MDB!
+    // Don't want this to be part of the data section, as the memory backing
+    // the data section of the kernel can and will disappear when we reboot a
+    // core with a different kernel but want to restore the state
     struct cte *rootcn = &kcb_current->init_rootcn;
     mdb_init(kcb_current);
     kcb_current->is_valid = true;
@@ -162,6 +160,21 @@ struct dcb *spawn_module(struct spawn_state *st,
                           rootcn);
     assert(err_is_ok(err));
 
+    // on BSP core: Add BSP KCB to rootcn
+    if (apic_is_bsp()) {
+        // cannot use caps_create_new() here, as that would zero out KCB, so
+        // we replicate the cap initialization here.
+        struct capability bspkcb_cap;
+        memset(&bspkcb_cap, 0, sizeof(struct capability));
+        bspkcb_cap.type = ObjType_KernelControlBlock;
+        bspkcb_cap.rights = CAPRIGHTS_ALLRIGHTS;
+        bspkcb_cap.u.kernelcontrolblock.kcb = kcb_current;
+        // find slot in init rootcn
+        struct cte *bspkcb = caps_locate_slot(CNODE(rootcn), ROOTCN_SLOT_BSPKCB);
+        assert(bspkcb && bspkcb->cap.type == ObjType_Null);
+        memcpy(&bspkcb->cap, &bspkcb_cap, sizeof(struct capability));
+    }
+
     // Task cnode in root cnode
     st->taskcn = caps_locate_slot(CNODE(rootcn), ROOTCN_SLOT_TASKCN);
     err = caps_create_new(ObjType_CNode, alloc_phys(BASE_PAGE_SIZE),
index 9c7e091..009594b 100644 (file)
@@ -53,6 +53,16 @@ errval_t initialize_monitor(struct spawninfo *si)
         return err_push(err, INIT_ERR_COPY_KERNEL_CAP);
     }
 
+    /* Give monitor.0 the BSP KCB capability */
+    dest.cnode = si->rootcn;
+    dest.slot  = ROOTCN_SLOT_BSPKCB;
+    src.cnode = cnode_root;
+    src.slot  = ROOTCN_SLOT_BSPKCB;
+    err = cap_copy(dest, src);
+    if (err_is_fail(err)) {
+        return err_push(err, INIT_ERR_COPY_KERNEL_CAP);
+    }
+
     /* Give monitor the perfmon capability */
     dest.cnode = si->taskcn;
     dest.slot = TASKCN_SLOT_PERF_MON;