Added functionality to start PCI driver to Kaluga.
authorGerd Zellweger <zgerd@student.ethz.ch>
Wed, 29 Feb 2012 23:43:11 +0000 (00:43 +0100)
committerGerd Zellweger <zgerd@student.ethz.ch>
Wed, 29 Feb 2012 23:43:11 +0000 (00:43 +0100)
--HG--
rename : usr/kaluga/app_cores.c => usr/kaluga/start_cpu.c

12 files changed:
usr/kaluga/Hakefile
usr/kaluga/boot_modules.c
usr/kaluga/common.c [new file with mode: 0644]
usr/kaluga/debug.h
usr/kaluga/kaluga.h
usr/kaluga/main.c
usr/kaluga/start_cpu.c [new file with mode: 0644]
usr/kaluga/start_pci.c [new file with mode: 0644]
usr/kaluga/start_pci_driver.c [new file with mode: 0644]
usr/pci/pci.c
usr/skb/programs/device_db.pl
usr/startd/spawn.c

index a59b481..538722f 100644 (file)
 --------------------------------------------------------------------------
 
 [ build application { target = "kaluga",
-                             cFiles = [ "main.c", "queue.c", "app_cores.c", "boot_modules.c" ],
-                             flounderDefs = [ "monitor" ],
-                             flounderBindings = [ "dist2" ],
-                             addLibraries = [ "skb", "dist2", "dist_parser", 
-                                              "thc", "vfs", "nfs", "ahci", "lwip",
+                      cFiles = [ "main.c", "queue.c", "boot_modules.c", "common.c",
+                                 "start_cpu.c", "start_pci.c", "start_pci_driver.c" ],
+                         flounderDefs = [ "monitor" ],
+                      flounderBindings = [ "dist2" ],
+                      addLibraries = [ "skb", "dist2", "dist_parser", 
+                                       "thc", "vfs", "nfs", "ahci", "lwip",
                                        "contmng", "procon", "hashtable", 
                                        "spawndomain", "elf", "trace" ] }
 ]
index 1cab525..e6ce1e5 100644 (file)
 
 #define MAX_DRIVER_MODULES 128
 
-struct module_info {
-    char* complete_line;
-    char* path;
-    char* binary;
+static struct module_info modules[MAX_DRIVER_MODULES];
 
-    char* cmdargs; // Used for pointers in argv
-    int argc;
-    char* argv[MAX_CMDLINE_ARGS + 1];
-};
+inline bool is_auto_driver(struct module_info* mi) {
+    return strcmp(mi->argv[1], "auto") == 0;
+}
 
-static struct module_info boot_modules[MAX_DRIVER_MODULES];
+struct module_info* find_module(char *binary)
+{
+    assert(binary != NULL);
+    bool found = false;
+    struct module_info* si = NULL;
+
+    for (size_t i=0; i< MAX_DRIVER_MODULES; i++) {
+        si = &modules[i];
+        if (si->binary != NULL && strcmp(si->binary, binary) == 0) {
+            found = true;
+            break;
+        }
+    }
+
+    return (found) ? si : NULL;
+}
 
 static void parse_module(char* line, struct module_info* si)
 {
@@ -41,6 +52,7 @@ static void parse_module(char* line, struct module_info* si)
 
     char* binary_start = strrchr(si->path, '/');
     si->binary = strdup(binary_start+1); // exclude /
+    si->did = 0;
 
     char* cmdstart = line + path_size - strlen(si->binary);
     si->cmdargs = strdup(cmdstart);
@@ -64,7 +76,7 @@ static errval_t parse_modules(char* bootmodules)
     char* line = strtok(bm, delim);
 
     while (line != NULL && entry < MAX_DRIVER_MODULES) {
-        struct module_info* si = &boot_modules[entry++];
+        struct module_info* si = &modules[entry++];
         parse_module(line, si);
         KALUGA_DEBUG("found boot module:\n%s\n%s\n%s (%d)\n", si->binary, si->path, si->cmdargs, si->argc);
 
diff --git a/usr/kaluga/common.c b/usr/kaluga/common.c
new file mode 100644 (file)
index 0000000..1cd9f35
--- /dev/null
@@ -0,0 +1,64 @@
+#include <barrelfish/barrelfish.h>
+#include <dist2/dist2.h>
+
+#include "kaluga.h"
+
+errval_t trigger_existing_and_watch(const char* query,
+        trigger_handler_fn event_handler,  dist2_trigger_id_t* tid)
+{
+    errval_t error_code;
+    char** names = NULL;
+    char* output = NULL;
+    char* record = NULL; // freed by cpu_change_event
+    size_t len = 0;
+    dist2_trigger_t t = dist_mktrigger(SYS_ERR_OK, dist2_BINDING_EVENT,
+            TRIGGER_ALWAYS, event_handler, NULL);
+
+    // Get current cores registered in system
+    struct dist2_thc_client_binding_t* rpc = dist_get_thc_client();
+    errval_t err = rpc->call_seq.get_names(rpc, query,
+            t, &output, tid, &error_code);
+    if (err_is_fail(err)) {
+        goto out;
+    }
+    err = error_code;
+
+    switch(err_no(err)) {
+    case SYS_ERR_OK:
+        err = dist_parse_names(output, &names, &len);
+        if (err_is_fail(err)) {
+            goto out;
+        }
+
+        for (size_t i=0; i < len; i++) {
+            KALUGA_DEBUG("get record for name:%s\n", names[i]);
+            err = dist_get(&record, names[i]);
+
+            switch (err_no(err)) {
+            case SYS_ERR_OK:
+                event_handler(DIST_ON_SET, record, NULL);
+                break;
+
+            case DIST2_ERR_NO_RECORD:
+                assert(record == NULL);
+                break;
+
+            default:
+                DEBUG_ERR(err, "Unable to retrieve core record for %s", names[i]);
+                assert(record == NULL);
+                break;
+            }
+        }
+        break;
+
+    default:
+        // Do nothing (wait for trigger)
+        break;
+    }
+
+out:
+    dist_free_names(names, len);
+    free(output);
+
+    return err;
+}
index 3980836..4e6255e 100644 (file)
@@ -18,7 +18,7 @@
 #define KALUGA_SERVICE_DEBUG 1
 
 #if defined(KALUGA_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
-#define KALUGA_DEBUG(x...) debug_printf("kaluga: " x)
+#define KALUGA_DEBUG(x...) debug_printf(x)
 #else
 #define KALUGA_DEBUG(x...) ((void)0)
 #endif
index ff6f737..7d55ab3 100644 (file)
@@ -1,15 +1,8 @@
-/*
- * kaluga.h
- *
- *  Created on: Feb 26, 2012
- *      Author: gz
- */
-
 #ifndef KALUGA_H_
 #define KALUGA_H_
 
 #include <barrelfish/barrelfish.h>
-#include <dist2/definitions.h>
+#include <dist2/dist2.h>
 
 #include "queue.h"
 #include "debug.h"
 #define TRIGGER_ALWAYS (DIST_PERSIST | DIST_ON_SET | DIST_ON_DEL | DIST_ALWAYS_SET)
 #define BSP_CORE_ID 0
 
+struct module_info {
+    char* complete_line;
+    char* path;
+    char* binary;
+
+    char* cmdargs; // Used for pointers in argv
+    int argc;
+    char* argv[MAX_CMDLINE_ARGS + 1];
+
+    domainid_t did;
+};
+
 extern coreid_t my_core_id;
 extern uint32_t my_arch_id;
 
+
+errval_t trigger_existing_and_watch(const char*,
+        trigger_handler_fn,  dist2_trigger_id_t*);
+
 errval_t watch_for_cores(void);
+errval_t watch_for_pci_root_bridge(void);
+errval_t watch_for_pci_devices(void);
 
 void init_environ(void);
 errval_t init_boot_modules(void);
+struct module_info* find_module(char*);
+bool is_auto_driver(struct module_info* mi);
 
 #endif /* KALUGA_H_ */
index 49be9d7..c2d2ef2 100644 (file)
 coreid_t my_core_id = 0; // Core ID
 uint32_t my_arch_id = 0; // APIC ID
 
-errval_t watch_for_pci_devices(void);
-errval_t watch_for_pci_devices(void)
-{
-    char** names = NULL;
-    size_t len = 0;
-    errval_t err = dist_get_names(&names, &len, "r'device.*' { class: _ }");
-
-    for (size_t i=0; i<len; i++) {
-        //debug_printf("found device: %s\n", names[i]);
-        char* device_record = NULL;
-        err = dist_get(&device_record, names[i]);
-        assert(err_is_ok(err));
-
-        uint64_t device_id, vendor_id;
-        //debug_printf("device record is: %s\n", device_record);
-        err = dist_read(device_record, "_ { device_id: %d, vendor: %d }", &device_id, &vendor_id);
-        assert(err_is_ok(err));
-        debug_printf("device_record: %s\n", device_record);
-        char* db_record = NULL;
-        err = dist_get(&db_record, "pci.db.devices.%lu.%lu", vendor_id, device_id);
-        if (err_is_ok(err)) {
-            char* vendor_name = NULL;
-            char* device_name = NULL;
-            //debug_printf("found db_record: %s\n", db_record);
-
-            err = dist_read(db_record, "_ { device_name: %s, vendor_name: %s }", &device_name, &vendor_name);
-            assert(err_is_ok(err));
-
-            KALUGA_DEBUG("** New device found: %s, %s\n", vendor_name, device_name);
-            free(vendor_name);
-            free(device_name);
-        }
-        else {
-            KALUGA_DEBUG("** New device not recognized: vendor_id:%lu, device_id:%lu\n", vendor_id, device_id);
-        }
-
-        free(device_record);
-    }
-
-    dist_free_names(names, len);
-
-    return err;
-}
-
 static void parse_arguments(int argc, char** argv)
 {
     for (int i = 1; i < argc; i++) {
         if (strncmp(argv[i], "apicid=", sizeof("apicid")) == 0) {
             my_arch_id = strtol(argv[i] + sizeof("apicid"), NULL, 10);
-        } else if(!strcmp(argv[i],"boot")) {
+        }
+        else if(strcmp(argv[i], "boot") == 0) {
             // ignored
         }
     }
@@ -99,6 +56,8 @@ static inline errval_t wait_for_pci(void)
 
 int main(int argc, char** argv)
 {
+    init_environ();
+
     errval_t err;
     char* record = NULL;
 
@@ -114,6 +73,11 @@ int main(int argc, char** argv)
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "Connect to SKB.");
     }
+    // Make sure the driver db is loaded
+    err = skb_execute("[device_db].");
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "Device DB not loaded.");
+    }
 
     err = dist_init();
     if (err_is_fail(err)) {
@@ -122,11 +86,9 @@ int main(int argc, char** argv)
 
     err = init_boot_modules();
     if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Initialize boot modules.");
+        USER_PANIC_ERR(err, "Parse boot modules.");
     }
 
-
-
     // The current boot protocol needs us to have
     // knowledge about how many CPUs are available at boot
     // time in order to start-up properly.
@@ -137,6 +99,11 @@ int main(int argc, char** argv)
         USER_PANIC_ERR(err, "Watching for cores.");
     }
 
+    err = watch_for_pci_root_bridge();
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "Watching for PCI root bridges.");
+    }
+
     /*
     err = watch_for_ioapic();
     if (err_is_fail(err)) {
@@ -150,18 +117,10 @@ int main(int argc, char** argv)
         return EXIT_FAILURE;
     }
 
-    /*
-    err = watch_for_pci_rootcomplex();
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Watching PCI root complexes.");
-    }*/
-
-    /*
     err = watch_for_pci_devices();
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "Watching PCI devices.");
-    }*/
-
+    }
 
     messages_handler_loop();
     return EXIT_SUCCESS;
diff --git a/usr/kaluga/start_cpu.c b/usr/kaluga/start_cpu.c
new file mode 100644 (file)
index 0000000..0905cc0
--- /dev/null
@@ -0,0 +1,243 @@
+/**
+ * \file
+ * \brief Code responsible for booting application cores
+ */
+
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/cpu_arch.h>
+
+#include <if/monitor_defs.h>
+
+#include <dist2/dist2.h>
+#include <skb/skb.h>
+
+#include "kaluga.h"
+
+// TODO: This is needed because of we have to send
+// boot_initialize_request after all cores have booted
+// It's is a hack (see monitors boot.c)
+static coreid_t cores_on_boot = 0;
+
+static errval_t new_mon_msg(struct mon_msg_state** mms, send_handler_fn s)
+{
+    *mms = malloc(sizeof(struct mon_msg_state));
+    if (*mms == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    (*mms)->send = s;
+    (*mms)->next = NULL;
+
+    return SYS_ERR_OK;
+}
+
+static void send_boot_initialize_request(struct monitor_binding* b,
+        struct mon_msg_state* mm)
+{
+    errval_t err;
+
+    err = b->tx_vtbl.boot_initialize_request(b,
+            MKCONT(free, mm));
+
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            enqueue_msg_state(b, mm);
+            return;
+        }
+        USER_PANIC_ERR(err, "kaluga: sending %s failed!", __FUNCTION__);
+    }
+}
+
+static void boot_core_reply(struct monitor_binding *st, errval_t msgerr)
+{
+    static coreid_t core_boot_replies = 1; // BSP Monitor already running
+    if (err_is_fail(msgerr)) {
+        USER_PANIC_ERR(msgerr, "msgerr in boot_core_reply, exiting\n");
+    }
+
+    KALUGA_DEBUG("boot_core_reply: core_boot_replies=%d, cores_on_boot=%d\n",
+            core_boot_replies+1, cores_on_boot);
+
+    if (++core_boot_replies == cores_on_boot) {
+        struct monitor_binding *mb = get_monitor_binding();
+        struct mon_msg_state *mms = NULL;
+        errval_t err = new_mon_msg(&mms, send_boot_initialize_request);
+        assert(err_is_ok(err));
+
+        KALUGA_DEBUG("before boot send...\n");
+        mms->send(mb, mms);
+    }
+}
+
+static void boot_initialize_reply(struct monitor_binding *st)
+{
+    KALUGA_DEBUG("boot_initialize_reply\n");
+    errval_t err = dist_set("all_spawnds_up { iref: 0 }");
+    assert(err_is_ok(err));
+}
+
+
+static void send_boot_core_request(struct monitor_binding* b,
+        struct mon_msg_state* mm)
+{
+    errval_t err;
+
+    struct module_info* mi = find_module("cpu");
+    err = b->tx_vtbl.boot_core_request(b, MKCONT(free, mm), mm->core_id,
+            mm->arch_id, CURRENT_CPU_TYPE, mi->complete_line);
+
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            enqueue_msg_state(b, mm);
+            return;
+        }
+        USER_PANIC_ERR(err, "device_manager: sending %s failed!", __FUNCTION__);
+    }
+}
+
+static inline void configure_monitor_binding(void)
+{
+    struct monitor_binding* mb = get_monitor_binding();
+    mb->rx_vtbl.boot_core_reply = boot_core_reply;
+    mb->rx_vtbl.boot_initialize_reply = boot_initialize_reply;
+    mb->st = NULL;
+}
+
+static void cpu_change_event(dist2_mode_t mode, char* record, void* state)
+{
+    if (mode & DIST_ON_SET) {
+        KALUGA_DEBUG("CPU found: %s\n", record);
+
+        uint64_t cpu_id, arch_id, enabled = 0;
+        errval_t err = dist_read(record, "_ { cpu_id: %d, id: %d, enabled: %d }",
+                &cpu_id, &arch_id, &enabled);
+        if (err_is_fail(err)) {
+            DEBUG_ERR(err, "Cannot read record.");
+            assert(!"Illformed core record received");
+            goto out;
+        }
+
+        // cpu_id may vary so we can't really use this
+        // to enumerate cores...
+        assert(my_core_id == 0);
+        static coreid_t core_id = 1;
+
+        if (arch_id != my_arch_id && enabled) {
+            struct monitor_binding* mb = get_monitor_binding();
+
+            struct mon_msg_state* mms = NULL;
+            err = new_mon_msg(&mms, send_boot_core_request);
+            assert(err_is_ok(err));
+           
+            mms->core_id = core_id++;
+            mms->arch_id = arch_id;
+            mms->send(mb, mms);
+
+            // XXX: copied this line from spawnd bsp_bootup,
+            // not sure why x86_64 is hardcoded here but it
+            // seems broken...
+            skb_add_fact("corename(%d, x86_64, apic(%lu)).",
+                    core_id, arch_id);
+        }
+
+    }
+    if (mode & DIST_ON_DEL) {
+        KALUGA_DEBUG("CPU removed: %s\n", record);
+        assert(!"NYI");
+    }
+
+out:
+    assert(!(mode & DIST_REMOVED));
+    free(record);
+}
+
+errval_t watch_for_cores(void) {
+    configure_monitor_binding();
+
+    errval_t error_code;
+    char** names = NULL;
+    char* output = NULL;
+    char* core_record = NULL; // freed by cpu_change_event
+    size_t len = 0;
+    dist2_trigger_id_t tid;
+    dist2_trigger_t t = dist_mktrigger(SYS_ERR_OK, dist2_BINDING_EVENT,
+            TRIGGER_ALWAYS, cpu_change_event, NULL);
+
+    // Get current cores registered in system
+    struct dist2_thc_client_binding_t* rpc = dist_get_thc_client();
+    static char* local_apics = "r'hw\\.apic\\.[0-9]+' { cpu_id: _, "
+                               "                        enabled: 1, "
+                               "                        id: _ }";
+    errval_t err = rpc->call_seq.get_names(rpc, local_apics,
+            t, &output, &tid, &error_code);
+    if (err_is_fail(err)) {
+        goto out;
+    }
+    err = error_code;
+
+    switch(err_no(err)) {
+    case SYS_ERR_OK:
+        err = dist_parse_names(output, &names, &len);
+        if (err_is_fail(err)) {
+            goto out;
+        }
+        cores_on_boot = (coreid_t) len;
+
+        for (size_t i=0; i < cores_on_boot; i++) {
+            KALUGA_DEBUG("get core record for name:%s\n", names[i]);
+            err = dist_get(&core_record, names[i]);
+
+            switch (err_no(err)) {
+            case SYS_ERR_OK:
+                cpu_change_event(DIST_ON_SET, core_record, NULL);
+                break;
+
+            case DIST2_ERR_NO_RECORD:
+                // Core was removed in the meantime - ignore
+                assert(core_record == NULL);
+                break;
+
+            default:
+                DEBUG_ERR(err, "Unable to retrieve core record for %s", names[i]);
+                assert(core_record == NULL);
+                break;
+            }
+        }
+        break;
+
+    case DIST2_ERR_NO_RECORD:
+        // No cores found, do nothing for now
+        KALUGA_DEBUG("No additional cores found in ACPI!\n");
+        cores_on_boot = 1;
+
+        // XXX: We simulate a boot initialize reply to set the
+        // all_spawnds_up record. The whole app monitor boot protocol will
+        // most likely change in the future and render this unnecessary.
+        boot_initialize_reply(NULL);
+        break;
+
+    default:
+        USER_PANIC_ERR(err, "Failed to check for CPU cores in SKB.");
+        break;
+    }
+
+out:
+    dist_free_names(names, cores_on_boot);
+    free(output);
+
+    return err;
+}
diff --git a/usr/kaluga/start_pci.c b/usr/kaluga/start_pci.c
new file mode 100644 (file)
index 0000000..729993e
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * \file
+ * \brief Code responsible for booting application cores
+ */
+
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/spawn_client.h>
+
+#include <dist2/dist2.h>
+#include <skb/skb.h>
+
+#include "kaluga.h"
+
+static domainid_t pci_driver = 0;
+extern char **environ;
+
+static void bridge_change_event(dist2_mode_t mode, char* bridge_record, void* st)
+{
+    if (mode & DIST_ON_SET) {
+        if (pci_driver != 0) {
+            KALUGA_DEBUG("Got new root bridge, PCI driver is already running.");
+            goto out;
+        }
+
+        // No need to ask the SKB as we always start pci for
+        // in case we find a root bridge
+        struct module_info* mi = find_module("pci");
+        if (mi == NULL || !is_auto_driver(mi)) {
+            KALUGA_DEBUG("PCI driver not found or not declared as auto.");
+            goto out;
+        }
+
+        // XXX: always spawn on my_core_id
+        KALUGA_DEBUG("bridge_change_event: spawn mi->path: %s\n", mi->path);
+        errval_t err = spawn_program(my_core_id, mi->path, mi->argv+1,
+                environ, 0, &pci_driver);
+        if (err_is_fail(err)) {
+            DEBUG_ERR(err, "Spawning PCI driver failed.");
+        }
+    }
+
+out:
+    free(bridge_record);
+}
+
+errval_t watch_for_pci_root_bridge(void)
+{
+    static char* root_bridge = "r'hw\\.pci\\.rootbridge\\.[0-9]+' { "
+                               " bus: _, device: _, function: _, maxbus: _,"
+                               " acpi_node: _ }";
+    dist2_trigger_id_t tid;
+    return trigger_existing_and_watch(root_bridge, bridge_change_event, &tid);
+}
diff --git a/usr/kaluga/start_pci_driver.c b/usr/kaluga/start_pci_driver.c
new file mode 100644 (file)
index 0000000..639d414
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * \file
+ * \brief Code responsible for booting application cores
+ */
+
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/spawn_client.h>
+
+#include <dist2/dist2.h>
+#include <skb/skb.h>
+
+#include "kaluga.h"
+
+extern char **environ;
+
+static void pci_change_event(dist2_mode_t mode, char* device_record, void* st)
+{
+    KALUGA_DEBUG("pci_change_event: %s\n", device_record);
+    errval_t err;
+    if (mode & DIST_ON_SET) {
+        uint64_t vendor_id, device_id;
+        err = dist_read(device_record, "_ { vendor: %d, device_id: %d }",
+                &vendor_id, &device_id);
+        if (err_is_fail(err)) {
+            USER_PANIC_ERR(err, "Got malformed device record?");
+        }
+
+        // Ask the SKB which binary and where to start it...
+        static char* query = "find_pci_driver(pci_card(%lu, %lu, _, _, _), Driver),"
+                             "writeln(Driver).";
+        err = skb_execute_query(query, vendor_id, device_id);
+        if (err_no(err) == SKB_ERR_EXECUTION) {
+            KALUGA_DEBUG("No PCI driver found for: VendorId=0x%lx, "
+                         "DeviceId=0x%lx\n",
+                    vendor_id, device_id);
+            goto out;
+        }
+        else if (err_is_fail(err)) {
+            DEBUG_ERR(err, "Failed to query SKB.\n");
+            goto out;
+        }
+
+        // XXX: Find better way to parse binary
+        // name from SKB
+        char* binary_name = malloc(strlen(skb_get_output()));
+        coreid_t core;
+        skb_read_output("driver(%s, %c)", binary_name, &core);
+        *strrchr(binary_name, ',') = '\0';
+
+        // No need to ask the SKB as we always start pci for
+        // in case we find a root bridge
+        struct module_info* mi = find_module(binary_name);
+        free(binary_name);
+        if (mi == NULL || !is_auto_driver(mi)) {
+            KALUGA_DEBUG("PCI driver not found or not declared as auto.\n");
+            goto out;
+        }
+
+        if (mi->did == 0) {
+            KALUGA_DEBUG("Spawn PCI driver: %s\n", mi->binary);
+
+            err = spawn_program(core, mi->path, mi->argv+1,
+                    environ, 0, &mi->did);
+            if (err_is_fail(err)) {
+                DEBUG_ERR(err, "Spawning %s failed.", mi->path);
+            }
+        }
+        else {
+            // Driver already running.
+        }
+    }
+
+out:
+    free(device_record);
+}
+
+errval_t watch_for_pci_devices(void)
+{
+    static char* pci_device  = "r'hw\\.pci\\.device\\.[0-9]+' { "
+                               " bus: _, device: _, function: _, vendor: _,"
+                               " device_id: _, class: _, subclass: _, "
+                               " prog_if: _ }";
+    dist2_trigger_id_t tid;
+    return trigger_existing_and_watch(pci_device, pci_change_event, &tid);
+}
index 250805a..a1e545e 100644 (file)
@@ -589,18 +589,21 @@ static void assign_bus_numbers(struct pci_address parentaddr, uint8_t *busnum,
                              classcode.subclss, classcode.prog_if,
                              pci_hdr0_int_pin_rd(&devhdr) - 1);
 
-                /*// TODO: test for get/set api
 
+                // dist2 start
                 char* record = NULL;
-                static char* device_fmt = "device. { bus: %u, device: %u, function: %u, vendor: %u, device_id: %u, class: %u, subclass: %u, prog_if: %u }";
-                errval_t err = dist_set_get(SET_SEQUENTIAL, &record, device_fmt,
+                static char* device_fmt = "hw.pci.device. { "
+                                          "bus: %u, device: %u, function: %u, "
+                                          "vendor: %u, device_id: %u, class: %u, "
+                                          "subclass: %u, prog_if: %u }";
+                errval_t err = dist_mset(SET_SEQUENTIAL, device_fmt,
                         addr.bus, addr.device, addr.function, vendor,
                         device_id, classcode.clss, classcode.subclss,
                         classcode.prog_if);
 
                 assert(err_is_ok(err));
                 free(record);
-                // end dist2*/
+                // end dist2
 
                 query_bars(devhdr, addr, false);
             }
index 7cea8e2..70f7377 100644 (file)
 pci_driver{
     binary: "e1000",
     supported_cards:
-    [ pci_card{ vendor: 16'8086, device: 16'ded, function: _, subvendor: _, subdevice: _ },
-      pci_card{ vendor: 16'8086, device: 16'ded, function: _, subvendor: _, subdevice: _ } ],
+    [ pci_card{ vendor: 16'8086, device: 16'ded, function: _, subvendor: _, subdevice: _ } ],
     core_hint: 0,
     interrupt_load: 0.75,
     platforms: ['x86_64', 'x86_32']
 }.
 
-cpu_driver{
-    binary: "cpu",
+pci_driver{
+    binary: "rtl8029",
+    supported_cards:
+    [ pci_card{ vendor: 16'10ec, device: 16'8029, function: _, subvendor: _, subdevice: _ } ],
+    core_hint: 0,
+    interrupt_load: 0.5,
     platforms: ['x86_64', 'x86_32']
 }.
 
-bus_driver{
-    binary: "pci",
-    core_hint: 0,
+cpu_driver{
+    binary: "cpu",
     platforms: ['x86_64', 'x86_32']
 }.
 
@@ -57,7 +59,6 @@ bus_driver{
     platforms: ['x86_64', 'x86_32']
 }.
 
-
 %
 % Driver selection logic
 %
index 473ef00..74b43e0 100644 (file)
@@ -238,7 +238,8 @@ void spawn_app_domains(void)
            or nospawn modules */
         if (si.argc >= 2 && (strcmp(si.argv[1], "boot") == 0
                           || strcmp(si.argv[1], "dist-serv") == 0
-                          || strcmp(si.argv[1], "nospawn") == 0)) {
+                          || strcmp(si.argv[1], "nospawn") == 0
+                          || strcmp(si.argv[1], "auto") == 0)) {
             spawn_here = false;
         }