Add spawn, spawn_with_caps and span calls to the Process Manager API.
[barrelfish] / include / barrelfish / caddr.h
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  */
43 static 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  */
54 static inline capaddr_t get_capaddr_cnode_addr(capaddr_t addr)
55 {
56     return addr & ~MASK_T(capaddr_t, L2_CNODE_BITS);
57 }
58
59 enum 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  */
69 struct 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
83 struct capref {
84     struct cnoderef cnode;
85     cslot_t slot;
86 };
87
88 #define NULL_CAP (struct capref){ /*cnode*/ NULL_CNODE, /*slot*/ 0 }
89
90 static inline bool cnoderef_is_null(struct cnoderef cnoderef)
91 {
92     return cnoderef.croot == 0 && cnoderef.cnode == 0;
93 }
94
95 static 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 */
101 extern struct cnoderef cnode_root, cnode_task, cnode_base, cnode_super,
102                        cnode_page, cnode_module;
103
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,
108                      cap_domainid;
109
110 /**
111  * \brief Returns the depth in the CSpace address of a cap
112  */
113 static 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  */
125 static 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  */
146 static 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  */
154 static 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  */
171 static inline capaddr_t get_croot_addr(struct capref cap)
172 {
173     return cap.cnode.croot;
174 }
175
176 static 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  */
196 static 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  */
207 static 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  */
216 static 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