armv8: implement user space irq routing + lpuart interrupt
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Thu, 14 Nov 2019 16:44:30 +0000 (17:44 +0100)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Mon, 18 Nov 2019 11:53:02 +0000 (12:53 +0100)
Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

12 files changed:
hake/menu.lst.armv8_imx8x
include/int_route/int_route_debug.h
lib/int_route/Hakefile
lib/int_route/client/client.c
lib/int_route/server/standalone.c
lib/int_route/server/standalone_armv7.c [new file with mode: 0644]
platforms/Hakefile
usr/drivers/pl390_dist/Hakefile
usr/drivers/serial/serial_lpuart.c
usr/kaluga/armv8_imx8x.c
usr/monitor/monitor_rpc_server.c
usr/skb/programs/irq_routing_new.pl

index 1ac4a20..209e659 100644 (file)
@@ -27,6 +27,8 @@ modulenounzip /skb_ramfs.cpio.gz nospawn
 #module /armv8/sbin/corectrl auto
 #module /armv8/sbin/pci auto
 module /armv8/sbin/serial_lpuart auto 
+module /armv8/sbin/pl390_dist auto 
+module /armv8/sbin/int_route auto
 
 
 # General user domains
index f28837f..2c38857 100644 (file)
@@ -1,8 +1,16 @@
+/**
+ * \file
+ * \brief Interrupt routing debug print
+ */
+
 /*
- * int_route_debug.h
+ * Copyright (c) 2016, 2019, ETH Zurich.
+ * All rights reserved.
  *
- *  Created on: Jul 5, 2016
- *      Author: luki
+ * 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, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
+ * Attn: Systems Group.
  */
 
 #ifndef INT_ROUTE_INT_ROUTE_DEBUG_H_
index 8fe286f..0b58fa0 100644 (file)
 
     -- We run a stand alone IRS on ARMv7
     build application { target = "int_route",
-                    cFiles = [ "server/standalone.c" ],
+                    cFiles = [ "server/standalone_armv7.c" ],
                     flounderDefs = [ "int_route_service", "monitor_blocking" ],
                     flounderBindings = [ "int_route_service", "int_route_controller" ],
                     flounderExtraBindings = [ ("int_route_service", ["rpcclient"]),
                                               ("monitor_blocking", ["rpcclient"]) ],
                     architectures = ["armv7"]
+                   },
+
+    -- We run a stand alone IRS on ARMv8. It uses lib skb_int_route_server
+    build application { target = "int_route",
+                    cFiles = [ "server/standalone.c" ],
+                    flounderDefs = [ "int_route_service", "monitor_blocking" ],
+                    flounderBindings = [ "int_route_service", "int_route_controller" ],
+                    flounderExtraBindings = [ ("int_route_service", ["rpcclient"]),
+                                              ("monitor_blocking", ["rpcclient"]) ],
+                    addLibraries = ["int_route_server"],
+                    architectures = ["armv8"] 
                    }
 ]
index 6aad7c7..d5c4328 100644 (file)
@@ -114,6 +114,8 @@ static void irq_handler(void *arg)
     irqarg->uc.handler(irqarg->uc.arg);
 }
 
+#define DIST_OFFSET 1000
+
 errval_t int_route_client_route_and_connect(struct capref intsrc, int irq_idx,
         struct waitset * ws, interrupt_handler_fn handler, void *handler_arg)
 {
@@ -127,7 +129,9 @@ errval_t int_route_client_route_and_connect(struct capref intsrc, int irq_idx,
 
     /* allocate irq dest cap */
     struct capref irq_dest_cap;
-#ifdef __arm__
+    /* TODO: Following cases assume a specific irq number layout. 
+     * Replace these cases with a skb query */
+#if defined(__arm__) || defined(__ARM_ARCH_8A__)
     err = alloc_dest_irq_cap_arm(intsrc, irq_idx, &irq_dest_cap);
 #else
     err = alloc_dest_irq_cap(&irq_dest_cap);
index 79f1132..1c75cb7 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2009, 2010, 2012, ETH Zurich.
+ * Copyright (c) 2019, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
 #include <string.h>
 #include <inttypes.h>
 #include <errno.h>
-
 #include <barrelfish/barrelfish.h>
-#include <barrelfish/nameservice_client.h>
-#include <skb/skb.h> // read list
+#include <skb/skb.h>
 #include <int_route/int_route_server.h>
-#include <int_route/int_route_debug.h>
-
-#include <if/int_route_service_defs.h>
-#include <if/int_route_controller_defs.h>
-
-struct controller_driver {
-   char * label; // Label used in the SKB
-   char * class; // Class used in the SKB
-   struct int_route_controller_binding * binding; //
-   struct controller_driver * next; // Linked list next
-};
-
-/* This server exports two interfaces:
- * * RPC interface - This is RPC the interface that
- * * Controller interface - Interrupt controllers use a
- */
-
-struct controller_driver * controller_head;
-static int exported = 0;
-
-static struct controller_driver * add_controller(struct controller_driver * d){
-    struct controller_driver * cur;
-    if(controller_head == NULL){
-        controller_head = malloc(sizeof(struct controller_driver));
-        cur = controller_head;
-    } else if(d != NULL && d->next != NULL){
-        return add_controller(d->next);
-    } else {
-        assert(d != NULL);
-        d->next = malloc(sizeof(struct controller_driver));
-        cur = d->next;
-    }
-
-    // Initialize cur
-    cur->next = NULL;
-    cur->binding = NULL;
-    cur->label = NULL;
-    cur->class = NULL;
-    return cur;
-}
-
-/*
- * Finds a controller for the given label/class combination.
- * First, if a label is passed, it tries to match the label exactly, if no
- * controller is found, it goes on to match on the class.
- */
-static struct controller_driver *find_controller(const char *label,
-                                                 const char *class) {
-    if (label != NULL && strlen(label) > 0) {
-        for (struct controller_driver *cur = controller_head; cur != NULL;
-             cur = cur->next) {
-            if (strcmp(label, cur->label) == 0) {
-                return cur;
-            }
-        }
-    }
-    if (class != NULL && strlen(class) > 0) {
-        for (struct controller_driver *cur = controller_head; cur != NULL;
-             cur = cur->next) {
-            if (strcmp(class, cur->class) == 0) {
-                return cur;
-            }
-        }
-    }
-    return NULL;
-}
-
-struct controller_add_mapping_data {
-    char * lbl;
-    char * class;
-    int_route_controller_int_message_t in_msg;
-    int_route_controller_int_message_t out_msg;
-    struct int_route_controller_binding *binding;
-};
-
-#define INVALID_PORT -1
-#define INVALID_VECTOR ((uint64_t)-1)
-
-/**
- * Since on ARMv7 the topolgy is easy, we don't use the SKB.
- */
-static void driver_route_call_armv7(struct int_route_service_binding *b,
-        struct capref intsource, int irq_idx,
-        struct capref intdest){
-    INT_DEBUG("%s: enter\n", __FUNCTION__);
-
-    errval_t err;
-    uint64_t int_src_num = INVALID_VECTOR;
-    err = invoke_irqsrc_get_vec_start(intsource, &int_src_num);
-    uint64_t int_src_num_high = INVALID_VECTOR;
-    err = invoke_irqsrc_get_vec_end(intsource, &int_src_num_high);
-    if(int_src_num + irq_idx > int_src_num_high || irq_idx < 0){
-        err = SYS_ERR_IRQ_INVALID;
-        DEBUG_ERR(err, "irq_idx out of range");
-        b->tx_vtbl.route_response(b, NOP_CONT, err);
-        return;
-    }
-
-    assert(err_is_ok(err));
-    int_src_num += irq_idx;
-
-    uint64_t dest_vec = INVALID_VECTOR;
-    err = invoke_irqdest_get_vector(intdest, &dest_vec);
-    assert(err_is_ok(err));
-
-    uint64_t dest_cpu = INVALID_VECTOR;
-    err = invoke_irqdest_get_cpu(intdest, &dest_cpu);
-    assert(err_is_ok(err));
-
-    printf("Int route service: Routing request, (int=%"PRIu64") to "
-            "(cpu=%"PRIu64",vec=%"PRIu64")\n",
-            int_src_num, dest_cpu, dest_vec);
-
-
-    const char * class = "gic_dist";
-    struct controller_driver * gic_dist = find_controller(NULL, class);
-
-    if(gic_dist == NULL){
-        err = SYS_ERR_IRQ_INVALID;
-        DEBUG_ERR(err, "gic_dist controller not found!\n");
-    } else {
-        int_route_controller_int_message_t in_msg;
-        in_msg.port = int_src_num;
-        int_route_controller_int_message_t out_msg;
-        out_msg.port = dest_cpu;
-        err = int_route_controller_add_mapping__tx(gic_dist->binding,
-                BLOCKING_CONT, NULL, class, in_msg,
-                out_msg);
-    }
-
-    b->tx_vtbl.route_response(b, NOP_CONT, err);
-}
-
-static void ctrl_register_controller(struct int_route_controller_binding *_binding,
-        const char *label, const char *class) {
-    struct controller_driver * c = add_controller(controller_head);
-    c->label = malloc(strlen(label)+1);
-    assert(c->label != NULL);
-    strcpy(c->label, label);
-
-    c->class = malloc(strlen(class)+1);
-    assert(c->class != NULL);
-    strcpy(c->class, class);
-    INT_DEBUG("ctrl_register_controller, label=%s, class=%s\n",c->label, c->class);
-
-    c->binding = _binding;
-}
-
-
-static struct int_route_service_rx_vtbl driver_rx_vtbl = {
-        .route_call = driver_route_call_armv7
-
-};
-
-static struct int_route_controller_rx_vtbl ctrl_rx_vtbl = {
-        .register_controller = ctrl_register_controller
-};
-
-static errval_t driver_connect_cb(void *st, struct int_route_service_binding *b) {
-    INT_DEBUG("%s: enter\n", __FUNCTION__);
-    b->st = NULL;
-    b->rx_vtbl = driver_rx_vtbl;
-    return SYS_ERR_OK;
-
-}
-
-static errval_t ctrl_connect_cb(void *st, struct int_route_controller_binding *b) {
-    INT_DEBUG("%s: enter\n", __FUNCTION__);
-    b->st = NULL;
-    b->rx_vtbl = ctrl_rx_vtbl;
-    return SYS_ERR_OK;
-
-}
-
-static void driver_export_cb(void *st, errval_t err, iref_t iref){
-    INT_DEBUG("%s: enter\n", __FUNCTION__);
-    assert(err_is_ok(err));
-
-    err = nameservice_register("int_route_service", iref);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "nameservice_register 1 failed");
-    };
-    exported++;
-}
-
-static void ctrl_export_cb(void *st, errval_t err, iref_t iref){
-    INT_DEBUG("%s: enter\n", __FUNCTION__);
-    assert(err_is_ok(err));
-
-    err = nameservice_register("int_ctrl_service", iref);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "nameservice_register 2 failed");
-    };
-    exported++;
-}
 
 
 // The main function of this service
 int main(void) {
+    debug_printf("Hello from int_route standalone service\n");
     errval_t err;
-    debug_printf("Start\n");
 
-    // Export route service for PCI device drivers
-    err = int_route_service_export(NULL, driver_export_cb, driver_connect_cb,
-                                   get_default_waitset(),
-                                   IDC_EXPORT_FLAGS_DEFAULT);
+    err = skb_client_connect();
+    if(err_is_fail(err)){
+        USER_PANIC_ERR(err, "starting skb");
+    }
 
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "int_route_service_export failed");
+    err = skb_execute("[irq_routing_new].");
+    if(err_is_fail(err)){
+        DEBUG_SKB_ERR(err, "loading irq routing new");
+        USER_PANIC("panic");
     }
 
-    err = int_route_controller_export(NULL, ctrl_export_cb, ctrl_connect_cb,
-                                      get_default_waitset(),
-                                      IDC_EXPORT_FLAGS_DEFAULT);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "int_route_controller_export failed");
+    err = skb_execute("add_armv8_controllers");
+    if(err_is_fail(err)){
+        DEBUG_SKB_ERR(err, "add_armv8_controllers");
+        USER_PANIC("panic");
     }
 
+    err = int_route_service_init();
+    assert(err_is_ok(err));
     while (true) {
         event_dispatch(get_default_waitset());
     }
-
     return 0;
 }
diff --git a/lib/int_route/server/standalone_armv7.c b/lib/int_route/server/standalone_armv7.c
new file mode 100644 (file)
index 0000000..79f1132
--- /dev/null
@@ -0,0 +1,247 @@
+/**
+ * \file
+ * \brief Contains handler functions for server-side octopus interface RPC call.
+ */
+
+/*
+ * Copyright (c) 2009, 2010, 2012, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/nameservice_client.h>
+#include <skb/skb.h> // read list
+#include <int_route/int_route_server.h>
+#include <int_route/int_route_debug.h>
+
+#include <if/int_route_service_defs.h>
+#include <if/int_route_controller_defs.h>
+
+struct controller_driver {
+   char * label; // Label used in the SKB
+   char * class; // Class used in the SKB
+   struct int_route_controller_binding * binding; //
+   struct controller_driver * next; // Linked list next
+};
+
+/* This server exports two interfaces:
+ * * RPC interface - This is RPC the interface that
+ * * Controller interface - Interrupt controllers use a
+ */
+
+struct controller_driver * controller_head;
+static int exported = 0;
+
+static struct controller_driver * add_controller(struct controller_driver * d){
+    struct controller_driver * cur;
+    if(controller_head == NULL){
+        controller_head = malloc(sizeof(struct controller_driver));
+        cur = controller_head;
+    } else if(d != NULL && d->next != NULL){
+        return add_controller(d->next);
+    } else {
+        assert(d != NULL);
+        d->next = malloc(sizeof(struct controller_driver));
+        cur = d->next;
+    }
+
+    // Initialize cur
+    cur->next = NULL;
+    cur->binding = NULL;
+    cur->label = NULL;
+    cur->class = NULL;
+    return cur;
+}
+
+/*
+ * Finds a controller for the given label/class combination.
+ * First, if a label is passed, it tries to match the label exactly, if no
+ * controller is found, it goes on to match on the class.
+ */
+static struct controller_driver *find_controller(const char *label,
+                                                 const char *class) {
+    if (label != NULL && strlen(label) > 0) {
+        for (struct controller_driver *cur = controller_head; cur != NULL;
+             cur = cur->next) {
+            if (strcmp(label, cur->label) == 0) {
+                return cur;
+            }
+        }
+    }
+    if (class != NULL && strlen(class) > 0) {
+        for (struct controller_driver *cur = controller_head; cur != NULL;
+             cur = cur->next) {
+            if (strcmp(class, cur->class) == 0) {
+                return cur;
+            }
+        }
+    }
+    return NULL;
+}
+
+struct controller_add_mapping_data {
+    char * lbl;
+    char * class;
+    int_route_controller_int_message_t in_msg;
+    int_route_controller_int_message_t out_msg;
+    struct int_route_controller_binding *binding;
+};
+
+#define INVALID_PORT -1
+#define INVALID_VECTOR ((uint64_t)-1)
+
+/**
+ * Since on ARMv7 the topolgy is easy, we don't use the SKB.
+ */
+static void driver_route_call_armv7(struct int_route_service_binding *b,
+        struct capref intsource, int irq_idx,
+        struct capref intdest){
+    INT_DEBUG("%s: enter\n", __FUNCTION__);
+
+    errval_t err;
+    uint64_t int_src_num = INVALID_VECTOR;
+    err = invoke_irqsrc_get_vec_start(intsource, &int_src_num);
+    uint64_t int_src_num_high = INVALID_VECTOR;
+    err = invoke_irqsrc_get_vec_end(intsource, &int_src_num_high);
+    if(int_src_num + irq_idx > int_src_num_high || irq_idx < 0){
+        err = SYS_ERR_IRQ_INVALID;
+        DEBUG_ERR(err, "irq_idx out of range");
+        b->tx_vtbl.route_response(b, NOP_CONT, err);
+        return;
+    }
+
+    assert(err_is_ok(err));
+    int_src_num += irq_idx;
+
+    uint64_t dest_vec = INVALID_VECTOR;
+    err = invoke_irqdest_get_vector(intdest, &dest_vec);
+    assert(err_is_ok(err));
+
+    uint64_t dest_cpu = INVALID_VECTOR;
+    err = invoke_irqdest_get_cpu(intdest, &dest_cpu);
+    assert(err_is_ok(err));
+
+    printf("Int route service: Routing request, (int=%"PRIu64") to "
+            "(cpu=%"PRIu64",vec=%"PRIu64")\n",
+            int_src_num, dest_cpu, dest_vec);
+
+
+    const char * class = "gic_dist";
+    struct controller_driver * gic_dist = find_controller(NULL, class);
+
+    if(gic_dist == NULL){
+        err = SYS_ERR_IRQ_INVALID;
+        DEBUG_ERR(err, "gic_dist controller not found!\n");
+    } else {
+        int_route_controller_int_message_t in_msg;
+        in_msg.port = int_src_num;
+        int_route_controller_int_message_t out_msg;
+        out_msg.port = dest_cpu;
+        err = int_route_controller_add_mapping__tx(gic_dist->binding,
+                BLOCKING_CONT, NULL, class, in_msg,
+                out_msg);
+    }
+
+    b->tx_vtbl.route_response(b, NOP_CONT, err);
+}
+
+static void ctrl_register_controller(struct int_route_controller_binding *_binding,
+        const char *label, const char *class) {
+    struct controller_driver * c = add_controller(controller_head);
+    c->label = malloc(strlen(label)+1);
+    assert(c->label != NULL);
+    strcpy(c->label, label);
+
+    c->class = malloc(strlen(class)+1);
+    assert(c->class != NULL);
+    strcpy(c->class, class);
+    INT_DEBUG("ctrl_register_controller, label=%s, class=%s\n",c->label, c->class);
+
+    c->binding = _binding;
+}
+
+
+static struct int_route_service_rx_vtbl driver_rx_vtbl = {
+        .route_call = driver_route_call_armv7
+
+};
+
+static struct int_route_controller_rx_vtbl ctrl_rx_vtbl = {
+        .register_controller = ctrl_register_controller
+};
+
+static errval_t driver_connect_cb(void *st, struct int_route_service_binding *b) {
+    INT_DEBUG("%s: enter\n", __FUNCTION__);
+    b->st = NULL;
+    b->rx_vtbl = driver_rx_vtbl;
+    return SYS_ERR_OK;
+
+}
+
+static errval_t ctrl_connect_cb(void *st, struct int_route_controller_binding *b) {
+    INT_DEBUG("%s: enter\n", __FUNCTION__);
+    b->st = NULL;
+    b->rx_vtbl = ctrl_rx_vtbl;
+    return SYS_ERR_OK;
+
+}
+
+static void driver_export_cb(void *st, errval_t err, iref_t iref){
+    INT_DEBUG("%s: enter\n", __FUNCTION__);
+    assert(err_is_ok(err));
+
+    err = nameservice_register("int_route_service", iref);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "nameservice_register 1 failed");
+    };
+    exported++;
+}
+
+static void ctrl_export_cb(void *st, errval_t err, iref_t iref){
+    INT_DEBUG("%s: enter\n", __FUNCTION__);
+    assert(err_is_ok(err));
+
+    err = nameservice_register("int_ctrl_service", iref);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "nameservice_register 2 failed");
+    };
+    exported++;
+}
+
+
+// The main function of this service
+int main(void) {
+    errval_t err;
+    debug_printf("Start\n");
+
+    // Export route service for PCI device drivers
+    err = int_route_service_export(NULL, driver_export_cb, driver_connect_cb,
+                                   get_default_waitset(),
+                                   IDC_EXPORT_FLAGS_DEFAULT);
+
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "int_route_service_export failed");
+    }
+
+    err = int_route_controller_export(NULL, ctrl_export_cb, ctrl_connect_cb,
+                                      get_default_waitset(),
+                                      IDC_EXPORT_FLAGS_DEFAULT);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "int_route_controller_export failed");
+    }
+
+    while (true) {
+        event_dispatch(get_default_waitset());
+    }
+
+    return 0;
+}
index 156f130..cae574e 100644 (file)
@@ -393,8 +393,10 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                        "skb",
                        "pci",
                        "memtest",
+                       "int_route",
                        "serial_kernel",
                        "serial_lpuart",
+                       "pl390_dist",
                        "fish",
                        "angler",
                        "kaluga",
index 96280b2..c1542bb 100644 (file)
 --------------------------------------------------------------------------
 
 [
-    build library { target = "pl390_dist_module",
+    build drivermodule { target = "pl390_dist_module",
                     flounderBindings = [ "int_route_controller" ],
                     cFiles = ["main.c"],
                     mackerelDevices = [ "pl390_gic_dist" ],
-                    architectures = ["armv7"]
+                    architectures = ["armv7", "armv8"]
+    },
+
+    build driverdomain {
+        target = "pl390_dist",
+        addModules = ["pl390_dist_module"], 
+        architectures = ["armv8"]
     }
+    
 ]
index bd30e29..c1e3b32 100644 (file)
@@ -48,20 +48,29 @@ static void print_regvalues(struct serial_lpuart *spc)
 static void serial_poll(struct serial_lpuart *spc)
 {
     while (lpuart_stat_rdrf_rdf(&spc->uart)) {
-        char c = lpuart_rxdata_buf_rdf((&spc->uart));
+        char c = lpuart_rxdata_buf_rdf(&spc->uart);
         if (c)
             LPUART_DEBUG("Read char=%c\n", c);
         else
             LPUART_DEBUG("Read NULL char\n");
+
         serial_input(&spc->m, &c, 1);
-        uint8_t or = lpuart_stat_or_rdf(&spc->uart);
-        if (or == 1) {
-            LPUART_DEBUG("OR FLAG IS SET\n");
+
+        if (lpuart_stat_or_rdf(&spc->uart)) {
+            debug_printf("receive buffer overrun!\n");
             lpuart_stat_or_wrf(&spc->uart, 1);
         }
     }
 }
 
+static void serial_int(void *arg)
+{
+    LPUART_DEBUG("serial_int: enter\n");
+    serial_poll((struct serial_lpuart *)arg);
+}
+
+// For using deferred to poll the device.
+__attribute__((used))
 static void serial_poll_ev(void *arg)
 {
     serial_poll((struct serial_lpuart *)arg);
@@ -77,7 +86,8 @@ static void serial_poll_ev(void *arg)
 
 
 static void hw_init(struct serial_lpuart *spc)
-{  // Disable transceiver
+{  
+    // Disable transceiver
     lpuart_ctrl_t ctrl = lpuart_ctrl_rawrd(&spc->uart);
     ctrl = lpuart_ctrl_te_insert(ctrl, 0);
     ctrl = lpuart_ctrl_re_insert(ctrl, 0);
@@ -109,23 +119,9 @@ static void hw_init(struct serial_lpuart *spc)
     ctrl = lpuart_ctrl_re_insert(ctrl, 1);
     lpuart_ctrl_wr(&spc->uart, ctrl);
     print_regvalues(spc);
-    // ENABLE INTERRUPTS
-    /*
-    //transmit interrupt enable
-     lpuart_ctrl_tie_wrf(&spc->uart,1);
-    //Transmission Complete Interrupt Enable
-    lpuart_ctrl_tcie_wrf(&spc->uart,1);
-    //Receiver Interrupt Enable
+    
+    // Receive interrupt enable
     lpuart_ctrl_rie_wrf(&spc->uart,1);
-    //Overrun Interrupt Enable
-     lpuart_ctrl_orie_wrf(&spc->uart,1);
-     //noise error interrupt enable
-     lpuart_ctrl_neie_wrf(&spc->uart,1);
-     //framing error interrupt enable
-     lpuart_ctrl_feie_wrf(&spc->uart,1);
-     //Parity Error Interrupt Enable
-     lpuart_ctrl_peie_wrf(&spc->uart,1);
-     */
 }
 
 static void serial_putc(struct serial_lpuart *spc, char c)
@@ -146,34 +142,9 @@ static void serial_write(void *m, const char *c, size_t len)
     }
 }
 
-static errval_t serial_lpuart_init(struct serial_lpuart *spc, struct capref irq_src)
-{
-    debug_printf("Hello world from serial lpuart driver\n");
-
-    // errval_t err;
-
-    // if(capref_is_null(irq_src))
-    //     USER_PANIC("serial_kernel requires an irq cap");
-
-    spc->m.output = serial_write;
-    spc->m.output_arg = spc;
-
-    // Register interrupt handler
-    // err = int_route_client_route_and_connect(irq_src, 0,
-    //        get_default_waitset(), serial_interrupt, spc);
-    // if (err_is_fail(err)) {
-    //    USER_PANIC_ERR(err, "interrupt setup failed.");
-    // }
-
-    hw_init(spc);
-
-    // offer service now we're up
-    start_service(&spc->m);
-    return SYS_ERR_OK;
-}
-
 static errval_t init(struct bfdriver_instance *bfi, uint64_t flags, iref_t *dev)
 {
+    LPUART_DEBUG("lpuart driver init\n");
     errval_t err;
     struct serial_lpuart *spc = malloc(sizeof(struct serial_lpuart));
     init_serial_common(&spc->m);
@@ -182,19 +153,32 @@ static errval_t init(struct bfdriver_instance *bfi, uint64_t flags, iref_t *dev)
     struct capref devframe_cap = { .slot = DRIVERKIT_ARGCN_SLOT_BAR0,
                                    .cnode = bfi->argcn };
     err = map_device_cap(devframe_cap, &vbase);
-    debug_printf("vbase = %p\n", vbase);
     lpuart_initialize(&spc->uart, (mackerel_addr_t)vbase);
 
-    /*  struct capref irq_src;
+    struct capref irq_src;
     irq_src.cnode = bfi->argcn;
-    irq_src.slot = PCIARG_SLOT_INT; */
-    err = serial_lpuart_init(spc, NULL_CAP);
-    assert(err_is_ok(err));
+    irq_src.slot = PCIARG_SLOT_INT; 
+
+    spc->m.output = serial_write;
+    spc->m.output_arg = spc;
+
+    // Register interrupt handler
+    err = int_route_client_route_and_connect(irq_src, 0,
+           get_default_waitset(), serial_int, spc);
+    if (err_is_fail(err)) {
+       USER_PANIC_ERR(err, "interrupt setup failed.");
+    }
+    LPUART_DEBUG("interrupt setup complete\n");
+
+    hw_init(spc);
+
+    // offer service now we're up
+    start_service(&spc->m);
     bfi->dstate = spc;
 
-    SERIAL_DEBUG("lpuart Serial driver initialized.\n");
-    debug_printf("installing handler, spc=%p\n", spc);
-    serial_poll_ev(spc);
+    LPUART_DEBUG("lpuart Serial driver initialized.\n");
+    //For using deferred events
+    //serial_poll_ev(spc);
     return SYS_ERR_OK;
 }
 
index 70a295d..cfccdfd 100644 (file)
@@ -1,10 +1,12 @@
 #include <armv8_imx8x.h>
 #include <barrelfish/barrelfish.h>
 #include <barrelfish/nameservice_client.h>
+#include <barrelfish/spawn_client.h>
 #include <skb/skb.h>
 #include <barrelfish_kpi/platform.h>
 #include <if/monitor_blocking_defs.h>
 #include "kaluga.h"
+#include <pci/pci.h>
 
 static errval_t armv8_startup_common_noacpi(void)
 {
@@ -47,6 +49,7 @@ static errval_t armv8_startup_common_noacpi(void)
     }
 
     KALUGA_DEBUG("Kaluga: wait for spawnd\n");
+    //TODO: Change this once we have support for multiple cores
     err = nameservice_blocking_lookup("spawn.0", NULL);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "wait for spawnd");
@@ -91,7 +94,8 @@ static errval_t imx8x_get_device_cap(lpaddr_t address, size_t size, struct capre
 __attribute__((used))
 static errval_t start_gpio(char*name, lpaddr_t address)
 
-{   errval_t err;
+{
+    errval_t err;
     struct module_info *mi;
     mi = find_module("imx8x_gpio");
     if(mi == NULL){
@@ -136,12 +140,21 @@ static errval_t imx8x_serial_kernel(void)
     err = default_start_function_pure(0, mi,"serial_kernel {}", &arg);
     return err;
 } 
-//serial_lpuart
+
+/* IMX8X Reference Manual page 65 */
+#define UART0_INT 257
+#define UART1_INT 258
+#define UART2_INT 259
+#define UART3_INT 260
+#define DIST_OFFSET 1000  /* First interrupt index on the distributor */
+
 __attribute__((used))
-static errval_t start_serial_lpuart(lpaddr_t address)
+static errval_t start_serial_lpuart(lpaddr_t address, uint32_t irq)
 
 {   errval_t err;
     struct module_info *mi;
+    
+    // get module
     mi = find_module("serial_lpuart");
     if(mi == NULL){
         KALUGA_DEBUG("serial_lpuart not found, not starting");
@@ -150,22 +163,44 @@ static errval_t start_serial_lpuart(lpaddr_t address)
     struct driver_argument arg;
     init_driver_argument(&arg);
     arg.module_name = "serial_lpuart";
+
+    // get device frame
     struct capref device_frame;
     err = imx8x_get_device_cap(address, 0x00010000, &device_frame);
     if(err_is_fail(err)){
         USER_PANIC_ERR(err, "get_device_cap");
     }
-    KALUGA_DEBUG("get_device_cap worked\n");
-    //transfer destination
+    KALUGA_DEBUG("got device frame for lpuart\n");
+
+
     struct capref cap = {
-            .cnode = (&arg)->argnode_ref,
+            .cnode = arg.argnode_ref,
             .slot = DRIVERKIT_ARGCN_SLOT_BAR0
     };
     err = cap_copy(cap, device_frame);
     if(err_is_fail(err)){
         USER_PANIC_ERR(err, "get_device_cap");
     }
-    // Store capability in driver_argument: See add_mem_args in start_pci.c lines 197 and following
+
+    // get irq src for lpuart
+    struct capref irq_src;
+    err = slot_alloc(&irq_src);
+    assert(err_is_ok(err));
+
+    err = sys_debug_create_irq_src_cap(irq_src, irq + DIST_OFFSET, irq + DIST_OFFSET);
+    assert(err_is_ok(err));
+
+    struct capref irq_dst = {
+        .cnode = arg.argnode_ref,
+        .slot = PCIARG_SLOT_INT 
+    };
+    err = cap_copy(irq_dst, irq_src);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err, "cap_copy\n");
+        return err;
+    }
+    KALUGA_DEBUG("got irq src cap frame for lpuart\n");
+     
     err = default_start_function_pure(0, mi, "serial_lpuart {}", &arg);
     if(err_is_fail(err)){
         USER_PANIC_ERR(err, "get_device_cap");
@@ -173,6 +208,56 @@ static errval_t start_serial_lpuart(lpaddr_t address)
     return err;
 } 
 
+static lpaddr_t platform_gic_distributor_base = 0x51a00000;
+//static lpaddr_t platform_gic_redistributor_base = 0x51b00000;
+
+static errval_t
+start_int_route_domains(void)
+{
+    errval_t err;
+    // Int route server
+    char *argv[] = {NULL};
+    err = spawn_program(0, "int_route", argv, NULL, 0, NULL); 
+    if(err_is_fail(err)){
+         DEBUG_ERR(err,"int_route start");
+         return err;
+    }
+
+    //Distributor driver
+    struct module_info *mi;
+    mi = find_module("pl390_dist");
+    if(mi == NULL){
+        KALUGA_DEBUG("pl390_dist not found, not starting\n");
+        return KALUGA_ERR_MODULE_NOT_FOUND;
+    }
+    struct driver_argument arg;
+    init_driver_argument(&arg);
+    arg.module_name = "pl390_dist";
+    struct capref device_frame;
+
+    err = imx8x_get_device_cap(platform_gic_distributor_base, 0x1000, &device_frame);
+    if(err_is_fail(err)){
+        USER_PANIC_ERR(err, "get_device_cap");
+    }
+    KALUGA_DEBUG("get_device_cap worked\n");
+    //transfer destination
+    struct capref cap = {
+            .cnode = arg.argnode_ref,
+            .slot = 0
+    };
+    err = cap_copy(cap, device_frame);
+    if(err_is_fail(err)){
+        USER_PANIC_ERR(err, "get_device_cap");
+    }
+    err = default_start_function_pure(0, mi, "gic.dist {}", &arg);
+    if(err_is_fail(err)){
+        USER_PANIC_ERR(err, "get_device_cap");
+    }
+    return err;
+
+   
+}
+
 errval_t imx8x_startup(void)
 {
     errval_t err;
@@ -180,6 +265,12 @@ errval_t imx8x_startup(void)
     if(err_is_fail(err)){
         USER_PANIC_ERR(err, "startup common");
     }
+
+    err = start_int_route_domains();
+    if(err_is_fail(err)) {
+        USER_PANIC_ERR(err, "start int_route");
+    }
+
     err = start_gpio("imx8x.gpio1 {}", 0x5D090000);
     if(err_is_fail(err) && err_no(err) != KALUGA_ERR_MODULE_NOT_FOUND) {
         USER_PANIC_ERR(err, "gpio1 start");
@@ -189,7 +280,7 @@ errval_t imx8x_startup(void)
         USER_PANIC_ERR(err, "gpio2 start");
     }
 
-    err = start_serial_lpuart(0x5A090000);
+    err = start_serial_lpuart(0x5A090000, UART3_INT);
     if(err_is_fail(err) && err_no(err) != KALUGA_ERR_MODULE_NOT_FOUND) {
         USER_PANIC_ERR(err, "imx8x serial lpuart");
     }
index 298f468..307fd6e 100644 (file)
@@ -402,6 +402,12 @@ static void get_irq_dest_cap(struct monitor_blocking_binding *b)
     }
 }
 
+#if defined(__ARM_ARCH_8A__)
+#define DISP_OFFSET 1000
+#else
+#define DISP_OFFSET 0
+#endif
+
 static void get_irq_dest_cap_arm(
         struct monitor_blocking_binding *b,
         struct capref irqsrc, int irq_idx)
@@ -416,15 +422,15 @@ static void get_irq_dest_cap_arm(
 
     if(irqsrc_cap.u.irqsrc.vec_start + irq_idx > irqsrc_cap.u.irqsrc.vec_end ||
             irq_idx < 0){
-        USER_PANIC("invalid irq_idx");
+        USER_PANIC("Invalid irq_idx");
     }
 
     struct capref dest_cap;
     slot_alloc(&dest_cap);
     err = invoke_irqtable_alloc_dest_cap(cap_irq, dest_cap,
-            irqsrc_cap.u.irqsrc.vec_start + irq_idx);
+            irqsrc_cap.u.irqsrc.vec_start + irq_idx - DISP_OFFSET);
     if(err_is_fail(err)){
-        DEBUG_ERR(err,"x");
+        printf("requested idx %d\n", irqsrc_cap.u.irqsrc.vec_start + irq_idx);
         USER_PANIC_ERR(err, "could not allocate dest cap!");
     }
 
index be239cb..20c450d 100644 (file)
 % mapf(msi_a, 100, nullMsg, 11, mem_write(110, 230))
 :- dynamic(mapf/5).        
 
+% Running on x86? irq_platform(x86) is true.
+% on arm? irq_platform(arm) is true.
+:- dynamic(irq_platform/1).        
+
 % The controller predicate describes an instance of a controller
 % See below for details.
 % controller(ControllerLabel, ControllerClass, InputRange, OutputRange)
@@ -186,8 +190,11 @@ index_ones(Index, [H | Tail]) :-
 %>> ARM
 % Controller constraints
 
-mapf_valid_class(gicv2, CtrlLabel, InPort, InMsg, OutPort, OutMsg) :-
-    OutMsg = InMsg.
+mapf_valid_class(gic_dist, CtrlLbl, InPort, InMsg, OutPort, OutMsg) :-
+    controller(CtrlLbl, _, InRange, OutRange),
+    get_min_range(InRange, MinIn),
+    OutMsg is InPort - MinIn.
+
 
 %>> X86
 % Controller constraints
@@ -429,7 +436,7 @@ print_route(Li) :-
 % TODO: Upper bound of CoreId shouldnt be hardcoded (here). 
 int_dest_port(Port) :-
     %corename(Port, _, _). % Does not work bc synchronization issues
-    Port :: [0 .. 1000],
+    Port :: [0 .. 999],
     labeling([Port]).
 
 % Returns a list of integers representing the int destinations
@@ -439,7 +446,11 @@ int_dest_port_list(Li) :-
 %>> X86
 % Returns true if this Msg is acceptable as being delivered to a destination
 int_dest_msg(Msg) :-
+    irq_platform(x86),
     Msg :: [32 .. 255].
+int_dest_msg(Msg) :-
+    irq_platform(arm),
+    Msg :: [32 .. 1019].
     
 
 % Scans all controller and sinkPortRange and returns the maximum used port number
@@ -451,7 +462,7 @@ max_used_port(OutMax) :-
     % Due to synchronization issues, we cant use the following two lines
     %findall(Ri, int_dest_port(Ri), MaxList1), 
     %append(MaxList1, MaxList2, MaxList),
-    append([1000], MaxList2, MaxList),
+    append([999], MaxList2, MaxList),
     ic:max(MaxList, OutMax).
     
 
@@ -493,6 +504,7 @@ x86_iommu_mode :-
 % It uses facts that are added by the acpi and pci discovery, hence
 % it must be run when these facts are added.
 add_x86_controllers :-
+    assert(irq_platform(x86)),
     % pic + iommu is not a valid combination...
     (x86_interrupt_model(apic) ; not(x86_iommu_mode)),
     int_dest_port_list(CpuPorts),
@@ -539,6 +551,19 @@ add_x86_controllers :-
     %    add_pcilnk_controller(GSIList, Name, _)
     %)).
 
+add_armv8_controllers :-
+    assert(irq_platform(arm)),
+    % the distributor routes SPIs in the range 32-1019
+    get_unused_range(987, DistInRange),
+    % Todo fix hardcoded CPU limit
+    get_max_range(DistInRange, DistInMax),
+    OutMin is DistInMax + 1,
+    OutMax is OutMin + 128,
+    DistOutRange = [OutMin .. OutMax],
+    get_unused_controller_label(dist, 0, Lbl),
+    assert_controller(Lbl, gic_dist, DistInRange, DistOutRange),
+    (for(S,OutMin,OutMax), for(D,0,128) do add_connection(S,D) ).
+
 
 
 %>> GENERIC