IRQ: Add range to IRQSrc cap
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Fri, 7 Oct 2016 15:14:07 +0000 (17:14 +0200)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Fri, 14 Oct 2016 16:11:52 +0000 (18:11 +0200)
To prepare for MSIx, we change the IRQSrc cap so that it does not
represent a single interrupt source but a whole range. This commit
changes it to a range.

Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

19 files changed:
capabilities/caps.hl
include/arch/x86_32/barrelfish/invocations_arch.h
include/barrelfish/invocations.h
include/barrelfish/sys_debug.h
include/barrelfish_kpi/capabilities.h
kernel/arch/x86_32/irq.c
kernel/arch/x86_64/irq.c
kernel/arch/x86_64/syscall.c
kernel/include/arch/x86_64/irq.h
lib/barrelfish/arch/aarch64/sys_debug.c
lib/barrelfish/arch/arm/sys_debug.c
lib/barrelfish/arch/x86/sys_debug.c
lib/barrelfish/debug.c
lib/int_route/server/init.c
lib/pci/pci_client.c
usr/kaluga/start_pci.c
usr/kaluga/x86.c
usr/pci/pci_service.c
usr/skb/programs/irq_routing_new.pl

index da3e1fe..83d997e 100644 (file)
@@ -265,14 +265,19 @@ cap IRQTable is_always_copy {
 };
 
 cap IRQDest {
+       /* IRQ Destination capability.
+       Represents a slot in a CPUs int vector table.
+       Can be connected to a LMP endpoint to recv this interrupt. */
     eq uint64 cpu;
     eq uint64 vector;
 };
 
 cap IRQSrc {
-       /* IRQ capability. Represents an interrupt vector at an interrupt controller. */
-       eq uint64 vector;
-       eq uint64 controller;
+       /* IRQ Source capability.
+       Represents an interrupt source. It contains a range of interrupt
+       source numbers. */ 
+       eq uint64 vec_start;
+       eq uint64 vec_end;
 };
 
 cap IO {
index 993eb5d..bb0701a 100644 (file)
@@ -481,19 +481,22 @@ static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t
     return ret.error;
 }
 
-static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
+static inline errval_t invoke_irqsrc_get_vec_start(struct capref irqcap, uint32_t * out_vec)
 {
-    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
-    *out_vec = ret.value;
-    return ret.error;
+    USER_PANIC("NYI");
+    return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static inline errval_t invoke_irqsrc_get_vec_end(struct capref irqcap, uint32_t * out_vec)
+{
+    USER_PANIC("NYI");
+    return LIB_ERR_NOT_IMPLEMENTED;
 }
 
 static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
 {
-    uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
-    capaddr_t dcn_addr = get_cnode_addr(dest_cap);
-    struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
-    return ret.error;
+    USER_PANIC("NYI");
+    return LIB_ERR_NOT_IMPLEMENTED;
 }
 
 /**
index 99a309d..b35b320 100644 (file)
@@ -320,9 +320,16 @@ static inline errval_t invoke_irqdest_get_cpu(struct capref irqcap, uint64_t * o
     return ret.error;
 }
 
-static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint64_t * out_vec)
+static inline errval_t invoke_irqsrc_get_vec_start(struct capref irqcap, uint64_t * out_vec)
 {
-    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
+    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVecStart);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqsrc_get_vec_end(struct capref irqcap, uint64_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVecEnd);
     *out_vec = ret.value;
     return ret.error;
 }
index 9d6909d..d3d4cf7 100644 (file)
@@ -44,7 +44,7 @@ errval_t sys_debug_hardware_timer_read(uintptr_t* ret);
 errval_t sys_debug_hardware_timer_hertz_read(uintptr_t* ret);
 errval_t sys_debug_hardware_global_timer_read(uint64_t *ret);
 errval_t sys_debug_get_apic_ticks_per_sec(uint32_t *ret);
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi);
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start, uint64_t end);
 
 #ifdef ENABLE_FEIGN_FRAME_CAP
 errval_t sys_debug_feign_frame_cap(struct capref slot, lpaddr_t base,
index f338e8c..5a5e43e 100644 (file)
@@ -483,7 +483,8 @@ enum irqdest_cmd {
  */
 
 enum irqsrc_cmd {
-    IRQSrcCmd_GetVector   ///< Return vector and controller saved in this cap.
+    IRQSrcCmd_GetVecStart,   ///< Return vector range start
+    IRQSrcCmd_GetVecEnd   ///< Return vector range high
 };
 
 
index 8330d0b..60b3a07 100644 (file)
@@ -443,7 +443,8 @@ errval_t irq_table_alloc(int *outvec)
     }
 }
 
-errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi)
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn,
+        capaddr_t out_cap_addr, uint64_t start, uint64_t end)
 {
     // This method is a hack to forge a irq src cap for the given GSI targeting the ioapic
     errval_t err;
@@ -451,9 +452,8 @@ errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t ou
     memset(&out_cap, 0, sizeof(struct cte));
 
     out_cap.cap.type = ObjType_IRQSrc;
-    out_cap.cap.u.irqsrc.vector = gsi;
-    const uint32_t ioapic_controller_id = 1000;
-    out_cap.cap.u.irqsrc.controller = ioapic_controller_id;
+    out_cap.cap.u.irqsrc.vec_start = start;
+    out_cap.cap.u.irqsrc.vec_end = end;
 
     struct cte * cn;
     err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_vbits, &cn, CAPRIGHTS_WRITE);
index 62194fb..f8b179c 100644 (file)
@@ -513,20 +513,21 @@ errval_t irq_table_alloc(int *outvec)
     }
 }
 
-errval_t irq_debug_create_src_cap(uint8_t dcn_level, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi)
+/* Create a src cap for one specific interrupt. vec_start = vec_end = gsi */
+errval_t irq_debug_create_src_cap(uint8_t dcn_level, capaddr_t dcn,
+        capaddr_t out_cap_addr, uint64_t start, uint64_t end)
 {
-    // This method is a hack to forge a irq src cap for the given GSI targeting the ioapic
     errval_t err;
     struct cte out_cap;
     memset(&out_cap, 0, sizeof(struct cte));
 
     out_cap.cap.type = ObjType_IRQSrc;
-    out_cap.cap.u.irqsrc.vector = gsi;
-    const uint32_t ioapic_controller_id = 1000;
-    out_cap.cap.u.irqsrc.controller = ioapic_controller_id;
+    out_cap.cap.u.irqsrc.vec_start = start;
+    out_cap.cap.u.irqsrc.vec_end = end;
 
     struct cte * cn;
-    err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_level, &cn, CAPRIGHTS_WRITE);
+    err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_level, &cn,
+            CAPRIGHTS_WRITE);
     if(err_is_fail(err)){
         return err;
     }
index cca6c77..2c6e7a4 100644 (file)
@@ -845,12 +845,22 @@ static struct sysret handle_trace_setup(struct capability *cap,
     return SYSRET(SYS_ERR_OK);
 }
 
-static struct sysret handle_irqsrc_get_vector(struct capability * to, int cmd,
+static struct sysret handle_irqsrc_get_vec_start(struct capability * to, int cmd,
         uintptr_t *args)
 {
     struct sysret ret;
     ret.error = SYS_ERR_OK;
-    ret.value = to->u.irqsrc.vector;
+    ret.value = to->u.irqsrc.vec_start;
+    return ret;
+
+}
+
+static struct sysret handle_irqsrc_get_vec_end(struct capability * to, int cmd,
+        uintptr_t *args)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqsrc.vec_end;
     return ret;
 
 }
@@ -1258,7 +1268,8 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [IRQDestCmd_GetCpu] = handle_irqdest_get_cpu
        },
        [ObjType_IRQSrc] = {
-        [IRQSrcCmd_GetVector] = handle_irqsrc_get_vector,
+        [IRQSrcCmd_GetVecStart] = handle_irqsrc_get_vec_start,
+        [IRQSrcCmd_GetVecEnd] = handle_irqsrc_get_vec_end
        },
     [ObjType_IRQTable] = {
         [IRQTableCmd_Alloc] = handle_irq_table_alloc,
@@ -1558,7 +1569,8 @@ struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
             break;
 
         case DEBUG_CREATE_IRQ_SRC_CAP:
-            retval.error = irq_debug_create_src_cap(arg1, args[0], args[1], args[2]);
+            retval.error = irq_debug_create_src_cap(arg1, args[0], args[1],
+                    args[2], args[3]);
             break;
 
         default:
index 1413a2a..6df65af 100644 (file)
@@ -164,7 +164,9 @@ errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint);
 errval_t irq_table_delete(unsigned int nidt);
 struct kcb;
 errval_t irq_table_notify_domains(struct kcb *kcb);
-errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr);
-errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi);
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn,
+        capaddr_t out_cap_addr);
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn,
+        capaddr_t out_cap_addr, uint64_t start, uint64_t end);
 
 #endif
index 28ec71b..79ffd5b 100644 (file)
@@ -36,13 +36,14 @@ errval_t sys_debug_hardware_timer_read(uintptr_t* v)
     return sr.error;
 }
 
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start,
+        uint64_t end)
 {
     uint8_t dcn_level = get_cnode_level(cap);
     capaddr_t dcn_addr = get_cnode_addr(cap);
 
-    struct sysret sr = syscall6(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP,
-                                dcn_level, dcn_addr, cap.slot, gsi);
+    struct sysret sr = syscall7(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP,
+                                dcn_level, dcn_addr, cap.slot, start, end);
     return sr.error;
 }
 
index 2aa7553..4f1e54b 100644 (file)
@@ -63,7 +63,8 @@ errval_t sys_debug_hardware_global_timer_read(uint64_t *ret)
     return sr.error;
 }
 
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start,
+        uint64_t end)
 {
     assert(!"NYI");
     return SYS_ERR_OK;
index e4a96ce..746e26c 100644 (file)
@@ -27,14 +27,14 @@ errval_t sys_debug_get_tsc_per_ms(uint64_t *ret)
     return sr.error;
 }
 
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start, uint64_t end)
 {
     // XXX: check this
     uint8_t dcn_level = get_cnode_level(cap);
     capaddr_t dcn_addr = get_cnode_addr(cap);
 
-    struct sysret sr = syscall6(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP, dcn_level, dcn_addr,
-        cap.slot, gsi);
+    struct sysret sr = syscall7(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP, dcn_level, dcn_addr,
+        cap.slot, start, end);
     return sr.error;
 }
 
index 9efa533..837000d 100644 (file)
@@ -355,8 +355,8 @@ int debug_print_cap(char *buf, size_t len, struct capability *cap)
         return snprintf(buf, len, "IRQTable cap");
 
     case ObjType_IRQSrc:
-        return snprintf(buf, len, "IRQSrc cap (vec: %"PRIu64")",
-                cap->u.irqsrc.vector);
+        return snprintf(buf, len, "IRQSrc cap (vec: %"PRIu64"-%"PRIu64")",
+                cap->u.irqsrc.vec_start, cap->u.irqsrc.vec_end);
 
     case ObjType_IRQDest:
         return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", cpu: %"PRIu64")",
index fdd82e3..0cf1234 100644 (file)
@@ -195,7 +195,20 @@ static void driver_route_call(struct int_route_service_binding *b,
     errval_t err;
 
     uint64_t int_src_num = INVALID_VECTOR;
-    err = invoke_irqsrc_get_vector(intsource, &int_src_num);
+    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);
+
+    // TODO: Maybe it would be better to pass a IRQ offset into 
+    // the capability to the route call. So that the client
+    // doesnt have to do retype all the time.
+    if(int_src_num != int_src_num_high){
+        err = SYS_ERR_IRQ_INVALID;
+        DEBUG_ERR(err, "IrqSrc cap must contain only one vec");
+        b->tx_vtbl.route_response(b, NOP_CONT, err);
+        return;
+    }
+
     assert(err_is_ok(err));
 
     uint64_t dest_vec = INVALID_VECTOR;
index 775089a..d8aba11 100644 (file)
@@ -136,8 +136,9 @@ static errval_t setup_int_routing(int irq_idx, interrupt_handler_fn handler,
         return err;
     }
 
+    // For now, we just use the first vector passed to the driver.
     uint64_t gsi = INVALID_VECTOR;
-    err = invoke_irqsrc_get_vector(irq_src_cap, &gsi);
+    err = invoke_irqsrc_get_vec_start(irq_src_cap, &gsi);
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "Could not lookup GSI vector");
         return err;
index a4385cb..5b18de7 100644 (file)
@@ -113,8 +113,8 @@ static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
         int_arg.int_range_start = 1000;
         int_arg.int_range_end = 1004;
         coreid_t offset;
-        err = skb_read_output("driver(%"SCNu8", %"SCNu8", %"SCNu8", %[^,], %"SCNu8")", &core, &multi, &offset,
-                binary_name, &int_model_in);
+        err = skb_read_output("driver(%"SCNu8", %"SCNu8", %"SCNu8", %[^,], "
+                "%"SCNu8")", &core, &multi, &offset, binary_name, &int_model_in);
         if(err_is_fail(err)){
             USER_PANIC_SKB_ERR(err, "Could not parse SKB output.\n");
         }
@@ -140,31 +140,25 @@ static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
             if(nl) *nl = '\0';
             intcaps_debug_msg[99] = '\0';
 
+            uint64_t start=0, end=0;
+            err = skb_read_output("%"SCNu64", %"SCNu64, &start, &end);
             if(err_is_fail(err)){
                 DEBUG_SKB_ERR(err, "Could not parse SKB output. Not starting driver.\n");
                 goto out;
             }
-            struct list_parser_status pa_sta;
-            skb_read_list_init(&pa_sta);
-            int int_num;
+
             struct cnoderef argnode_ref;
             err = cnode_create_l2(&driver_arg.arg_caps, &argnode_ref);
-
             if(err_is_fail(err)){
-                USER_PANIC_ERR(err, "Could not create int_src cap");
+                USER_PANIC_ERR(err, "Could not cnode_create_l2");
             }
 
-            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");
-                }
+            struct capref cap;
+            cap.cnode = argnode_ref;
+            cap.slot = 0;
+            err = sys_debug_create_irq_src_cap(cap, start, end);
+            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 (%s) with MSI interrupts\n", binary_name);
index 9a5f784..48b7587 100644 (file)
@@ -61,7 +61,7 @@ static errval_t start_serial(void){
         struct capref cap;
         cap.cnode = argnode_ref;
         cap.slot = 0;
-        err = sys_debug_create_irq_src_cap(cap, int_nr);
+        err = sys_debug_create_irq_src_cap(cap, int_nr, int_nr);
 
         if(err_is_fail(err)){
             DEBUG_ERR(err, "Could not create int_src cap");
@@ -111,7 +111,7 @@ static errval_t start_lpc_timer(void){
         struct capref cap;
         cap.cnode = argnode_ref;
         cap.slot = 0;
-        err = sys_debug_create_irq_src_cap(cap, int_nr);
+        err = sys_debug_create_irq_src_cap(cap, int_nr, int_nr);
 
         if(err_is_fail(err)){
             DEBUG_ERR(err, "Could not create int_src cap");
index b2bff83..c6cf859 100644 (file)
@@ -213,7 +213,7 @@ static void get_irq_cap_handler(struct pci_binding *b, uint16_t idx){
 
     PCI_DEBUG("pci: Interrupt enabled.\n");
 
-    err = sys_debug_create_irq_src_cap(cap, irq);
+    err = sys_debug_create_irq_src_cap(cap, irq, irq);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "create irq src cap failed.");
     }
index f1ea29f..2517db8 100644 (file)
@@ -561,17 +561,16 @@ find_prt_entry(Pin, Addr, PrtEntry) :-
 
 % when using legacy interrupts, the PCI card does not need a controller
 % however it needs to be aware of the int numbers to use.
+% This function returns always only one interrupt, but for compatibility,
+% it returns a Lo,Hi tuple
 % A = addr(Bus,Device,Function)
-get_pci_legacy_int_range(A, Li) :-
-    ((
-        device(_, A, _, _, _, _, _, Pin),
-        find_prt_entry(Pin, A, X),
-        prt_entry_to_num(X, IntNu),
-        LiT = [int(IntNu)]
-    ) ; (
-        LiT = [none]
-    )),
-    filter_none(LiT,Li).
+% LiR = (Lo,Hi)
+get_pci_legacy_int_range(A, (Lo,Hi)) :-
+    device(_, A, _, _, _, _, _, Pin),
+    find_prt_entry(Pin, A, X),
+    prt_entry_to_num(X, IntNu),
+    Lo = IntNu,
+    Hi = IntNu.
 
 % Translates fixed x86 legacy interrupt numbers to internal interrupt source number.
 % It first translates Legacy to GSI, then GSI to internal.