Added ID capability, providing a system-wide unique ID.
authorRaphael Fuchs <raphaelfuchs@student.ethz.ch>
Fri, 22 Jun 2012 09:04:45 +0000 (11:04 +0200)
committerRaphael Fuchs <raphaelfuchs@student.ethz.ch>
Fri, 22 Jun 2012 09:04:45 +0000 (11:04 +0200)
The ID capability currently supports one invocation called 'identify', to
retrieve the system-wide unique ID.

The Domain capability, which was never used, is removed with this patch, since
the ID capability provides a more general capability.

14 files changed:
capabilities/caps.hl
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
include/barrelfish_kpi/types.h
kernel/arch/x86_32/syscall.c
kernel/arch/x86_64/syscall.c
kernel/capabilities.c
kernel/include/syscall.h
kernel/syscall.c
lib/barrelfish/capabilities.c
lib/barrelfish/debug.c

index 49a538a..3f5243d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, ETH Zurich.
+ * Copyright (c) 2009, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -266,9 +266,10 @@ cap Notify_IPI {
     eq uint16 chanid;
 };
 
-cap Domain {
-    /* Domain capability (opaque type, used by the monitors) */
-    eq uint32 domainid;
+/* ID capability, system-wide unique */
+cap ID {
+    eq coreid coreid; /* core cap was created */
+    eq uint32 core_local_id; /* per core unique id */
 };
 
 cap PerfMon is_always_copy {
index 76ef179..cc5e4bd 100644 (file)
@@ -117,6 +117,9 @@ errors kernel SYS_ERR_ {
 
     // SCC driver errors
     failure CROSS_MC                   "Frame crosses memory controllers",
+
+    // ID capability
+    failure ID_SPACE_EXHAUSTED  "ID space exhausted",
 };
 
 // errors generated by libcaps
index 8a4b3ed..d44e3e9 100644 (file)
@@ -493,3 +493,27 @@ static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap)
 {
     return ERR_NOTIMP;
 }
+
+/**
+ * \brief Return the system-wide unique ID of the passed ID capability.
+ *
+ * \param idcap ID capability to invoke.
+ * \param id    Filled-in with system-wide unique ID of ID cap.
+ *
+ * \return      Error code
+ */
+static inline errval_t invoke_idcap_identify(struct capref idcap,
+                                             idcap_id_t *id)
+{
+    assert(id != NULL);
+
+    uint8_t invoke_bits = get_cap_valid_bits(idcap);
+    capaddr_t invoke_cptr = get_cap_addr(idcap) >> (CPTR_BITS - invoke_bits);
+
+    // user-space pointer 'id' is directly written to by kernel.
+    struct sysret sysret =
+        syscall3((invoke_bits << 16) | (IDCmd_Identify << 8) | SYSCALL_INVOKE,
+                 invoke_cptr, (uintptr_t) id);
+
+    return sysret.error;
+}
index 46b7f2c..86fcfc2 100644 (file)
@@ -357,4 +357,26 @@ static inline errval_t invoke_ipi_notify_send(struct capref notify_cap)
     return cap_invoke1(notify_cap, NotifyCmd_Send).error;
 }
 
+/**
+ * \brief Return the system-wide unique ID of the passed ID capability.
+ *
+ * \param idcap ID capability to invoke.
+ * \param id    Filled-in with system-wide unique ID of ID cap.
+ *
+ * \return      Error code
+ */
+static inline errval_t invoke_idcap_identify(struct capref idcap,
+                                             idcap_id_t *id)
+{
+    assert(id != NULL);
+
+    struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify);
+
+    if (err_is_ok(sysret.error)) {
+        *id = sysret.value;
+    }
+
+    return sysret.error;
+}
+
 #endif
index 90eec2f..5d289b0 100644 (file)
@@ -51,6 +51,9 @@ struct lmp_endpoint;
 errval_t endpoint_create(size_t buflen, struct capref *retcap,
                          struct lmp_endpoint **retep);
 
+errval_t idcap_alloc(struct capref *dest);
+errval_t idcap_create(struct capref dest);
+
 /**
  * \brief Mint (Copy changing type-specific parameters) a capability
  *
index 24432c3..ff00120 100644 (file)
@@ -198,6 +198,13 @@ enum perfmon_cmd {
 };
 
 /**
+ * ID capability commands.
+ */
+enum id_cmd {
+    IDCmd_Identify  ///< Return system-wide unique ID
+};
+
+/**
  * Maximum command ordinal.
  */
 #define CAP_MAX_CMD KernelCmd_Count
index 7e3b949..58a5837 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -86,6 +86,12 @@ typedef uint8_t      coreid_t;
 #define MAX_COREID  255 // limit of coreid_t type (see comment above)
 #endif
 
+/* ID capability ID */
+// Returned if IDCmd_Identify is invoked on an ID capability.
+typedef uint64_t idcap_id_t;
+#define PRIuIDCAPID PRIu64
+#define PRIxIDCAPID PRIx64
+
 /* Resource id */
 typedef uint32_t rsrcid_t;
 #define PRIuRSRCID  PRIu32
index e303786..0edf4eb 100644 (file)
@@ -31,6 +31,7 @@
 #include <arch/x86/syscall.h>
 #include <arch/x86/timing.h>
 #include <fpu.h>
+#include <useraccess.h>
 #ifdef __scc__
 #       include <rck.h>
 #else
@@ -574,6 +575,22 @@ static struct sysret handle_irq_table_delete(struct capability *to, int cmd, uin
     return SYSRET(irq_table_delete(args[0]));
 }
 
+/**
+ * \brief Return system-wide unique ID of this ID cap.
+ */
+static struct sysret handle_idcap_identify(struct capability *cap, int cmd,
+                                           uintptr_t *args)
+{
+    idcap_id_t *idp = (idcap_id_t *) args[0];
+
+    // Check validity of user space pointer
+    if (!access_ok(ACCESS_WRITE, (lvaddr_t) idp, sizeof(*idp)))  {
+        return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
+    }
+
+    return sys_idcap_identify(cap, idp);
+}
+
 #ifdef __scc__
 static struct sysret kernel_rck_register(struct capability *cap,
                                          int cmd, uintptr_t *args)
@@ -703,6 +720,9 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [IOCmd_Inw] = handle_io,
         [IOCmd_Ind] = handle_io
     },
+    [ObjType_ID] = {
+        [IDCmd_Identify] = handle_idcap_identify
+    },
 #ifdef __scc__
     [ObjType_Notify_RCK] = {
         [NotifyCmd_Send] = handle_rck_notify_send
index 7c07530..5403d97 100644 (file)
@@ -650,6 +650,19 @@ static struct sysret performance_counter_deactivate(struct capability *cap,
     return SYSRET(SYS_ERR_OK);
 }
 
+/*
+ * \brief Return system-wide unique ID of this ID cap.
+ */
+static struct sysret handle_idcap_identify(struct capability *cap, int cmd,
+                                           uintptr_t *args)
+{
+    idcap_id_t id;
+    struct sysret sysret = sys_idcap_identify(cap, &id);
+    sysret.value = id;
+
+    return sysret;
+}
+
 typedef struct sysret (*invocation_handler_t)(struct capability *to,
                                               int cmd, uintptr_t *args);
 
@@ -724,6 +737,9 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [PerfmonCmd_Activate] = performance_counter_activate,
         [PerfmonCmd_Deactivate] = performance_counter_deactivate,
         [PerfmonCmd_Write] = performance_counter_write,
+    },
+    [ObjType_ID] = {
+        [IDCmd_Identify] = handle_idcap_identify,
     }
 };
 
index 3fdfe63..3ebf95c 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
 struct capability monitor_ep;
 
 /**
+ * ID capability core_local_id counter.
+ */
+static uint32_t id_cap_counter = 1;
+
+/**
  *  Sets #dest equal to #src
  *
  * #dest cannot be in use.
@@ -125,7 +130,7 @@ static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
     case ObjType_IRQTable:
     case ObjType_IO:
     case ObjType_EndPoint:
-    case ObjType_Domain:
+    case ObjType_ID:
     case ObjType_Notify_RCK:
     case ObjType_Notify_IPI:
     case ObjType_PerfMon:
@@ -525,6 +530,25 @@ static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, uint8_t bits,
         }
         return SYS_ERR_OK;
 
+    case ObjType_ID:
+        // ID type does not refer to a kernel object
+        assert(lpaddr  == 0);
+        assert(bits    == 0);
+        assert(objbits == 0);
+        assert(numobjs == 1);
+
+        // Prevent wrap around
+        if (id_cap_counter >= UINT32_MAX) {
+            return SYS_ERR_ID_SPACE_EXHAUSTED;
+        }
+
+        // Generate a new ID, core_local_id monotonically increases
+        src_cap.u.id.coreid = my_core_id;
+        src_cap.u.id.core_local_id = id_cap_counter++;
+
+        // Insert the capability
+        return set_cap(&dest_caps->cap, &src_cap);
+
     case ObjType_IO:
         src_cap.u.io.start = 0;
         src_cap.u.io.end   = 65535;
@@ -533,7 +557,6 @@ static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, uint8_t bits,
     case ObjType_Kernel:
     case ObjType_IRQTable:
     case ObjType_EndPoint:
-    case ObjType_Domain:
     case ObjType_Notify_RCK:
     case ObjType_Notify_IPI:
     case ObjType_PerfMon:
index 294bb4e..012c4b5 100644 (file)
@@ -56,5 +56,6 @@ sys_dispatcher_setup_guest (struct capability *to,
                             capaddr_t vmcbp, capaddr_t ctrlp);
 struct sysret sys_monitor_domain_id(capaddr_t cptr, domainid_t domain_id);
 struct sysret sys_trace_setup(struct capability *cap, capaddr_t cptr);
+struct sysret sys_idcap_identify(struct capability *cap, idcap_id_t *id);
 
 #endif
index 5b6e8f8..0a04ad3 100644 (file)
@@ -278,7 +278,8 @@ struct sysret sys_create(struct capability *root, enum objtype type,
     /* List capabilities allowed to be created at runtime. */
     switch(type) {
 
-    // TODO: add capability types that can be created at runtime.
+    case ObjType_ID:
+        break;
 
     // only certain types of capabilities can be created at runtime
     default:
@@ -501,3 +502,22 @@ struct sysret sys_yield(capaddr_t target)
 
     panic("Yield returned!");
 }
+
+/**
+ * The format of the returned ID is:
+ *
+ * --------------------------------------------------------------------
+ * |             0 (unused) | coreid |         core_local_id          |
+ * --------------------------------------------------------------------
+ * 63                        39       31                              0 Bit
+ *
+ */
+struct sysret sys_idcap_identify(struct capability *cap, idcap_id_t *id)
+{
+    STATIC_ASSERT_SIZEOF(coreid_t, 1);
+
+    idcap_id_t coreid = (idcap_id_t) cap->u.id.coreid;
+    *id = coreid << 32 | cap->u.id.core_local_id;
+
+    return SYSRET(SYS_ERR_OK);
+}
index e645e32..ccd1fb8 100644 (file)
@@ -696,3 +696,33 @@ errval_t devframe_type(struct capref *dest, struct capref src, uint8_t bits)
 
     return cap_retype(*dest, src, ObjType_DevFrame, bits);
 }
+
+/**
+ * \brief Create an ID cap in a newly allocated slot.
+ *
+ * \param dest  Pointer to capref struct, filld-in with location of new cap.
+ *
+ * The caller is responsible for revoking the cap after using it.
+ */
+errval_t idcap_alloc(struct capref *dest)
+{
+    errval_t err = slot_alloc(dest);
+
+    if (err_is_fail(err)) {
+        return err_push(err, LIB_ERR_SLOT_ALLOC);
+    }
+
+    return idcap_create(*dest);
+}
+
+/**
+ * \brief Create an ID cap in the specified slot.
+ *
+ * \param dest  Capref, where ID cap should be created.
+ *
+ * The caller is responsible for revoking the cap after using it.
+ */
+errval_t idcap_create(struct capref dest)
+{
+    return cap_create(dest, ObjType_ID, 0);
+}
index ae4497d..706f246 100644 (file)
@@ -181,6 +181,11 @@ int debug_print_cap(char *buf, size_t len, struct capability *cap)
     case ObjType_Kernel:
         return snprintf(buf, len, "Kernel cap");
 
+    case ObjType_ID:
+        return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
+                        " core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
+                        cap->u.id.core_local_id);
+
     default:
         return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
     }