Moved interrupt vector allocation into cpu driver.
authorSimon Gerber <simon.gerber@inf.ethz.ch>
Wed, 22 Jan 2014 12:50:50 +0000 (13:50 +0100)
committerGerd Zellweger <mail@gerdzellweger.com>
Tue, 14 Oct 2014 06:50:08 +0000 (08:50 +0200)
errors/errno.fugu
include/arch/x86_64/barrelfish/invocations_arch.h
include/barrelfish_kpi/capabilities.h
kernel/arch/x86_64/irq.c
kernel/arch/x86_64/syscall.c
kernel/include/arch/x86_64/irq.h
usr/monitor/monitor_rpc_server.c

index 7cf4279..b369411 100644 (file)
@@ -83,6 +83,7 @@ errors kernel SYS_ERR_ {
     failure IRQ_NOT_ENDPOINT    "Specified capability is not an endpoint cap",
     failure IRQ_NO_LISTENER     "No listener on specified endpoint cap", // ??
     failure IRQ_INVALID         "Invalid interrupt number",
+    failure IRQ_NO_FREE_VECTOR  "Unable to allocate vector",
 
     // IO capability
     failure IO_PORT_INVALID     "IO port out of range",
index 52b3d3f..0bb545d 100644 (file)
@@ -320,6 +320,18 @@ invoke_dispatcher_setup_guest(struct capref dispatcher,
                        get_cap_addr(guest_control_cap)).error;
 }
 
+
+static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc);
+    if (err_is_ok(ret.error)) {
+        *retirq = ret.value;
+    } else {
+        *retirq = 0;
+    }
+    return ret.error;
+}
+
 static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq,
                                            struct capref ep)
 {
index c0114ba..2d7605a 100644 (file)
@@ -224,6 +224,7 @@ enum frame_cmd {
  * IRQ Table capability commands.
  */
 enum irqtable_cmd {
+    IRQTableCmd_Alloc,  ///< Allocate new vector (XXX: HACK: this is x86 specific)
     IRQTableCmd_Set,    ///< Set endpoint for IRQ# notifications
     IRQTableCmd_Delete  ///< Remove notification endpoint for IRQ#
 };
index 2f00831..1e00e4f 100644 (file)
@@ -455,6 +455,24 @@ static void send_user_interrupt(int irq)
 #endif
 }
 
+errval_t irq_table_alloc(int *outvec)
+{
+    assert(outvec);
+    // XXX: this is O(n)
+    int i;
+    for (i = 0; i < NDISPATCH; i++) {
+        if (kcb_current->irq_dispatch[i].cap.type == ObjType_Null)
+            break;
+    }
+    if (i == NDISPATCH) {
+        *outvec = -1;
+        return SYS_ERR_IRQ_NO_FREE_VECTOR;
+    } else {
+        *outvec = i;
+        return SYS_ERR_OK;
+    }
+}
+
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
 {
     errval_t err;
index 2c099d1..555c130 100644 (file)
@@ -724,6 +724,17 @@ static struct sysret handle_trace_setup(struct capability *cap,
     return SYSRET(SYS_ERR_OK);
 }
 
+static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    struct sysret ret;
+    int outvec;
+    ret.error = irq_table_alloc(&outvec);
+    ret.value = outvec;
+    return ret;
+}
+
+
 static struct sysret handle_irq_table_set(struct capability *to, int cmd,
                                           uintptr_t *args)
 {
@@ -974,6 +985,7 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [KernelCmd_Suspend_kcb_sched]   = kernel_suspend_kcb_sched,
     },
     [ObjType_IRQTable] = {
+        [IRQTableCmd_Alloc] = handle_irq_table_alloc,
         [IRQTableCmd_Set] = handle_irq_table_set,
         [IRQTableCmd_Delete] = handle_irq_table_delete
     },
index 7409943..f603a7a 100644 (file)
@@ -158,6 +158,7 @@ struct task_state_segment {
 
 void setup_default_idt(void);
 
+errval_t irq_table_alloc(int *outvec);
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint);
 errval_t irq_table_delete(unsigned int nidt);
 
index 5df8afc..19b99e4 100644 (file)
@@ -501,13 +501,17 @@ static void arm_irq_handle_call(struct monitor_blocking_binding *b,
 static void irq_handle_call(struct monitor_blocking_binding *b, struct capref ep)
 {
     /* allocate a new slot in the IRQ table */
-    // XXX: probably want to be able to reuse vectors! :)
-    static int nextvec = 0;
-    int vec = nextvec++;
+    int vec;
+    errval_t err, err2;
+    err = invoke_irqtable_alloc_vector(cap_irq, &vec);
+    if (err_is_fail(err)) {
+        err2 = b->tx_vtbl.irq_handle_response(b, NOP_CONT, err, 0);
+    }
+    // we got a vector
 
     /* set it and reply */
-    errval_t err = invoke_irqtable_set(cap_irq, vec, ep);
-    errval_t err2 = b->tx_vtbl.irq_handle_response(b, NOP_CONT, err, vec);
+    err = invoke_irqtable_set(cap_irq, vec, ep);
+    err2 = b->tx_vtbl.irq_handle_response(b, NOP_CONT, err, vec);
     assert(err_is_ok(err2));
 }