IRQ: Allow retyping of IRQSrc capability
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Mon, 10 Oct 2016 13:24:33 +0000 (15:24 +0200)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Fri, 14 Oct 2016 16:11:52 +0000 (18:11 +0200)
Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

capabilities/caps.hl
errors/errno.fugu
kernel/capabilities.c
lib/barrelfish/capabilities.c
usr/kaluga/start_pci.c

index 83d997e..ab3a5c3 100644 (file)
@@ -272,7 +272,7 @@ cap IRQDest {
     eq uint64 vector;
 };
 
-cap IRQSrc {
+cap IRQSrc from_self {
        /* IRQ Source capability.
        Represents an interrupt source. It contains a range of interrupt
        source numbers. */ 
index 27346e7..0720ced 100755 (executable)
@@ -78,6 +78,7 @@ errors kernel SYS_ERR_ {
     failure SLOTS_IN_USE        "One or more destination capability slots occupied",
     failure RETYPE_CREATE       "Error while creating new capabilities in retype",
     failure RETYPE_INVALID_OFFSET "Offset into source capability invalid for retype",
+    failure RETYPE_INVALID_OBJSIZE "Objsize invalid for retype",
     failure NO_LOCAL_COPIES     "No copies of specified capability in local MDB",
     failure RETRY_THROUGH_MONITOR "There is a remote copy of the capability, monitor must be involved to perform a cross core agreement protocol",
     failure TYPE_NOT_CREATABLE  "Specified capability type is not creatable at runtime. Consider retyping it from another capability.",
index cc727da..3585c90 100644 (file)
@@ -1010,11 +1010,12 @@ static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, gensize_t size,
         temp_cap.u.io.end   = 65535;
         /* fall through */
 
+    case ObjType_IRQSrc:
+        /* Caller has to set vec_start and vec_end */
     case ObjType_Kernel:
     case ObjType_IPI:
     case ObjType_IRQTable:
     case ObjType_IRQDest:
-    case ObjType_IRQSrc:
     case ObjType_EndPoint:
     case ObjType_Notify_IPI:
     case ObjType_PerfMon:
@@ -1423,6 +1424,7 @@ errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
     gensize_t size = 0;
     errval_t err;
     bool do_range_check = false;
+    struct capability *src_cap = &src_cte->cap;
 
     /* Parameter checking */
     assert(type != ObjType_Null);
@@ -1436,10 +1438,10 @@ errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
             __FUNCTION__, type, offset, objsize, count);
 
     /* check that offset into source cap is multiple of BASE_PAGE_SIZE */
-    if (offset % BASE_PAGE_SIZE != 0) {
+    if (src_cap->type != ObjType_IRQSrc && offset % BASE_PAGE_SIZE != 0) {
         return SYS_ERR_RETYPE_INVALID_OFFSET;
     }
-    assert(offset % BASE_PAGE_SIZE == 0);
+    assert(offset % BASE_PAGE_SIZE == 0 || src_cap->type == ObjType_IRQSrc);
 
     // check that size is multiple of BASE_PAGE_SIZE for mappable types
     gensize_t base_size = BASE_PAGE_SIZE;
@@ -1471,7 +1473,6 @@ errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
         return SYS_ERR_RETYPE_MAPPING_EXPLICIT;
     }
 
-    struct capability *src_cap = &src_cte->cap;
 
     TRACE_CAP_MSG("retyping", src_cte);
 
@@ -1498,9 +1499,10 @@ errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
            src_cap->type == ObjType_RAM ||
            src_cap->type == ObjType_Dispatcher ||
            src_cap->type == ObjType_Frame ||
-           src_cap->type == ObjType_DevFrame);
+           src_cap->type == ObjType_DevFrame ||
+           src_cap->type == ObjType_IRQSrc);
 
-    if (src_cap->type != ObjType_Dispatcher) {
+    if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
         base = get_address(src_cap);
         size = get_size(src_cap);
     }
@@ -1527,7 +1529,7 @@ errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
 
     /* check that we can create `count` objs from `offset` in source, and
      * update base accordingly */
-    if (src_cap->type != ObjType_Dispatcher) {
+    if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
         // TODO: convince ourselves that this is the only condition on offset
         if (offset + count * objsize > get_size(src_cap)) {
             debug(SUBSYS_CAPS, "caps_retype: cannot create all %zu objects"
@@ -1602,10 +1604,43 @@ errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
         }
     }
 
+    // IRQSrc specific checks
+    uint64_t vec_start_new = offset;
+    uint64_t vec_end_new = objsize;
+    if(src_cap->type == ObjType_IRQSrc){
+
+        // Check new range is valid
+        if(vec_start_new > vec_end_new){
+            return SYS_ERR_RETYPE_INVALID_OFFSET;
+        }
+        
+        // Check vec_start_new in range
+        if(!(src_cap->u.irqsrc.vec_start <= vec_start_new &&
+                vec_start_new <= src_cap->u.irqsrc.vec_end)){
+            return SYS_ERR_RETYPE_INVALID_OFFSET;
+        }
+
+        // Check vec_end_new in range
+        if(!(src_cap->u.irqsrc.vec_start <= vec_end_new &&
+                vec_end_new <= src_cap->u.irqsrc.vec_end)){
+            return SYS_ERR_RETYPE_INVALID_OBJSIZE;
+        }
+    }
+
+
     /* create new caps */
     struct cte *dest_cte =
         caps_locate_slot(get_address(dest_cnode), dest_slot);
-    err = caps_create(type, base, size, objsize, count, my_core_id, dest_cte);
+    if(type == ObjType_IRQSrc){
+        // Pass special arguments
+        err = caps_create(type, 0, 0, 0, 1, my_core_id, dest_cte);
+        if(err_is_ok(err)){
+            dest_cte->cap.u.irqsrc.vec_start = vec_start_new;
+            dest_cte->cap.u.irqsrc.vec_end = vec_end_new;
+        }
+    } else {
+        err = caps_create(type, base, size, objsize, count, my_core_id, dest_cte);
+    }
     if (err_is_fail(err)) {
         debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
         return err_push(err, SYS_ERR_RETYPE_CREATE);
index 03d0073..c651225 100644 (file)
@@ -266,6 +266,9 @@ static errval_t cap_revoke_remote(struct capref root, capaddr_t src, uint8_t lev
  *                      (ignored for fixed-size objects)
  * \param count         The number of new objects to create
  *
+ * When retyping IRQSrc capabilities, offset and objsize represent the start
+ * and end of the to be created interrupt range. Count must be 1 for IRQSrc.
+ *
  * Retypes (part of) the given source capability into a number of new
  * capabilities, which may be of the same or of different type. The new
  * capabilities are created in the slots starting from dest_start, which must
index 5b18de7..2e4bfad 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "kaluga.h"
 
+static struct capref all_irq_cap;
+
 static void pci_change_event(octopus_mode_t mode, char* device_record, void* st);
 
 static void spawnd_up_event(octopus_mode_t mode, char* spawnd_record, void* st)
@@ -156,7 +158,9 @@ static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
             struct capref cap;
             cap.cnode = argnode_ref;
             cap.slot = 0;
-            err = sys_debug_create_irq_src_cap(cap, start, end);
+            //err = sys_debug_create_irq_src_cap(cap, start, end);
+            err = cap_retype(cap, all_irq_cap, start, ObjType_IRQSrc, 
+                    end, 1);
             if(err_is_fail(err)){
                 USER_PANIC_ERR(err, "Could not create int_src cap");
             }
@@ -275,6 +279,14 @@ static void bridge_change_event(octopus_mode_t mode, char* bridge_record, void*
 
 errval_t watch_for_pci_root_bridge(void)
 {
+
+    // TODO: Get all_irq_cap from somewhere and remove sys_debug call
+    errval_t err;
+    err = slot_alloc(&all_irq_cap);
+    assert(err_is_ok(err));
+    err = sys_debug_create_irq_src_cap(all_irq_cap, 0, 65536);
+    assert(err_is_ok(err));
+    
     static char* root_bridge = "r'hw\\.pci\\.rootbridge\\.[0-9]+' { "
                                " bus: _, device: _, function: _, maxbus: _,"
                                " acpi_node: _ }";