3 * \brief Inline functions to allow manipulation of raw capability addresses
5 * This file is not part of the standard includes, because most user code should
6 * treat #capref as an opaque value.
10 * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
11 * All rights reserved.
13 * This file is distributed under the terms in the attached LICENSE file.
14 * If you do not find this file, copies can be found by writing to:
15 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
18 #ifndef INCLUDEBARRELFISH_CADDR_H
19 #define INCLUDEBARRELFISH_CADDR_H
22 #include <sys/cdefs.h>
24 #include <barrelfish_kpi/types.h>
25 #include <barrelfish_kpi/init.h>
26 #include <barrelfish_kpi/capabilities.h>
28 #include <barrelfish/cspace.h>
33 #include <bitmacros.h>
38 * \brief extract slot (L2 index) from capability address `addr`
39 * \param addr the capability address
40 * \return The slot number (L2 index) component of the address, i.e. the low
43 static inline cslot_t get_capaddr_slot(capaddr_t addr)
45 return (cslot_t)(addr & MASK_T(capaddr_t, L2_CNODE_BITS));
49 * \brief extract CNode address component from capability address `addr`
50 * \param addr the capability address
51 * \return the cnode component of the address, i.e. the address with the slot
52 * (L2 index) bits set to zero.
54 static inline capaddr_t get_capaddr_cnode_addr(capaddr_t addr)
56 return addr & ~MASK_T(capaddr_t, L2_CNODE_BITS);
63 } __attribute__((packed));
66 * \brief User-level representation of a CNode, this is essentially a capref
72 enum cnode_type level;
73 } __attribute__((packed));
75 #define NULL_CNODE (struct cnoderef){ \
76 /*croot*/ 0, /*cnode*/ 0, \
77 /*level*/ CNODE_TYPE_ROOT }
80 * \brief User-level representation of a capability and its CSpace address
84 struct cnoderef cnode;
88 #define NULL_CAP (struct capref){ /*cnode*/ NULL_CNODE, /*slot*/ 0 }
90 static inline bool cnoderef_is_null(struct cnoderef cnoderef)
92 return cnoderef.croot == 0 && cnoderef.cnode == 0;
95 static inline bool capref_is_null(struct capref capref)
97 return cnoderef_is_null(capref.cnode) && capref.slot == 0;
100 /* well-known cnodes */
101 extern struct cnoderef cnode_root, cnode_task, cnode_base, cnode_super,
102 cnode_page, cnode_module;
104 /* well-known capabilities */
105 extern struct capref cap_root, cap_monitorep, cap_irq, cap_io, cap_dispatcher,
106 cap_selfep, cap_kernel, cap_initep, cap_perfmon, cap_dispframe,
107 cap_sessionid, cap_ipi, cap_vroot, cap_argcn, cap_procmng;
110 * \brief Returns the depth in the CSpace address of a cap
112 static inline uint8_t get_cap_level(struct capref cap)
114 if (capref_is_null(cap)) {
117 return cap.cnode.level + 1;
122 * \brief Returns the CSpace address of a cap
124 static inline capaddr_t get_cap_addr(struct capref cap)
126 if (!capref_is_null(cap)) {
127 switch (cap.cnode.level) {
128 case CNODE_TYPE_ROOT:
129 return cap.slot << L2_CNODE_BITS;
130 // capref is in L2 CNode
131 case CNODE_TYPE_OTHER:
132 return cap.cnode.cnode | cap.slot;
134 assert(!"invalid level");
142 * \brief Returns the depth in the CSpace address of the CNode
143 * containing the given cap
145 static inline uint8_t get_cnode_level(struct capref cap)
147 return cap.cnode.level;
151 * \brief Returns the CSpace address of the CNode containing the given cap
153 static inline capaddr_t get_cnode_addr(struct capref cap)
155 switch (cap.cnode.level) {
156 case CNODE_TYPE_ROOT:
157 return cap.cnode.croot;
158 case CNODE_TYPE_OTHER:
159 return cap.cnode.cnode;
161 assert(!"unknown cnoderef type");
168 * \brief Returns the CSpace address of the cspace root cap of the given cap
170 static inline capaddr_t get_croot_addr(struct capref cap)
172 return cap.cnode.croot;
175 static inline struct capref get_croot_capref(struct capref cap)
177 capaddr_t croot = get_croot_addr(cap);
178 struct capref ref = {
180 .croot = CPTR_ROOTCN,
181 .cnode = get_capaddr_cnode_addr(croot),
182 .level = CNODE_TYPE_OTHER,
184 .slot = get_capaddr_slot(croot),
190 * \brief Compare two cnoderefs
192 * Two cnoderefs are equal if they have the same base address,
193 * same number of valid bits and the same guard_size.
195 static inline bool cnodecmp(struct cnoderef c1, struct cnoderef c2)
197 return (c1.cnode == c2.cnode && c1.croot == c2.croot && c1.level == c2.level);
201 * \brief Compare two caprefs
203 * Two caprefs are equal if they have the same cnoderef and the same
206 static inline bool capcmp(struct capref c1, struct capref c2)
208 return c1.slot == c2.slot && cnodecmp(c1.cnode, c2.cnode);
212 * \brief Creates a new #cnoderef struct, performing address calculations.
213 * XXX: TODO remove size_bits from signature
215 static inline struct cnoderef build_cnoderef(struct capref cap,
216 enum cnode_type cntype)
218 assert(cntype < CNODE_TYPE_COUNT);
220 struct cnoderef cnode = NULL_CNODE;
221 switch(get_cnode_level(cap)) {
222 // L2 cnode in our root cnode
223 case CNODE_TYPE_ROOT:
224 // cannot make cnoderef from non-invokable capref.
225 assert(cap.cnode.croot == CPTR_ROOTCN);
226 cnode.croot = CPTR_ROOTCN;
227 cnode.cnode = get_cap_addr(cap);
228 cnode.level = cntype;
230 // CNode for another cspace
231 case CNODE_TYPE_OTHER:
232 cnode.level = cntype;
234 // creating a cnoderef to a root cnode for another cspace
235 case CNODE_TYPE_ROOT:
236 cnode.croot = get_cap_addr(cap);
239 case CNODE_TYPE_OTHER:
240 cnode.croot = get_croot_addr(cap);
241 cnode.cnode = get_cap_addr(cap);
244 assert(!"build_cnoderef: provided cntype invalid");
249 assert(!"cap level not valid");