clean up and add some flexbility to mapping of APIC IDs and core IDs
authorAndrew Baumann <andrew.baumann@microsoft.com>
Wed, 11 Jan 2012 17:10:45 +0000 (09:10 -0800)
committerAndrew Baumann <andrew.baumann@microsoft.com>
Wed, 11 Jan 2012 17:10:45 +0000 (09:10 -0800)
 * introduced kernel boot parameter to control the core ID for the BSP
   (on x86, where it was always zero)
 * introduced spawnd parameter to allow all core IDs to start from an offset
   (I'm using this for boot on MIC)
 * added monitor API to query the local core's APIC ID (some drivers might need it)
 * fixed some kernel paths that were needlessly reading the APIC ID out of the
   APIC all the time

13 files changed:
if/monitor_blocking.if
kernel/arch/x86/apic.c
kernel/arch/x86/misc.c
kernel/arch/x86/startup_x86.c
kernel/arch/x86_32/init.c
kernel/arch/x86_32/syscall.c
kernel/arch/x86_64/init.c
kernel/arch/x86_64/syscall.c
kernel/include/arch/x86/apic.h
kernel/include/kernel.h
usr/monitor/monitor_rpc_server.c
usr/monitor/spawn.c
usr/spawnd/bsp_bootup.c

index 5ba8236..93744c8 100644 (file)
@@ -49,4 +49,7 @@ interface monitor_blocking "The monitor to client RPC interface" {
 
         /* Allocate local IRQ vector */
         rpc irq_handle(in cap ep, out errval err, out uint32 vector);
+
+        /* Retrieve local arch-specific core ID (e.g. APIC ID on x86)*/
+        rpc get_arch_core_id(out uintptr id);
 };
index c841107..e6137dc 100644 (file)
 #define APIC_PAGE_SIZE          4096
 #define APIC_DEFAULT_PRIORITY   0x0000
 
+/**
+ * The kernel's APIC ID.
+ */
+uint8_t apic_id;
+
+/**
+ * True iff we're on the BSP
+ */
+bool apic_bsp = true;
+
 // global pointers used in init_ap.S
 extern uint64_t x86_64_start_ap;
 extern uint64_t x86_64_init_ap_wait;
 extern uint64_t x86_32_start_ap;
 extern uint64_t x86_32_init_ap_wait;
 
-bool bsp = true;
 static xapic_t apic;
 
 /**
@@ -132,13 +141,14 @@ void apic_init(void)
     xapic_initialize(&apic, (void *)apic_base);
 
 #if !defined(__scc__) || defined(RCK_EMU)
-    debug(SUBSYS_APIC, "APIC ID=%hhu\n", xapic_id_id_rdf(&apic) );
+    apic_id = apic_get_id();
+    debug(SUBSYS_APIC, "APIC ID=%hhu\n", apic_id);
     if (ia32_apic_base_bsp_extract(apic_base_msr)) {
         debug(SUBSYS_APIC, "APIC: bootstrap processor\n");
-        bsp = true;
+        apic_bsp = true;
     } else {
         debug(SUBSYS_APIC, "APIC: application processor\n");
-        bsp = false;
+        apic_bsp = false;
         *ap_wait = AP_STARTED;
     }
 #endif
@@ -405,7 +415,7 @@ void apic_unmask_timer(void)
 
 bool arch_core_is_bsp(void)
 {
-    return bsp;
+    return apic_is_bsp();
 }
 
 xapic_esr_t apic_get_esr(void)
index 96f7908..4c606b5 100644 (file)
@@ -22,7 +22,6 @@
 #include <barrelfish_kpi/cpu.h>
 #include <exec.h>
 #include <misc.h>
-#include <arch/x86/apic.h>
 #include <dispatch.h>
 #include <trace/trace.h>
 
@@ -53,11 +52,6 @@ bool kernel_ticks_enabled = true;
 size_t kernel_now = 0;
 
 /**
- * The kernel's APIC ID.
- */
-uint8_t apic_id;
-
-/**
  * \brief Print a message and halt the kernel.
  *
  * Something irrecoverably bad happened. Print a panic message, then halt.
@@ -71,7 +65,7 @@ void panic(const char *msg, ...)
     vsnprintf(buf, sizeof(buf), msg, ap);
     va_end(ap);
 
-    printf("kernel %d PANIC! %.*s\n", apic_id, (int)sizeof(buf), buf);
+    printf("kernel %d PANIC! %.*s\n", my_core_id, (int)sizeof(buf), buf);
 
     breakpoint();
     halt();
index 98a0ecb..f4059ae 100644 (file)
@@ -38,6 +38,9 @@
 #       include <rck.h>
 #endif
 
+/// Optional core ID to use for the BSP core (command-line argument)
+static int bsp_coreid;
+
 /// Quick way to find the base address of a cnode capability
 #define CNODE(cte)     (cte)->cap.u.cnode.cnode
 
@@ -238,6 +241,7 @@ static struct cmdarg cmdargs[] = {
 #ifndef __scc__ // FIXME: why not?
     {"serial", ArgType_Int, { .integer = &serial_portbase }},
 #endif
+    {"bsp_coreid", ArgType_Int, { .integer = &bsp_coreid }},
     {NULL, 0, {NULL}}
 };
 
@@ -288,6 +292,10 @@ void kernel_startup(void)
     struct dcb *init_dcb;
 
     if (apic_is_bsp()) {
+        if (bsp_coreid != 0) {
+            my_core_id = bsp_coreid;
+        }
+
         /* Initialize the location to allocate phys memory from */
         bsp_init_alloc_addr = glbl_core_data->start_free_ram;
 
index 10adf7b..3394d85 100644 (file)
@@ -574,9 +574,6 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
     // XXX: Set core ID and fake APIC ID to be the tile's core ID
     my_core_id = apic_id = rck_get_coreid();
     printf("My APIC ID: %d\n", apic_id);
-
-#else
-    apic_id = apic_get_id();
 #endif
 
     // do not remove/change this printf: needed by regression harness
index a142857..9bd9a8a 100644 (file)
@@ -308,11 +308,7 @@ static struct sysret monitor_get_arch_id(struct capability *kernel_cap,
 {
     return (struct sysret) {
         .error = SYS_ERR_OK,
-#ifdef __scc__
         .value = apic_id
-#else
-        .value = apic_get_id()
-#endif
     };
 }
 
index 6449e12..3a41041 100644 (file)
@@ -476,7 +476,6 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
 
     // Initialize local APIC
     apic_init();
-    apic_id = apic_get_id();
 
     // do not remove/change this printf: needed by regression harness
     printf("Barrelfish CPU driver starting on x86_64 apic_id %u\n", apic_id);
index bc38932..9ccd680 100644 (file)
@@ -254,7 +254,7 @@ static struct sysret monitor_get_core_id(struct capability *kernel_cap,
 static struct sysret monitor_get_arch_id(struct capability *kernel_cap,
                                          int cmd, uintptr_t *args)
 {
-    return (struct sysret){.error = SYS_ERR_OK, .value = apic_get_id()};
+    return (struct sysret){.error = SYS_ERR_OK, .value = apic_id};
 }
 
 static struct sysret monitor_identify_cap_common(struct capability *kernel_cap,
index 83821b5..7b8d227 100644 (file)
@@ -30,12 +30,12 @@ void apic_send_init_deassert(void);
 void apic_send_start_up(uint8_t destination,
                         uint8_t destination_shorthand,
                         uint8_t realmode_startpage);
-
-extern bool bsp;
+extern uint8_t apic_id;
+extern bool apic_bsp;
 
 static inline bool apic_is_bsp(void)
 {
-    return bsp;
+    return apic_bsp;
 }
 
 void apic_send_std_ipi(uint8_t destination, uint8_t destination_shorthand, uint8_t vector);
index ed8176b..1c15d84 100644 (file)
@@ -189,11 +189,6 @@ extern bool kernel_ticks_enabled;
  */
 extern size_t kernel_now;
 
-/**
- * Processor number (using IAPC terminology).
- */
-extern uint8_t apic_id;
-
 extern lvaddr_t kernel_trace_buf;
 
 extern struct capability monitor_ep;
index 7ef47f4..d20f2ba 100644 (file)
@@ -495,6 +495,21 @@ static void irq_handle_call(struct monitor_blocking_binding *b, struct capref ep
     assert(err_is_ok(err2));
 }
 
+static void get_arch_core_id(struct monitor_blocking_binding *b)
+{
+    static uintptr_t arch_id = -1;
+    errval_t err;
+
+    if (arch_id == -1) {
+        err = invoke_monitor_get_arch_id(&arch_id);
+        assert(err_is_ok(err));
+        assert(arch_id != -1);
+    }
+
+    err = b->tx_vtbl.get_arch_core_id_response(b, NOP_CONT, arch_id);
+    assert(err_is_ok(err));
+}
+
 static void cap_set_remote_done(void *arg)
 {
     struct capref *tmpcap = arg;
@@ -607,6 +622,7 @@ static struct monitor_blocking_rx_vtbl rx_vtbl = {
     .alloc_monitor_ep_call   = alloc_monitor_ep,
     .cap_identify_call       = cap_identify,
     .irq_handle_call         = irq_handle_call,
+    .get_arch_core_id_call   = get_arch_core_id,
 
     .cap_set_remote_call     = cap_set_remote,
 };
index 5a018c1..f79b663 100644 (file)
@@ -247,15 +247,14 @@ errval_t spawn_all_domains(void)
             return err_push(err, SPAWN_ERR_GET_CMDLINE_ARGS);
         }
 
-        // Pass the local arch-specific core ID to the PCI domain
-        if(!strcmp(short_name, "pci")) {
+        // Pass the local arch-specific core ID to the PCI and spawnd domains
+        if(strcmp(short_name, "pci") == 0 || strcmp(short_name, "spawnd") == 0) {
             // Get hardware core ID
             uintptr_t my_arch_id = 0;
             err = invoke_monitor_get_arch_id(&my_arch_id);
             assert(err_is_ok(err));
 
             char *myargs = malloc(strlen(args) + 50);
-            strcpy(myargs, args);
             snprintf(myargs, strlen(args) + 50, "%s apicid=%" PRIuPTR,
                      args, my_arch_id);
             free(args);
index ac5ef33..cf3fc3f 100644 (file)
 
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 
-struct mapping {
+struct coreid_mapping {
     int arch_id;
     bool present;
 };
 
-static struct mapping mappings[MAX_CPUS];
-static int num_cores = 0;
+static struct coreid_mapping coreid_mappings[MAX_COREID + 1];
+static coreid_t coreid_offset;
+
 static const char *kernel_cmdline;
 
 static void state_machine(void);
@@ -119,34 +120,23 @@ static void state_machine(void)
         // Fall through
 
     case 1: { // Boot all present cores
-        static int mapping_index = 0;
+        static int coreid = 0;
 
-        while (1) {
-            if (mapping_index == MAX_CPUS) {
-                break;
-            }
-            if (!mappings[mapping_index].present) {
-                mapping_index++;
-                continue;
-            }
-            if (mapping_index == my_core_id) {
-                mapping_index++;
-                continue;
-            }
-            break;
+        // find next core to boot
+        while (coreid <= MAX_COREID
+               && (coreid == my_core_id || !coreid_mappings[coreid].present)) {
+            coreid++;
         }
 
-        if (mapping_index != MAX_CPUS) {
-            err = mb->tx_vtbl.boot_core_request(mb, NOP_CONT, mapping_index,
-                                                mappings[mapping_index].arch_id,
-                                                CURRENT_CPU_TYPE,
-                                                kernel_cmdline);
+        if (coreid <= MAX_COREID) {
+            err = mb->tx_vtbl.boot_core_request(mb, NOP_CONT, coreid,
+                                                coreid_mappings[coreid].arch_id,
+                                                CURRENT_CPU_TYPE, kernel_cmdline);
             if (err_is_fail(err)) {
                 USER_PANIC_ERR(err, "sending boot core request");
             }
 
-            mapping_index++;
-            break;
+            coreid++;
         } else { // Send boot_initialize_request message
             err = mb->tx_vtbl.boot_initialize_request(mb, NOP_CONT);
             if (err_is_fail(err)) {
@@ -154,14 +144,15 @@ static void state_machine(void)
             }
 
             state_id++;
-            break;
         }
+
+        break;
     }
 
     case 2: { // wait for all spawnd's to come up
 
-        for (coreid_t c = 0; c < MAX_CPUS; c++) {
-            if (mappings[c].present && c != my_core_id) {
+        for (uintptr_t c = 0; c <= MAX_COREID; c++) {
+            if (coreid_mappings[c].present && c != my_core_id) {
                 err = nsb_wait_n(c, SERVICE_BASENAME);
                 if (err_is_fail(err)) {
                     USER_PANIC_ERR(err, "nameservice barrier wait for %s.%d",
@@ -193,22 +184,43 @@ static void state_machine(void)
 
 /* -------------------------- MAIN ------------------------------- */
 
-static void set_skb_present(char *str)
+static void mappings_from_skb(uintptr_t my_arch_id, char *str)
 {
+    // insert mapping for self
+    coreid_mappings[my_core_id].arch_id = my_arch_id;
+    coreid_mappings[my_core_id].present = true;
+
+    coreid_t n = 0;
+    if (n == my_core_id) {
+        n++;
+    }
+
     while (*str != '\0') {
         if (!isdigit(*str)) {
             str++;
             continue;
         }
-        mappings[num_cores].arch_id = strtol(str, &str, 10);
-        mappings[num_cores].present = true;
-        num_cores++;
+        uintptr_t arch_id = strtol(str, &str, 10);
+        if (arch_id != my_arch_id) {
+            coreid_mappings[n].arch_id = arch_id;
+            coreid_mappings[n].present = true;
+            if (++n == my_core_id) {
+                n++;
+            }
+        }
     }
 }
 
-static void set_cmdline_present(const char *str)
+static void mappings_from_cmdline(uintptr_t my_arch_id, const char *str)
 {
-    num_cores = 1; // include self
+    // insert mapping for self
+    coreid_mappings[my_core_id].arch_id = my_arch_id;
+    coreid_mappings[my_core_id].present = true;
+
+    coreid_t next = coreid_offset;
+    if (next == my_core_id) {
+        next++;
+    }
 
     char *p = strchr(str, '=');
     assert(p != NULL);
@@ -225,13 +237,15 @@ static void set_cmdline_present(const char *str)
         }
         for(int i = id_from; i <= id_to; i++) {
             if (CURRENT_CPU_TYPE == CPU_BEEHIVE) {
-                mappings[i].arch_id = i;
-                mappings[i].present = true;
-                num_cores++;
-            } else {
-                mappings[num_cores].arch_id = i;
-                mappings[num_cores].present = true;
-                num_cores++;
+                coreid_mappings[i].arch_id = i;
+                coreid_mappings[i].present = true;
+            } else if (i != my_arch_id) {
+                assert(next <= MAX_COREID);
+                coreid_mappings[next].arch_id = i;
+                coreid_mappings[next].present = true;
+                if (++next == my_core_id) {
+                    next++;
+                }
             }
         }
     }
@@ -239,6 +253,8 @@ static void set_cmdline_present(const char *str)
 
 void bsp_bootup(const char *bootmodules, int argc, const char *argv[])
 {
+    const char *cmdline_mappings = NULL;
+    uintptr_t my_arch_id = 0;
     errval_t err;
 
     // Find kernel cmdline
@@ -247,41 +263,37 @@ void bsp_bootup(const char *bootmodules, int argc, const char *argv[])
         USER_PANIC_ERR(err, "invalid kernel cmdline");
     }
 
-    bool use_skb = true;
+    /* This is all a bit silly. We do not yet support heterogeneous systems so
+       only one cmdline arg is expected, but in anticipation of that, we
+       support passing different names for that argument. */
     for (int i = 1; i < argc; i++) {
         if(!strncmp(argv[i],"bootapic-x86_64=",strlen("bootapic-x86_64="))) {
-            use_skb = false;
-            set_cmdline_present(argv[i]);
-            break; // XXX: We do not yet support heterogeneous systems so only one cmdline arg is expected
-        }
-        if(!strncmp(argv[i],"bootapic-x86_32=",strlen("bootapic-x86_32="))) {
-            use_skb = false;
-            set_cmdline_present(argv[i]);
-            break; // XXX: We do not yet support heterogeneous systems so only one cmdline arg is expected
-        }
-        if(!strncmp(argv[i],"bootscc=",strlen("bootscc="))) {
-            use_skb = false;
-            set_cmdline_present(argv[i]);
-            break; // XXX: We do not yet support heterogeneous systems so only one cmdline arg is expected
+            cmdline_mappings = argv[i];
+        } else if(!strncmp(argv[i],"bootapic-x86_32=",strlen("bootapic-x86_32="))) {
+            cmdline_mappings = argv[i];
+        } else if(!strncmp(argv[i],"bootscc=",strlen("bootscc="))) {
+            cmdline_mappings = argv[i];
+        } else if(!strncmp(argv[i],"bootbees=",strlen("bootbees="))) {
+            cmdline_mappings = argv[i];
+        } else if(!strcmp(argv[i],"bootarm")) {
+            cmdline_mappings = argv[i];
+        } else if (strncmp(argv[i], "coreid_offset=", sizeof("coreid_offset")) == 0) {
+            coreid_offset = strtol(argv[i] + sizeof("coreid_offset"), NULL, 10);
+        } else if (strncmp(argv[i], "apicid=", sizeof("apicid")) == 0) {
+            my_arch_id = strtol(argv[i] + sizeof("apicid"), NULL, 10);
+        } else if(!strcmp(argv[i],"boot")) {
+            // ignored
+        } else {
+            debug_printf("Invalid arg (%s) or architecture not supported.\n",
+                         argv[i]);
+            abort();
         }
-        if(!strncmp(argv[i],"bootbees=",strlen("bootbees="))) {
-            use_skb = false;
-            set_cmdline_present(argv[i]);
-            break; // XXX: We do not yet support heterogeneous systems so only one cmdline arg is expected
-        }
-        if(!strcmp(argv[i],"bootarm")) {
-            use_skb = false;
-            break; // XXX: We do not yet support heterogeneous systems so only one cmdline arg is expected
-        }
-        if(!strcmp(argv[i],"boot")) {
-            continue;
-        }
-        debug_printf("Invalid arg (%s) or architecture not supported.\n",
-               argv[i]);
-        abort();
     }
 
-    if (use_skb) {
+    if (cmdline_mappings != NULL) {
+        mappings_from_cmdline(my_arch_id, cmdline_mappings);
+    } else {
+        // Use SKB to boot all cores
         err = skb_client_connect();
         if (err_is_fail(err)) {
             USER_PANIC_ERR(err, "skb_client_connect failed");
@@ -306,18 +318,18 @@ void bsp_bootup(const char *bootmodules, int argc, const char *argv[])
         if (err_is_fail(err)) {
             USER_PANIC_ERR(err, "skb_evaluate failed");
         }
-        set_skb_present(result);
+        mappings_from_skb(my_arch_id, result);
         free(result);
         free(str_err);
 
-        /* Add the mapping to the skb */
-        for (int i = 0; i < MAX_CPUS; i++) {
-            if (!mappings[i].present) {
+        /* Add the mappings to the skb */
+        for (int i = 0; i <= MAX_COREID; i++) {
+            if (!coreid_mappings[i].present) {
                 continue;
             }
 
             err = skb_add_fact("corename(%d, x86_64, apic(%d)).",
-                               i, mappings[i].arch_id);
+                               i, coreid_mappings[i].arch_id);
             if (err_is_fail(err)) {
                 USER_PANIC_ERR(err, "failed to add core mapping to skb");
             }
@@ -333,9 +345,10 @@ void bsp_bootup(const char *bootmodules, int argc, const char *argv[])
 
     }
 
-    for (int i = 0; i < MAX_CPUS; i++) {
-        if (mappings[i].present) {
-            debug_printf("coreid %d is arch id %d\n", i, mappings[i].arch_id);
+    for (int i = 0; i <= MAX_COREID; i++) {
+        if (coreid_mappings[i].present) {
+            debug_printf("coreid %d is arch id %d\n", i,
+                         coreid_mappings[i].arch_id);
         }
     }