IRQ: Kaluga start driver with IRQ caps.
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Thu, 14 Jul 2016 15:23:25 +0000 (17:23 +0200)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Fri, 29 Jul 2016 11:38:03 +0000 (13:38 +0200)
Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

17 files changed:
include/barrelfish/caddr.h
include/int_route/int_route_client.h
include/pci/pci_client_debug.h
kernel/arch/x86_64/irq.c
lib/barrelfish/capabilities.c
lib/barrelfish/debug.c
lib/int_route/client/client.c
lib/int_route/server/init.c
lib/pci/pci_client.c
usr/kaluga/boot_modules.h
usr/kaluga/driver_startup.c
usr/kaluga/driver_startup.h
usr/kaluga/start_cpu.c
usr/kaluga/start_cpu.h
usr/kaluga/start_pci.c
usr/tests/irqtest/Hakefile
usr/tests/irqtest/irqtest.c

index b969c80..9eff4c6 100644 (file)
@@ -65,7 +65,7 @@ extern struct cnoderef cnode_root, cnode_task, cnode_base,
 /* well-known capabilities */
 extern struct capref cap_root, cap_monitorep, cap_irq, cap_io, cap_dispatcher,
                      cap_selfep, cap_kernel, cap_initep, cap_perfmon, cap_dispframe,
-                     cap_sessionid, cap_ipi, cap_vroot;
+                     cap_sessionid, cap_ipi, cap_vroot, cap_argcn;
 
 /**
  * \brief Returns the number of valid bits in the CSpace address of a cap
index 68c505f..dce0690 100644 (file)
@@ -16,5 +16,6 @@
 #define INT_ROUTE_CLIENT_H_
 
 errval_t int_route_client_connect(void);
+errval_t int_route_client_route(struct capref intsrc, struct capref intdest);
 
 #endif /* INT_ROUTE_CLIENT_H_ */
index 430a7c9..f417db9 100644 (file)
@@ -1,10 +1,10 @@
 #ifndef PCI_CLIENT_DEBUG_H
 #define PCI_CLIENT_DEBUG_H
 
-#define PCI_LIB_DEBUG 1
+#define PCI_LIB_DEBUG
 
 #if defined(PCI_LIB_DEBUG) || defined(GLOBAL_DEBUG)
-#define PCI_CLIENT_DEBUG(x...) printf("pci_client: " x)
+#define PCI_CLIENT_DEBUG(x...) debug_printf("pci_client: " x)
 #else
 #define PCI_CLIENT_DEBUG(x...) ((void)0)
 #endif
index 3e9ad25..34a77d2 100644 (file)
@@ -550,7 +550,7 @@ errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t ou
 
     int i;
     bool i_usable = false;
-    for (i = 0; i < NDISPATCH; i++) {
+    for (i = NEXCEPTIONS+1; i < NDISPATCH; i++) {
         i_usable = true;
         //Iterate over all kcbs
         struct kcb *k = kcb_current;
index 911fa89..1f22423 100644 (file)
@@ -116,6 +116,12 @@ struct capref cap_dispframe = {
     .size_bits = DEFAULT_CNODE_BITS, \
     .guard_size = 0 }
 
+/// Capability for ArgSpace
+struct capref cap_argcn = {
+    .cnode = ROOT_CNODE_INIT,
+    .slot  = ROOTCN_SLOT_ARGCN
+};
+
 /// Capability for monitor endpoint
 struct capref cap_monitorep = {
     .cnode = ROOT_CNODE_INIT,
index 52e7a66..801870d 100644 (file)
@@ -328,6 +328,10 @@ int debug_print_cap(char *buf, size_t len, struct capability *cap)
     case ObjType_IRQTable:
         return snprintf(buf, len, "IRQTable cap");
 
+    case ObjType_IRQSrc:
+        return snprintf(buf, len, "IRQSrc cap (vec: %"PRIu64")",
+                cap->u.irqsrc.vector);
+
     case ObjType_IRQDest:
         return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", cpu: %"PRIu64")",
                 cap->u.irqdest.vector, cap->u.irqdest.cpu);
index a8b6fd7..5670c05 100644 (file)
 #include <int_route/int_route_debug.h>
 
 #include <if/int_route_service_defs.h>
-//#include <if/int_route_service_rpcclient_defs.h>
+#include <if/int_route_service_rpcclient_defs.h>
 
 static struct int_route_state {
     bool request_done;
     struct int_route_rpc_client * client;
     struct int_route_service_binding * binding;
+    struct int_route_service_rpc_client rpc_client;
 
 } int_route_state_st;
 
@@ -37,7 +38,12 @@ static struct int_route_state * get_int_route_state(void){
 
 static void bind_cb(void *st, errval_t binderr, struct int_route_service_binding *b) {
     assert(err_is_ok(binderr));
-    get_int_route_state()->binding = b;
+    errval_t err;
+    int_route_state_st.binding = b;
+    int_route_state_st.request_done = true;
+
+    err = int_route_service_rpc_client_init(&(int_route_state_st.rpc_client), b);
+    assert(err_is_ok(err));
 }
 
 //errval_t int_route_add_controller(int bus, int dev, int fun,
@@ -57,6 +63,17 @@ static void bind_cb(void *st, errval_t binderr, struct int_route_service_binding
 //    return b->tx_vtbl.route_call(b, NULL, intin, dest);
 //}
 
+errval_t int_route_client_route(struct capref intsrc, struct capref intdest){
+    assert(int_route_state_st.request_done);
+    struct int_route_service_rpc_client * cl = &int_route_state_st.rpc_client;
+    errval_t msgerr, err;
+    msgerr = cl->vtbl.route(cl, intsrc, intdest, &err);
+    if(err_is_fail(msgerr)){
+        return msgerr;
+    }
+    return err;
+}
+
 errval_t int_route_client_connect(void){
     errval_t err;
     iref_t iref;
index 71ac15f..05af15f 100644 (file)
@@ -182,7 +182,7 @@ static void driver_route_call(struct int_route_service_binding *b,
     err = skb_execute(query);
     if(err_is_fail(err)){
         DEBUG_ERR(err, "Error executing: %s.\n", query);
-        b->rx_vtbl.route_response(b, err);
+        b->tx_vtbl.route_response(b, NOP_CONT, err);
         return;
     }
 
@@ -190,7 +190,7 @@ static void driver_route_call(struct int_route_service_binding *b,
     if(err_is_fail(err)){
         DEBUG_ERR(err, "Error read_route_and_tell_controllers.\n");
     }
-    b->rx_vtbl.route_response(b, err);
+    b->tx_vtbl.route_response(b, NOP_CONT, err);
 }
 
 static void ctrl_register_controller(struct int_route_controller_binding *_binding,
@@ -282,7 +282,7 @@ errval_t int_route_service_init(void)
     }
 
 
-    // HACK: Due to cyclic dependency, we must make sure the service has been exported before
+    // XXX: Due to cyclic dependency, we must make sure the service has been exported before
     // returning.
 
     while(exported != 2){
index 6710dab..4640515 100644 (file)
@@ -25,6 +25,7 @@
 #include <if/acpi_rpcclient_defs.h>
 #include <acpi_client/acpi_client.h>
 #include <int_route/int_model.h>
+#include <int_route/int_route_client.h>
 
 #define INVALID_VECTOR ((uint64_t)-1)
 
@@ -110,22 +111,33 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
                         &nbars, caps_per_bar, caps_per_bar + 1, caps_per_bar + 2,
                         caps_per_bar + 3, caps_per_bar + 4, caps_per_bar + 5);
     if (err_is_fail(err)) {
+        PCI_CLIENT_DEBUG("init pci device failed.\n");
         return err;
     } else if (err_is_fail(msgerr)) {
         return msgerr;
     }
 
-    struct capref irq_src_cap;
 
-    // Get vector 0 of the device.
-    // For backward compatibility with function interface.
-    err = pci_client->vtbl.get_irq_cap(pci_client, 0, &msgerr, &irq_src_cap);
-    if (err_is_fail(err) || err_is_fail(msgerr)) {
-        if (err_is_ok(err)) {
-            err = msgerr;
-        }
-        DEBUG_ERR(err, "requesting cap for IRQ 0 of device");
-        goto out;
+    // Check for cap argument
+    struct capability cap_argcn_data;
+    err = debug_cap_identify(cap_argcn, &cap_argcn_data);
+    if(err_is_fail(err) || cap_argcn_data.type == ObjType_Null){
+        PCI_CLIENT_DEBUG("No capabilites passed as argument. Driver not started by kaluga?");
+    }
+
+    // We use the first passed vector of the device,
+    // for backward compatibility with function interface.
+    struct capref irq_src_cap;
+    struct capability irq_src_cap_data;
+    irq_src_cap.cnode = build_cnoderef(cap_argcn, DEFAULT_CNODE_BITS);
+    irq_src_cap.slot = 0;
+    err = debug_cap_identify(irq_src_cap, &irq_src_cap_data);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err, "Could not identify cap?");
+    }
+    if(irq_src_cap_data.type != ObjType_IRQSrc){
+        PCI_CLIENT_DEBUG("First cap argument ist not of type IRQSrc (is=%d)."
+                "Driver not started by kaluga?\n", cap_argcn_data.type);
     }
 
     uint64_t gsi = INVALID_VECTOR;
@@ -134,7 +146,7 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
         DEBUG_ERR(err, "Could not lookup GSI vector");
         return err;
     }
-    PCI_CLIENT_DEBUG("Got irqsrc cap, gsi: %"PRIu32"\n", gsi);
+    PCI_CLIENT_DEBUG("Got irqsrc cap, gsi: %"PRIu64"\n", gsi);
 
     // Get irq_dest_cap from monitor
     struct capref irq_dest_cap;
@@ -149,21 +161,29 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
         DEBUG_ERR(err, "Could not lookup irq vector");
         return err;
     }
-    PCI_CLIENT_DEBUG("Got dest cap, vector: %"PRIu32"\n", irq_dest_vec);
+    PCI_CLIENT_DEBUG("Got dest cap, vector: %"PRIu64"\n", irq_dest_vec);
 
 
-    // Setup routing
-    // TODO: Instead of getting the vectors of each cap and set up routing,
-    // pass both to a routing service and let the service handle the setup.
-    struct acpi_rpc_client* cl = get_acpi_rpc_client();
-    errval_t ret_error;
-    err = cl->vtbl.enable_and_route_interrupt(cl, gsi, disp_get_core_id(), irq_dest_vec, &ret_error);
-    assert(err_is_ok(err));
-    if (err_is_fail(ret_error)) {
-        DEBUG_ERR(ret_error, "failed to route interrupt %d -> %d\n", gsi, irq_dest_vec);
-        return err_push(ret_error, PCI_ERR_ROUTING_IRQ);
+    err = int_route_client_route(irq_src_cap, irq_dest_cap);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err, "Could not set up route.");
+        return err;
+    } else {
+        PCI_CLIENT_DEBUG("Int route set-up success.\n");
     }
 
+    //// Setup routing
+    //// TODO: Instead of getting the vectors of each cap and set up routing,
+    //// pass both to a routing service and let the service handle the setup.
+    //struct acpi_rpc_client* cl = get_acpi_rpc_client();
+    //errval_t ret_error;
+    //err = cl->vtbl.enable_and_route_interrupt(cl, gsi, disp_get_core_id(), irq_dest_vec, &ret_error);
+    //assert(err_is_ok(err));
+    //if (err_is_fail(ret_error)) {
+    //    DEBUG_ERR(ret_error, "failed to route interrupt %d -> %d\n", gsi, irq_dest_vec);
+    //    return err_push(ret_error, PCI_ERR_ROUTING_IRQ);
+    //}
+
     // Connect endpoint to handler
     if(handler != NULL){
         err = inthandler_setup_movable_cap(irq_dest_cap, handler, handler_arg,
@@ -389,12 +409,15 @@ errval_t pci_client_connect(void)
     iref_t iref;
     errval_t err, err2 = SYS_ERR_OK;
 
+    PCI_CLIENT_DEBUG("Connecting to acpi\n");
     err = connect_to_acpi();
     if(err_is_fail(err)){
         return err;
     }
+    PCI_CLIENT_DEBUG("Connected to ACPI\n");
 
     /* Connect to the pci server */
+    PCI_CLIENT_DEBUG("Looking up pci iref\n");
     err = nameservice_blocking_lookup("pci", &iref);
     if (err_is_fail(err)) {
         return err;
@@ -402,6 +425,7 @@ errval_t pci_client_connect(void)
 
     assert(iref != 0);
 
+    PCI_CLIENT_DEBUG("Connecting to pci\n");
     /* Setup flounder connection with pci server */
     err = pci_bind(iref, bind_cont, &err2, get_default_waitset(),
                    IDC_BIND_FLAG_RPC_CAP_TRANSFER);
@@ -414,5 +438,14 @@ errval_t pci_client_connect(void)
         messages_wait_and_handle_next();
     }
 
+    if(err_is_ok(err2)){
+        PCI_CLIENT_DEBUG("PCI connection successful, connecting to int route service\n");
+        err = int_route_client_connect();
+        if(err_is_ok(err)){
+            PCI_CLIENT_DEBUG("Int route service connected.\n");
+        } else {
+            DEBUG_ERR(err, "Could not connect to int route service\n");
+        }
+    }
     return err2;
 }
index 4035950..7597edd 100644 (file)
@@ -2,11 +2,18 @@
 #define BOOT_MODULES_H_
 
 #include <barrelfish/barrelfish.h>
+#include <int_route/int_model.h>
 
 struct module_info;
 struct int_startup_argument;
+
+struct driver_argument {
+    struct capref arg_caps;
+    struct int_startup_argument int_arg;
+
+};
 typedef errval_t(*module_start_fn)(coreid_t where, struct module_info* mi,
-        char* record, struct int_startup_argument * int_arg);
+        char* record, struct driver_argument * int_arg);
 
 #define MAX_DRIVER_INSTANCES 16
 
index ed4925d..35b6f25 100644 (file)
@@ -44,7 +44,7 @@ static void argv_push(int * argc, char *** argv, char * new_arg){
 
 errval_t default_start_function(coreid_t where,
                                 struct module_info* mi,
-                                char* record, struct int_startup_argument * int_arg)
+                                char* record, struct driver_argument * arg)
 {
     assert(mi != NULL);
     errval_t err = SYS_ERR_OK;
@@ -77,9 +77,9 @@ errval_t default_start_function(coreid_t where,
                     &bus, &dev, &fun, &vendor_id, &device_id);
 
     char * int_arg_str = NULL;
-    if(int_arg != NULL){
+    if(arg != NULL){
         // This malloc int_arg_str
-        int_startup_argument_to_string(int_arg, &int_arg_str);
+        int_startup_argument_to_string(&(arg->int_arg), &int_arg_str);
         KALUGA_DEBUG("Adding int_arg_str: %s\n", int_arg_str);
         argv_push(&argc, &argv, int_arg_str);
     }
@@ -99,8 +99,15 @@ errval_t default_start_function(coreid_t where,
     }
 
 
-    err = spawn_program(core, mi->path, argv,
-                    environ, 0, get_did_ptr(mi));
+    //err = spawn_program(core, mi->path, argv,
+    //                environ, 0, get_did_ptr(mi));
+
+    struct capref arg_cap = NULL_CAP;
+    if(arg != NULL){
+       arg_cap = arg->arg_caps;
+    }
+    err = spawn_program_with_caps(core, mi->path, argv,
+                    environ, NULL_CAP, arg_cap, 0, get_did_ptr(mi));
 
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "Spawning %s failed.", mi->path);
@@ -116,7 +123,7 @@ errval_t default_start_function(coreid_t where,
 
 errval_t start_networking(coreid_t core,
                           struct module_info* driver,
-                          char* record, struct int_startup_argument * intarg)
+                          char* record, struct driver_argument * arg)
 {
     assert(driver != NULL);
     errval_t err = SYS_ERR_OK;
index 5bcfa44..9e391a4 100644 (file)
@@ -7,8 +7,8 @@
 
 struct int_startup_argument;
 errval_t default_start_function(coreid_t, struct module_info*, char*,
-        struct int_startup_argument * int_arg);
+        struct driver_argument * arg);
 errval_t start_networking(coreid_t, struct module_info*, char*,
-        struct int_startup_argument * int_arg);
+        struct driver_argument * arg);
 
 #endif /* DRIVER_STARTUP_H_ */
index b004b78..80e1c7d 100644 (file)
@@ -77,7 +77,7 @@ errval_t watch_for_cores(void)
 }
 
 errval_t start_boot_driver(coreid_t where, struct module_info* mi,
-        char* record, struct int_startup_argument * int_arg)
+        char* record, struct driver_argument * int_arg)
 {
     assert(mi != NULL);
     errval_t err;
index 1d53789..b4b20d3 100644 (file)
@@ -9,7 +9,7 @@ errval_t watch_for_cores(void);
 errval_t wait_for_all_spawnds(void);
 errval_t start_boot_driver(coreid_t where,
                            struct module_info* mi,
-                           char* record, struct int_startup_argument * int_arg);
+                           char* record, struct driver_argument * int_arg);
 
 
 #endif /* START_CPU_H_ */
index 155a73a..9489663 100644 (file)
@@ -115,6 +115,9 @@ static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
             USER_PANIC_ERR(err, "Could not parse SKB output: %s\n", skb_get_output());
         }
         int_arg.model = int_model_in;
+
+        struct driver_argument driver_arg;
+        driver_arg.int_arg = int_arg;
         if(int_arg.model == INT_MODEL_LEGACY){
             KALUGA_DEBUG("Starting driver with legacy interrupts\n");
             // No controller has to instantiated, but we need to get caps for the int numbers
@@ -127,9 +130,25 @@ static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
             struct list_parser_status pa_sta;
             skb_read_list_init(&pa_sta);
             int int_num;
-            while(skb_read_list(&pa_sta, "int(%d)", &int_num)){
+            struct cnoderef argnode_ref;
+            err = cnode_create(&driver_arg.arg_caps, &argnode_ref,
+                               DEFAULT_CNODE_SLOTS, NULL);
+
+            if(err_is_fail(err)){
+                USER_PANIC_ERR(err, "Could not create int_src cap");
+            }
+
+            for(int i=0; skb_read_list(&pa_sta, "int(%d)", &int_num); i++){
                 //Works
                 KALUGA_DEBUG("Interrupt for driver: %d\n", int_num);
+                struct capref cap;
+                cap.cnode = argnode_ref;
+                cap.slot = i;
+                err = sys_debug_create_irq_src_cap(cap, int_num);
+
+                if(err_is_fail(err)){
+                    USER_PANIC_ERR(err, "Could not create int_src cap");
+                }
             }
         } else if(int_arg.model == INT_MODEL_MSI){
             KALUGA_DEBUG("Starting driver with MSI interrupts");
@@ -170,7 +189,7 @@ static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
 
         // If we've come here the core where we spawn the driver
         // is already up
-        err = mi->start_function(core, mi, device_record, &int_arg);
+        err = mi->start_function(core, mi, device_record, &driver_arg);
         switch (err_no(err)) {
         case SYS_ERR_OK:
             KALUGA_DEBUG("Spawned PCI driver: %s\n", mi->binary);
index cd42277..d2fedbb 100644 (file)
@@ -12,7 +12,7 @@
 
 [ build application { target = "irqtest",
                       cFiles = [ "irqtest.c", "e1000n_helpers.c", "e1000n_hwinit.c" ],
-                      addLibraries = libDeps [ "pci" ],
+                      addLibraries = libDeps [ "pci", "int_route_client" ],
                       mackerelDevices = [ "e1000" ]
                     }
 ]
index fe0b7f7..9ae7c63 100644 (file)
@@ -159,6 +159,10 @@ int main(int argc, char **argv)
 {
     errval_t err;
 
+    IRQ_DEBUG("Printing Caps:\n");
+    debug_my_cspace();
+    IRQ_DEBUG("Printing Caps Done\n");
+
     /** Parse command line arguments. */
     IRQ_DEBUG("irq test started.\n");
 
@@ -169,6 +173,24 @@ int main(int argc, char **argv)
         IRQ_DEBUG("Could not parse int argument");
     }
 
+    if (argc > 1) {
+        uint32_t parsed = sscanf(argv[argc - 1], "%x:%x:%x:%x:%x", &vendor,
+                                 &deviceid, &bus, &device, &function);
+        if (parsed != 5) {
+            IRQ_DEBUG("Driver seems not to be started by Kaluga.\n");
+            vendor = PCI_DONT_CARE;
+            deviceid = PCI_DONT_CARE;
+            bus = PCI_DONT_CARE;
+            device = PCI_DONT_CARE;
+            function = PCI_DONT_CARE;
+        } else {
+            IRQ_DEBUG("Parsed Kaluga argument: PCI Device (%u, %u, %u) Vendor: 0x%04x, Device 0x%04x\n",
+                        bus, device, function, vendor, deviceid);
+            // remove the last argument
+            argc--;
+        }
+    }
+
     for (int i = 1; i < argc; i++) {
         IRQ_DEBUG("arg %d = %s\n", i, argv[i]);
         if (strcmp(argv[i], "auto") == 0) {
@@ -197,7 +219,7 @@ int main(int argc, char **argv)
                  strcmp(argv[i], "--help") == 0) {
             //exit_help(argv[0]);
         } else {
-            IRQ_DEBUG("Parsed Kaluga device address %s.\n", argv[i]);
+            IRQ_DEBUG("Ignoring %s.\n", argv[i]);
         }
     } // end for :
 
@@ -238,16 +260,15 @@ int main(int argc, char **argv)
 
 
     IRQ_DEBUG("Connecting to PCI.\n");
-
     err = pci_client_connect();
     assert(err_is_ok(err));
 
+    IRQ_DEBUG("########### Driver with interrupts ###########\n");
     err = pci_register_driver_movable_irq(e1000_init_fn, class, subclass, program_interface,
                                           vendor, deviceid, bus, device, function,
                                           e1000_interrupt_handler_fn, NULL,
                                           e1000_reregister_handler,
                                           NULL);
-    IRQ_DEBUG("########### Driver with interrupts ###########\n");
 
 
     if (err_is_fail(err)) {