Integrating coreboot for 32bit.
authorGerd Zellweger <mail@gerdzellweger.com>
Wed, 5 Nov 2014 15:39:41 +0000 (16:39 +0100)
committerGerd Zellweger <mail@gerdzellweger.com>
Wed, 5 Nov 2014 15:40:08 +0000 (16:40 +0100)
14 files changed:
include/arch/x86_32/barrelfish/invocations_arch.h
kernel/arch/x86/startup_x86.c
kernel/arch/x86_32/exec.c
kernel/arch/x86_32/init.c
kernel/arch/x86_32/irq.c
kernel/arch/x86_32/syscall.c
kernel/include/arch/x86_32/irq.h
kernel/include/kcb.h
kernel/schedule_rbed.c
kernel/startup.c
lib/barrelfish/arch/x86_32/dispatch.c
lib/barrelfish/arch/x86_32/syscalls.c
usr/monitor/include/arch/x86_32/monitor_invocations.h
usr/monitor/inter.c

index 2fea7fe..de60d6f 100644 (file)
@@ -427,6 +427,22 @@ static inline errval_t invoke_dispatcher_setup_guest(struct capref dispatcher,
     return LIB_ERR_NOT_IMPLEMENTED;
 }
 
+static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
+{
+    uint8_t invoke_bits = get_cap_valid_bits(irqcap);
+    capaddr_t invoke_cptr = get_cap_addr(irqcap) >> (CPTR_BITS - invoke_bits);
+
+    struct sysret ret = syscall2(
+                    (invoke_bits << 16) | (IRQTableCmd_Alloc << 8) | SYSCALL_INVOKE, 
+                    invoke_cptr);
+    if (err_is_ok(ret.error)) {
+        *retirq = ret.value;
+    } else {
+        *retirq = 0;
+    }
+    return ret.error;
+}
+
 static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq,
                                            struct capref ep)
 {
@@ -564,7 +580,6 @@ static inline errval_t invoke_idcap_identify(struct capref idcap,
                                              idcap_id_t *id)
 {
     assert(id != NULL);
-
     uint8_t invoke_bits = get_cap_valid_bits(idcap);
     capaddr_t invoke_cptr = get_cap_addr(idcap) >> (CPTR_BITS - invoke_bits);
 
@@ -575,3 +590,38 @@ static inline errval_t invoke_idcap_identify(struct capref idcap,
 
     return sysret.error;
 }
+
+static inline errval_t invoke_send_init_ipi(struct capref kernel_cap, coreid_t core_id)
+{
+    uint8_t invoke_bits = get_cap_valid_bits(kernel_cap);
+    capaddr_t invoke_cptr = get_cap_addr(kernel_cap) >> (CPTR_BITS - invoke_bits);
+
+    return
+        syscall3((invoke_bits << 16) | (KernelCmd_Init_IPI_Send << 8) | SYSCALL_INVOKE,
+                 invoke_cptr, (uintptr_t) core_id).error;
+}
+
+static inline errval_t invoke_send_start_ipi(struct capref kernel_cap, coreid_t core_id, forvaddr_t entry)
+{
+    uint8_t invoke_bits = get_cap_valid_bits(kernel_cap);
+    capaddr_t invoke_cptr = get_cap_addr(kernel_cap) >> (CPTR_BITS - invoke_bits);
+
+    return
+        syscall4((invoke_bits << 16) | (KernelCmd_Start_IPI_Send << 8) | SYSCALL_INVOKE,
+                 invoke_cptr, (uintptr_t) core_id, (uintptr_t) entry).error;
+
+}
+
+static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global)
+{ 
+    uint8_t invoke_bits = get_cap_valid_bits(kernel_cap);
+    capaddr_t invoke_cptr = get_cap_addr(kernel_cap) >> (CPTR_BITS - invoke_bits);
+
+    struct sysret sr = syscall2((invoke_bits << 16) | (KernelCmd_GetGlobalPhys << 8) | SYSCALL_INVOKE,
+             invoke_cptr);
+    if (err_is_ok(sr.error)) {
+        *global = sr.value;
+    }
+
+    return sr.error;
+}
\ No newline at end of file
index 424618f..3ebb949 100644 (file)
@@ -550,18 +550,15 @@ void kernel_startup(void)
         bsp_init_alloc_addr = glbl_core_data->start_free_ram;
 
         /* spawn init */
-    init_dcb = spawn_bsp_init(BSP_INIT_MODULE_PATH, bsp_alloc_phys);
+        init_dcb = spawn_bsp_init(BSP_INIT_MODULE_PATH, bsp_alloc_phys);
     } else {
         // if we have a kernel control block, use it
         if (kcb_current && kcb_current->is_valid) {
             debug(SUBSYS_STARTUP, "have valid kcb, restoring state\n");
-            assert(kcb_current == kcb_home);
-            //kernel_loglevel = 5;
-
             print_kcb();
-            errval_t err;
+
             // restore mdb
-            err = mdb_init(kcb_current);
+            errval_t err = mdb_init(kcb_current);
             if (err_is_fail(err)) {
                 panic("couldn't restore mdb");
             }
index 335f5bd..9fcdac3 100644 (file)
@@ -206,10 +206,6 @@ void __attribute__ ((noreturn)) wait_for_interrupt(void)
  *
  * Returns when the 64-bit word at base is not equal to lastval.
  */
-// TODO XXX: Where should this propotype live?
-void monitor_mwait(lvaddr_t base, uint64_t lastval, uint32_t extensions,
-                   uint32_t hints);
-
 void monitor_mwait(lvaddr_t base, uint64_t lastval, uint32_t extensions,
                    uint32_t hints)
 {
index a9a6643..33925df 100644 (file)
@@ -41,6 +41,9 @@
 #include <target/x86/barrelfish_kpi/coredata_target.h>
 #include <arch/x86/timing.h>
 #include <arch/x86/startup_x86.h>
+#include <arch/x86/start_aps.h>
+#include <coreboot.h>
+#include <kcb.h>
 
 #include "xapic_dev.h" // XXX
 
@@ -540,6 +543,9 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
     conio_relocate_vidmem(local_phys_to_mem(VIDEO_MEM));
 #endif
 
+    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
@@ -551,7 +557,7 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
     kernel_startup_early();
 
     // XXX: re-init the serial driver, in case the port changed after parsing args
-    serial_console_init();
+    serial_console_init(false);
 
     // Setup IDT
     setup_default_idt();
@@ -627,7 +633,7 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
 #endif
 
     /* Register start handler for other cores in the system */
-    set_spawn_core_handler(CPU_X86_64, start_aps_x86_32_start);
+    coreboot_set_spawn_handler(CPU_X86_32, start_aps_x86_32_start);
 
     // Call main kernel startup function -- this should never return
     kernel_startup();
@@ -674,7 +680,9 @@ void arch_init(uint32_t magic, void *pointer)
 #ifndef __scc__
     conio_cls();
 #endif
-    serial_console_init();
+    // Initialize serial, only initialize HW if we are
+    // the first kernel
+    serial_console_init((magic == MULTIBOOT_INFO_MAGIC));
 
     /* determine page-aligned physical address past end of multiboot */
     lvaddr_t dest = (lvaddr_t)&_start_kernel;
@@ -720,6 +728,10 @@ void arch_init(uint32_t magic, void *pointer)
             glbl_core_data->cmdline = mb->cmdline;
             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;
         }
         break;
 
@@ -754,6 +766,7 @@ void arch_init(uint32_t magic, void *pointer)
         glbl_core_data = core_data;
         glbl_core_data->cmdline = (lpaddr_t)&core_data->kernel_cmdline;
         my_core_id = core_data->dst_core_id;
+        kcb_current = (struct kcb*) (lpaddr_t)glbl_core_data->kcb;
         elf = &core_data->elf;
         break;
 
index 3cb8ebb..ca9021a 100644 (file)
@@ -67,6 +67,8 @@
 #include <arch/x86/timing.h>
 #include <arch/x86/syscall.h>
 #include <barrelfish_kpi/cpu_arch.h>
+#include <kcb.h>
+#include <mdb/mdb_tree.h>
 
 #ifdef FPU_LAZY_CONTEXT_SWITCH
 #  include <fpu.h>
@@ -340,18 +342,15 @@ HW_EXCEPTION_NOERR(666);
 #define ERR_PF_RESERVED         (1 << 3)
 #define ERR_PF_INSTRUCTION      (1 << 4)
 
-/// Number of (reserved) hardware exceptions
-#define NEXCEPTIONS             32
-
-/// Size of hardware IRQ dispatch table == #NIDT - #NEXCEPTIONS exceptions
-#define NDISPATCH               (NIDT - NEXCEPTIONS)
-
 /**
  * \brief Interrupt Descriptor Table (IDT) for processor this kernel is running
  * on.
  */
 static struct gate_descriptor idt[NIDT] __attribute__ ((aligned (16)));
 
+// this is used to pin a kcb for critical sections
+bool kcb_sched_suspended = false;
+
 /**
  * \brief User-space IRQ dispatch table.
  *
@@ -409,6 +408,34 @@ static void send_user_interrupt(int irq)
 #endif
 }
 
+errval_t irq_table_alloc(int *outvec)
+{
+    assert(outvec);
+    // XXX: this is O(#kcb*NDISPATCH)
+    int i;
+    for (i = 0; i < NDISPATCH; i++) {
+        struct kcb *k = kcb_current;
+        bool found_free = true;
+        do {
+            if (kcb_current->irq_dispatch[i].cap.type == ObjType_EndPoint) {
+                found_free = false;
+                break;
+            }
+            k=k->next?k->next:k;
+        } while(k != kcb_current);
+        if (found_free) {
+            break;
+        }
+    }
+    if (i == NDISPATCH) {
+        *outvec = -1;
+        return SYS_ERR_IRQ_NO_FREE_VECTOR;
+    } else {
+        *outvec = i;
+        return SYS_ERR_OK;
+    }
+}
+
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
 {
     errval_t err;
index afd1a2a..1988470 100644 (file)
@@ -619,6 +619,16 @@ static struct sysret handle_trace_setup(struct capability *cap,
     return SYSRET(SYS_ERR_OK);
 }
 
+static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    struct sysret ret;
+    int outvec;
+    ret.error = irq_table_alloc(&outvec);
+    ret.value = outvec;
+    return ret;
+}
+
 static struct sysret handle_irq_table_set(struct capability *to, int cmd, uintptr_t *args)
 {
     return SYSRET(irq_table_set(args[0], args[1]));
@@ -783,6 +793,7 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
 #endif
     },
     [ObjType_IRQTable] = {
+        [IRQTableCmd_Alloc] = handle_irq_table_alloc,
         [IRQTableCmd_Set] = handle_irq_table_set,
         [IRQTableCmd_Delete] = handle_irq_table_delete
     },
index 0611c4f..7ee5997 100644 (file)
@@ -116,6 +116,13 @@ struct  gate_descriptor {
  */
 #define NIDT    256             /* 32 reserved, 16 h/w, 0 s/w, linux's 0x80 */
 
+/// Number of (reserved) hardware exceptions
+#define NEXCEPTIONS             32
+
+/// Size of hardware IRQ dispatch table == #NIDT - #NEXCEPTIONS exceptions
+#define NDISPATCH               (NIDT - NEXCEPTIONS)
+
+
 /*
  * Entries in the Global Descriptor Table (GDT)
  */
@@ -203,6 +210,7 @@ struct task_state_segment {
 
 void setup_default_idt(void);
 
+errval_t irq_table_alloc(int *outvec);
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint);
 errval_t irq_table_delete(unsigned int nidt);
 
index cd3b91c..654067c 100644 (file)
@@ -66,7 +66,7 @@ struct kcb {
     //driver whose kernel_now > this kcb's kernel_off.
     int64_t kernel_off;
 
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__i386__)
     struct cte irq_dispatch[NDISPATCH];
 #endif
     // TODO: maybe add a shared part which can replace struct core_data?
@@ -74,8 +74,6 @@ struct kcb {
 
 ///< The kernel control block
 extern struct kcb *kcb_current;
-///< The home kernel control block, interrupts get handled based on this kcb
-extern struct kcb *kcb_home;
 ///< flag that indicates whether kcb scheduling should happen
 extern bool kcb_sched_suspended;
 
index b8d0748..291504a 100644 (file)
@@ -306,13 +306,6 @@ struct dcb *schedule(void)
 
     // Update executed time of last dispatched task
     if(lastdisp != NULL) {
-<<<<<<< HEAD
-        if (lastdisp->last_dispatch > kernel_now) {
-            printf("%s:%s:%d: lastdisp->last_dispatch(%lu) <= kernel_now(%zu)\n",
-                   __FILE__, __FUNCTION__, __LINE__, lastdisp->last_dispatch, kernel_now);
-        }
-=======
->>>>>>> 5e70008... Remove print statement in rbed.
         assert(lastdisp->last_dispatch <= kernel_now);
         if(lastdisp->release_time <= kernel_now) {
             lastdisp->etime += kernel_now -
@@ -331,7 +324,7 @@ struct dcb *schedule(void)
         } \
         struct dispatcher_shared_generic *dst = \
             get_dispatcher_shared_generic(d->disp); \
-        debug(SUBSYS_DISPATCH, "looking at '%s', release_time=%zu, kernel_now=%zu\n", \
+        debug(SUBSYS_DISPATCH, "looking at '%s', release_time=%lu, kernel_now=%zu\n", \
                 dst->name, d->release_time, kernel_now); \
     }while(0)
 
index 564fded..3125586 100644 (file)
@@ -28,7 +28,6 @@
 struct cte bspkcbcap;
 struct kcb bspkcb; ///< HACK! Remove and don't reference this, kcb points here in case we're bsp
 struct kcb *kcb_current;
-struct kcb *kcb_home;
 
 coreid_t my_core_id;
 
index 245b817..024e706 100644 (file)
@@ -244,3 +244,56 @@ void disp_save(dispatcher_handle_t handle, arch_registers_state_t *state,
 
     __asm volatile ("save_resume:");
 }
+
+
+/**
+ * \brief Save register state, remove our KCB from current CPU.
+ */
+void disp_save_rm_kcb(void)
+{
+    dispatcher_handle_t handle = disp_disable();
+    struct dispatcher_shared_generic *disp =
+        get_dispatcher_shared_generic(handle);
+    arch_registers_state_t *state =
+        dispatcher_get_enabled_save_area(handle);
+    assert_disabled(disp->disabled);
+
+    struct registers_x86_32 *regs = state;
+
+    // Save resume IP, stack and control registers
+    // See disp_switch above for details
+    // XXX: Using the clobber list here to make the compiler save only
+    // used registers. Be very careful when changing the code below
+    // this asm block! If registers in the clobber list are
+    // subsequently used, they won't be restored at save_resume.
+    __asm volatile ("movl       %%ebp,  6*4(%[regs])    \n\t"
+                    "movl       %%esp,  7*4(%[regs])    \n\t"
+                    // XXX: This is not PIC! - Need to fix
+                    "lea        save_rm_kcb_resume, %%ecx      \n\t"
+                    "movl       %%ecx,  8*4(%[regs])    \n\t"   // EIP
+                    "pushfl                             \n\t"
+                    "popl       9*4(%[regs])            \n\t"   // EFLAGS
+                    "movl       %%cs, %%ecx             \n\t"
+                    "movl       %%ecx, 10*4(%[regs])    \n\t"   // CS
+                    "movl       %%ss, %%ecx             \n\t"
+                    "movl       %%ecx, 11*4(%[regs])    \n\t"   // SS
+                    "mov        %%fs, %[fs]             \n\t"
+                    "mov        %%gs, %[gs]             \n\t"
+                    :
+                    : [regs] "a" (regs),
+                      [fs] "m" (regs->fs),
+                      [gs] "m" (regs->gs)
+                    : "ecx", "edx", "esi", "edi"
+                    );
+
+    // don't halt but remove kcb of this domain
+    sys_suspend(false);
+
+    // this code won't run if the yield succeeded
+
+    // enter thread scheduler again
+    // this doesn't return, and will call disp_yield if there's nothing to do
+    thread_run_disabled(handle);
+
+    __asm volatile ("save_rm_kcb_resume:");
+}
index d60c0dd..341113e 100644 (file)
@@ -28,6 +28,11 @@ errval_t sys_yield(capaddr_t target)
     return syscall3(SYSCALL_YIELD, target, yield_timeslices).error;
 }
 
+errval_t sys_suspend(bool halt)
+{
+    return syscall2(SYSCALL_SUSPEND, halt).error;
+}
+
 errval_t sys_print(const char *string, size_t length)
 {
     return syscall3(SYSCALL_PRINT, (uintptr_t)string, length).error;
index e55ab93..711f789 100644 (file)
@@ -255,6 +255,42 @@ static inline errval_t invoke_monitor_sync_timer(uint64_t synctime)
                     synctime & 0xffffffff).error;
 }
 
+static inline errval_t
+invoke_monitor_add_kcb(uintptr_t kcb_base)
+{
+    assert(kcb_base);
+    uint8_t invoke_bits = get_cap_valid_bits(cap_kernel);
+    capaddr_t invoke_cptr = get_cap_addr(cap_kernel) >> (CPTR_BITS - invoke_bits);
+
+    return syscall3((invoke_bits << 16) | (KernelCmd_Add_kcb << 8) | SYSCALL_INVOKE,
+                    invoke_cptr,
+                    kcb_base).error;
+}
+
+static inline errval_t
+invoke_monitor_remove_kcb(uintptr_t kcb_base)
+{
+    assert(kcb_base);
+
+    uint8_t invoke_bits = get_cap_valid_bits(cap_kernel);
+    capaddr_t invoke_cptr = get_cap_addr(cap_kernel) >> (CPTR_BITS - invoke_bits);
+
+    return syscall3((invoke_bits << 16) | (KernelCmd_Remove_kcb << 8) | SYSCALL_INVOKE,
+                    invoke_cptr,
+                    kcb_base).error;
+}
+
+static inline errval_t
+invoke_monitor_suspend_kcb_scheduler(bool suspend)
+{
+    uint8_t invoke_bits = get_cap_valid_bits(cap_kernel);
+    capaddr_t invoke_cptr = get_cap_addr(cap_kernel) >> (CPTR_BITS - invoke_bits);
+
+    return syscall3((invoke_bits << 16) | (KernelCmd_Suspend_kcb_sched << 8) | SYSCALL_INVOKE,
+                    invoke_cptr,
+                    suspend).error;
+}
+
 #ifdef __scc__
 static inline errval_t invoke_monitor_spawn_scc_core(uint8_t id,
                                                      genpaddr_t urpcframe_base,
index 19a9ea8..d47c32a 100644 (file)
@@ -13,7 +13,6 @@
  * If you do not find this file, copies can be found by writing to:
  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
  */
-#pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <inttypes.h>
 #include "monitor.h"
@@ -665,41 +664,6 @@ static void spawnd_image_request(struct intermon_binding *b)
     assert(err_is_ok(err));
 }
 
-static void stop_core(void* arg)
-{
-    //printf("%s:%s:%d: execute stop core\n",
-    //       __FILE__, __FUNCTION__, __LINE__);
-
-    //errval_t err = invoke_monitor_stop_core();
-    /*if (err_is_fail(err)) {
-        DEBUG_ERR(err, "Can not stop the core.");
-    }*/
-    disp_save_suspend();
-
-    //printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
-
-    struct intermon_binding *b = (struct intermon_binding *) arg;
-    errval_t err = b->tx_vtbl.monitor_initialized(b, NOP_CONT);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "sending boot_core_reply failed");
-    }
-    //printf("%s:%s:%d: \n", __FILE__, __FUNCTION__, __LINE__);
-}
-
-static void power_down_request(struct intermon_binding *b)
-{
-    errval_t err;
-    //printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
-
-    err = b->tx_vtbl.power_down_response(b, MKCONT(stop_core, b));
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Sending response failed.");
-    }
-
-    //printf("%s:%s:%d woken up again...\n", __FILE__, __FUNCTION__, __LINE__);
-    //USER_PANIC("Return from power down request?");
-}
-
 static void give_kcb_request(struct intermon_binding *b, intermon_caprep_t kcb_rep)
 {
     errval_t err;
@@ -777,20 +741,6 @@ static void forward_kcb_rm_response(struct intermon_binding *b, errval_t error)
     mb->tx_vtbl.forward_kcb_rm_request_response(mb, NOP_CONT, error);
 }
 
-extern struct monitor_binding* cpuboot_driver;
-
-static void power_down_response(struct intermon_binding* b)
-{
-    //printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
-    errval_t err;
-    err = cpuboot_driver->tx_vtbl.power_down_response(cpuboot_driver, NOP_CONT, 1);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "cpuboot driver failed.");
-    }
-
-}
-
-
 static struct intermon_rx_vtbl the_intermon_vtable = {
     .trace_caps_request = trace_caps_request,
     .trace_caps_reply = trace_caps_reply,
@@ -819,9 +769,6 @@ static struct intermon_rx_vtbl the_intermon_vtable = {
     .rsrc_phase                = inter_rsrc_phase,
     .rsrc_phase_data           = inter_rsrc_phase_data,
 
-    .power_down_request = power_down_request,
-    .power_down_response = power_down_response,
-
     .give_kcb_request = give_kcb_request,
     .give_kcb_response = give_kcb_response,