1/** 2 * \file 3 * \brief Inline functions to allow manipulation of raw capability addresses 4 * 5 * This file is not part of the standard includes, because most user code should 6 * treat #capref as an opaque value. 7 */ 8 9/* 10 * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich. 11 * All rights reserved. 12 * 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. 16 */ 17 18#ifndef INCLUDEBARRELFISH_CADDR_H 19#define INCLUDEBARRELFISH_CADDR_H 20 21#include <stdbool.h> 22#include <sys/cdefs.h> 23 24#include <barrelfish_kpi/types.h> 25#include <barrelfish_kpi/init.h> 26#include <barrelfish_kpi/capabilities.h> 27 28#include <barrelfish/cspace.h> 29 30#include <stdint.h> 31#include <stdbool.h> 32 33#include <bitmacros.h> 34 35__BEGIN_DECLS 36 37/** 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 41 * bits. 42 */ 43static inline cslot_t get_capaddr_slot(capaddr_t addr) 44{ 45 return (cslot_t)(addr & MASK_T(capaddr_t, L2_CNODE_BITS)); 46} 47 48/** 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. 53 */ 54static inline capaddr_t get_capaddr_cnode_addr(capaddr_t addr) 55{ 56 return addr & ~MASK_T(capaddr_t, L2_CNODE_BITS); 57} 58 59enum cnode_type { 60 CNODE_TYPE_ROOT = 0, 61 CNODE_TYPE_OTHER, 62 CNODE_TYPE_COUNT, 63} __attribute__((packed)); 64 65/** 66 * \brief User-level representation of a CNode, this is essentially a capref 67 * to a CNode. 68 */ 69struct cnoderef { 70 capaddr_t croot; 71 capaddr_t cnode; 72 enum cnode_type level; 73} __attribute__((packed)); 74 75#define NULL_CNODE (struct cnoderef){ \ 76 /*croot*/ 0, /*cnode*/ 0, \ 77 /*level*/ CNODE_TYPE_ROOT } 78 79/** 80 * \brief User-level representation of a capability and its CSpace address 81 */ 82 83struct capref { 84 struct cnoderef cnode; 85 cslot_t slot; 86}; 87 88#define NULL_CAP (struct capref){ /*cnode*/ NULL_CNODE, /*slot*/ 0 } 89 90static inline bool cnoderef_is_null(struct cnoderef cnoderef) 91{ 92 return cnoderef.croot == 0 && cnoderef.cnode == 0; 93} 94 95static inline bool capref_is_null(struct capref capref) 96{ 97 return cnoderef_is_null(capref.cnode) && capref.slot == 0; 98} 99 100/* well-known cnodes */ 101extern struct cnoderef cnode_root, cnode_task, cnode_base, cnode_super, 102 cnode_page, cnode_module; 103 104/* well-known capabilities */ 105extern 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, 108 cap_domainid; 109 110/** 111 * \brief Returns the depth in the CSpace address of a cap 112 */ 113static inline uint8_t get_cap_level(struct capref cap) 114{ 115 if (capref_is_null(cap)) { 116 return 0; 117 } else { 118 return cap.cnode.level + 1; 119 } 120} 121 122/** 123 * \brief Returns the CSpace address of a cap 124 */ 125static inline capaddr_t get_cap_addr(struct capref cap) 126{ 127 if (!capref_is_null(cap)) { 128 switch (cap.cnode.level) { 129 case CNODE_TYPE_ROOT: 130 return cap.slot << L2_CNODE_BITS; 131 // capref is in L2 CNode 132 case CNODE_TYPE_OTHER: 133 return cap.cnode.cnode | cap.slot; 134 default: 135 assert(!"invalid level"); 136 return 0x0; 137 } 138 } 139 return 0; 140} 141 142/** 143 * \brief Returns the depth in the CSpace address of the CNode 144 * containing the given cap 145 */ 146static inline uint8_t get_cnode_level(struct capref cap) 147{ 148 return cap.cnode.level; 149} 150 151/** 152 * \brief Returns the CSpace address of the CNode containing the given cap 153 */ 154static inline capaddr_t get_cnode_addr(struct capref cap) 155{ 156 switch (cap.cnode.level) { 157 case CNODE_TYPE_ROOT: 158 return cap.cnode.croot; 159 case CNODE_TYPE_OTHER: 160 return cap.cnode.cnode; 161 default: 162 assert(!"unknown cnoderef type"); 163 return 0x0; 164 } 165} 166 167 168/** 169 * \brief Returns the CSpace address of the cspace root cap of the given cap 170 */ 171static inline capaddr_t get_croot_addr(struct capref cap) 172{ 173 return cap.cnode.croot; 174} 175 176static inline struct capref get_croot_capref(struct capref cap) 177{ 178 capaddr_t croot = get_croot_addr(cap); 179 struct capref ref = { 180 .cnode = { 181 .croot = CPTR_ROOTCN, 182 .cnode = get_capaddr_cnode_addr(croot), 183 .level = CNODE_TYPE_OTHER, 184 }, 185 .slot = get_capaddr_slot(croot), 186 }; 187 return ref; 188} 189 190/** 191 * \brief Compare two cnoderefs 192 * 193 * Two cnoderefs are equal if they have the same base address, 194 * same number of valid bits and the same guard_size. 195 */ 196static inline bool cnodecmp(struct cnoderef c1, struct cnoderef c2) 197{ 198 return (c1.cnode == c2.cnode && c1.croot == c2.croot && c1.level == c2.level); 199} 200 201/** 202 * \brief Compare two caprefs 203 * 204 * Two caprefs are equal if they have the same cnoderef and the same 205 * slot. 206 */ 207static inline bool capcmp(struct capref c1, struct capref c2) 208{ 209 return c1.slot == c2.slot && cnodecmp(c1.cnode, c2.cnode); 210} 211 212/** 213 * \brief Creates a new #cnoderef struct, performing address calculations. 214 * XXX: TODO remove size_bits from signature 215 */ 216static inline struct cnoderef build_cnoderef(struct capref cap, 217 enum cnode_type cntype) 218{ 219 assert(cntype < CNODE_TYPE_COUNT); 220 221 struct cnoderef cnode = NULL_CNODE; 222 switch(get_cnode_level(cap)) { 223 // L2 cnode in our root cnode 224 case CNODE_TYPE_ROOT: 225 // cannot make cnoderef from non-invokable capref. 226 assert(cap.cnode.croot == CPTR_ROOTCN); 227 cnode.croot = CPTR_ROOTCN; 228 cnode.cnode = get_cap_addr(cap); 229 cnode.level = cntype; 230 break; 231 // CNode for another cspace 232 case CNODE_TYPE_OTHER: 233 cnode.level = cntype; 234 switch (cntype) { 235 // creating a cnoderef to a root cnode for another cspace 236 case CNODE_TYPE_ROOT: 237 cnode.croot = get_cap_addr(cap); 238 cnode.cnode = 0; 239 break; 240 case CNODE_TYPE_OTHER: 241 cnode.croot = get_croot_addr(cap); 242 cnode.cnode = get_cap_addr(cap); 243 break; 244 default: 245 assert(!"build_cnoderef: provided cntype invalid"); 246 return NULL_CNODE; 247 } 248 break; 249 default: 250 assert(!"cap level not valid"); 251 return NULL_CNODE; 252 } 253 return cnode; 254} 255 256__END_DECLS 257 258#endif 259