Added ability to create certain capabilities at runtime (without using retype).
authorRaphael Fuchs <raphaelfuchs@student.ethz.ch>
Mon, 18 Jun 2012 09:04:50 +0000 (11:04 +0200)
committerRaphael Fuchs <raphaelfuchs@student.ethz.ch>
Mon, 18 Jun 2012 09:04:50 +0000 (11:04 +0200)
The CNode capabilities are enhanced with a new invocation 'CNodeCmd_Create',
allowing to create new capabilities at runtime.
Only certain types of capabilities can be created this way. If invoked on a
capability type, that is not creatable at runtime the error
SYS_ERR_NOT_CREATABLE is emitted.

errors/errno.fugu
include/arch/x86_32/barrelfish/invocations_arch.h
include/arch/x86_64/barrelfish/invocations_arch.h
include/barrelfish/capabilities.h
include/barrelfish_kpi/capabilities.h
kernel/arch/x86_32/syscall.c
kernel/arch/x86_64/syscall.c
kernel/include/syscall.h
kernel/syscall.c
lib/barrelfish/capabilities.c

index c37baef..05565fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, ETH Zurich.
+ * Copyright (c) 2009, 2010, 2011, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -61,6 +61,7 @@ errors kernel SYS_ERR_ {
     failure RETYPE_CREATE       "Error while creating new capabilities in 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.",
 
     // errors specific to page mapping
     failure VNODE_SLOT_INVALID  "Destination slot exceeds size of page table",
index de8e81f..8a4b3ed 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -55,6 +55,47 @@ static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t cap,
 }
 
 /**
+ * \brief Create a capability.
+ *
+ * Create a new capability of type 'type' and size 'objbits'. The new cap will
+ * be placed in the slot 'dest_slot' of the CNode located at 'dest_cnode_cptr'
+ * in the address space rooted at 'root'.
+ *
+ * See also cap_create(), which wraps this.
+ *
+ * \param root            Capability of the CNode to invoke.
+ * \param type            Kernel object type to create.
+ * \param objbits         Size of created object
+ *                        (ignored for fixed-size objects)
+ * \param dest_cnode_cptr Address of CNode cap, where newly created cap will be
+ *                        placed into.
+ * \param dest_slot       Slot in CNode cap to place new cap.
+ * \param dest_vbits      Number of valid address bits in 'dest_cnode_cptr'.
+ *
+ * \return Error code
+ */
+static inline errval_t invoke_cnode_create(struct capref root,
+                                           enum objtype type, uint8_t objbits,
+                                           capaddr_t dest_cnode_cptr,
+                                           capaddr_t dest_slot,
+                                           uint8_t dest_vbits)
+{
+    /* Pack arguments */
+    assert(dest_cnode_cptr != CPTR_NULL);
+
+    uint8_t invoke_bits = get_cap_valid_bits(root);
+    capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits);
+
+    assert(type <= 0xffff);
+    assert(objbits <= 0xff);
+    assert(dest_vbits <= 0xff);
+
+    return syscall5((invoke_bits << 16) | (CNodeCmd_Create << 8) | SYSCALL_INVOKE,
+                    invoke_cptr, (type << 16) | (objbits << 8) | dest_vbits,
+                    dest_cnode_cptr, dest_slot).error;
+}
+
+/**
  * \brief "Mint" a capability.
  *
  * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within
index 4e4ea9a..46b7f2c 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -87,6 +87,37 @@ static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t cap,
 }
 
 /**
+ * \brief Create a capability.
+ *
+ * Create a new capability of type 'type' and size 'objbits'. The new cap will
+ * be placed in the slot 'dest_slot' of the CNode located at 'dest_cnode_cptr'
+ * in the address space rooted at 'root'.
+ *
+ * See also cap_create(), which wraps this.
+ *
+ * \param root            Capability of the CNode to invoke.
+ * \param type            Kernel object type to create.
+ * \param objbits         Size of created object
+ *                        (ignored for fixed-size objects)
+ * \param dest_cnode_cptr Address of CNode cap, where newly created cap will be
+ *                        placed into.
+ * \param dest_slot       Slot in CNode cap to place new cap.
+ * \param dest_vbits      Number of valid address bits in 'dest_cnode_cptr'.
+ *
+ * \return Error code
+ */
+static inline errval_t invoke_cnode_create(struct capref root,
+                                           enum objtype type, uint8_t objbits,
+                                           capaddr_t dest_cnode_cptr,
+                                           capaddr_t dest_slot,
+                                           uint8_t dest_vbits)
+{
+    assert(dest_cnode_cptr != CPTR_NULL);
+    return cap_invoke6(root, CNodeCmd_Create, type, objbits, dest_cnode_cptr,
+                       dest_slot, dest_vbits).error;
+}
+
+/**
  * \brief "Mint" a capability.
  *
  * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within
index 6cbad8f..90eec2f 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -33,6 +33,7 @@ errval_t cnode_create_from_mem(struct capref dest, struct capref src,
 
 errval_t cap_retype(struct capref dest_start, struct capref src,
                enum objtype new_type, uint8_t size_bits);
+errval_t cap_create(struct capref dest, enum objtype type, uint8_t size_bits);
 errval_t cap_delete(struct capref cap);
 errval_t cap_revoke(struct capref cap);
 struct cspace_allocator;
index 66ab3aa..24432c3 100644 (file)
@@ -105,6 +105,7 @@ enum cnode_cmd {
     CNodeCmd_Retype,    ///< Retype capability
     CNodeCmd_Delete,    ///< Delete capability
     CNodeCmd_Revoke,    ///< Revoke capability
+    CNodeCmd_Create,    ///< Create capability
 };
 
 enum vnode_cmd {
index 74ac0fa..e303786 100644 (file)
@@ -133,7 +133,19 @@ static struct sysret handle_retype(struct capability *root, int cmd, uintptr_t *
     return handle_retype_common(root, args, false);
 }
 
+static struct sysret handle_create(struct capability *root, int cmd,
+                                   uintptr_t *args)
+{
+    /* Retrieve arguments */
+    enum objtype type         = args[0] >> 16;
+    uint8_t objbits           = (args[0] >> 8) & 0xff;
+    capaddr_t dest_cnode_cptr = args[1];
+    capaddr_t dest_slot       = args[2];
+    uint8_t dest_vbits        = args[0] & 0xff;
 
+    return sys_create(root, type, objbits, dest_cnode_cptr, dest_slot,
+                      dest_vbits);
+}
 
 /**
  * Common code for copying and minting except the mint flag and param passing
@@ -638,6 +650,7 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [CNodeCmd_Copy]   = handle_copy,
         [CNodeCmd_Mint]   = handle_mint,
         [CNodeCmd_Retype] = handle_retype,
+        [CNodeCmd_Create] = handle_create,
         [CNodeCmd_Delete] = handle_delete,
         [CNodeCmd_Revoke] = handle_revoke,
     },
index 26a6d79..7c07530 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -86,6 +86,20 @@ static struct sysret handle_retype(struct capability *root,
     return handle_retype_common(root, args, false);
 }
 
+static struct sysret handle_create(struct capability *root,
+                                   int cmd, uintptr_t *args)
+{
+    /* Retrieve arguments */
+    enum objtype type         = args[0];
+    uint8_t objbits           = args[1];
+    capaddr_t dest_cnode_cptr = args[2];
+    cslot_t dest_slot         = args[3];
+    uint8_t dest_vbits        = args[4];
+
+    return sys_create(root, type, objbits, dest_cnode_cptr, dest_slot,
+                      dest_vbits);
+}
+
 
 /**
  * Common code for copying and minting except the mint flag and param passing
@@ -655,6 +669,7 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [CNodeCmd_Copy]   = handle_copy,
         [CNodeCmd_Mint]   = handle_mint,
         [CNodeCmd_Retype] = handle_retype,
+        [CNodeCmd_Create] = handle_create,
         [CNodeCmd_Delete] = handle_delete,
         [CNodeCmd_Revoke] = handle_revoke,
     },
index 2e8c8ef..294bb4e 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -34,6 +34,9 @@ struct sysret
 sys_retype(struct capability *root, capaddr_t source_cptr, enum objtype type,
            uint8_t objbits, capaddr_t dest_cnode_cptr, cslot_t dest_slot,
            uint8_t dest_vbits, bool from_monitor);
+struct sysret sys_create(struct capability *root, enum objtype type,
+                         uint8_t objbits, capaddr_t dest_cnode_cptr,
+                         cslot_t dest_slot, int dest_vbits);
 struct sysret
 sys_copy_or_mint(struct capability *root, capaddr_t destcn_cptr, cslot_t dest_slot,
                  capaddr_t source_cptr, int destcn_vbits, int source_vbits,
index e6f42d3..5b6e8f8 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -247,6 +247,47 @@ sys_retype(struct capability *root, capaddr_t source_cptr, enum objtype type,
                               source_cap, from_monitor));
 }
 
+struct sysret sys_create(struct capability *root, enum objtype type,
+                         uint8_t objbits, capaddr_t dest_cnode_cptr,
+                         cslot_t dest_slot, int dest_vbits)
+{
+    errval_t err;
+    uint8_t bits = 0;
+    genpaddr_t base = 0;
+
+    /* Paramter checking */
+    if (type == ObjType_Null || type >= ObjType_Num) {
+        return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
+    }
+
+    /* Destination CNode */
+    struct capability *dest_cnode_cap;
+    err = caps_lookup_cap(root, dest_cnode_cptr, dest_vbits,
+                          &dest_cnode_cap, CAPRIGHTS_READ_WRITE);
+    if (err_is_fail(err)) {
+        return SYSRET(err_push(err, SYS_ERR_DEST_CNODE_LOOKUP));
+    }
+
+    /* Destination slot */
+    struct cte *dest_cte;
+    dest_cte = caps_locate_slot(dest_cnode_cap->u.cnode.cnode, dest_slot);
+    if (dest_cte->cap.type != ObjType_Null) {
+        return SYSRET(SYS_ERR_SLOTS_IN_USE);
+    }
+
+    /* List capabilities allowed to be created at runtime. */
+    switch(type) {
+
+    // TODO: add capability types that can be created at runtime.
+
+    // only certain types of capabilities can be created at runtime
+    default:
+        return SYSRET(SYS_ERR_TYPE_NOT_CREATABLE);
+    }
+
+    return SYSRET(caps_create_new(type, base, bits, objbits, dest_cte));
+}
+
 /**
  * Common code for copying and minting except the mint flag and param passing
  */
index 07c87ac..e645e32 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -267,6 +267,34 @@ errval_t cap_retype(struct capref dest_start, struct capref src,
 
 
 /**
+ * \brief Create a capability
+ *
+ * \param dest      Location where to create the cap, which must be empty.
+ * \param type      Kernel object type to create.
+ * \param size_bits Size of the created capability as a power of two.
+ *                  (ignored for fixed-size objects)
+ *
+ * Only certain types of capabilities can be created this way. If invoked on
+ * a capability type, that is not creatable at runtime the error
+ * SYS_ERR_TYPE_NOT_CREATABLE is returned. Most capabilities have to be retyped
+ * from other capabilities with cap_retype().
+ */
+errval_t cap_create(struct capref dest, enum objtype type, uint8_t size_bits)
+{
+    errval_t err;
+
+    // Number of valid bits in the destination CNode address
+    uint8_t dest_vbits = get_cnode_valid_bits(dest);
+    // Address of the cap to the destination CNode
+    capaddr_t dest_cnode_cptr = get_cnode_addr(dest);
+
+    err = invoke_cnode_create(cap_root, type, size_bits, dest_cnode_cptr,
+                              dest.slot, dest_vbits);
+
+    return err;
+}
+
+/**
  * \brief Delete the given capability
  *
  * \param cap Capability to be deleted