3 * \brief Kernel capability management implementation.
7 * Copyright (c) 2007-2012,2015,2016 ETH Zurich.
8 * Copyright (c) 2015, 2016 Hewlett Packard Enterprise Development LP.
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
19 #include <barrelfish_kpi/syscalls.h>
20 #include <barrelfish_kpi/paging_arch.h>
21 #include <barrelfish_kpi/lmp.h>
23 #include <capabilities.h>
24 #include <cap_predicates.h>
28 #include <paging_kernel_arch.h>
30 #include <mdb/mdb_tree.h>
31 #include <trace/trace.h>
32 #include <trace_definitions/trace_defs.h>
34 #include <bitmacros.h>
37 #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
39 #ifdef TRACE_PMEM_CAPS
40 uint64_t trace_types_enabled = TRACE_TYPES_ENABLED_INITIAL;
41 genpaddr_t TRACE_PMEM_BEGIN = TRACE_PMEM_BEGIN_INITIAL;
42 gensize_t TRACE_PMEM_SIZE = TRACE_PMEM_SIZE_INITIAL;
44 void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
47 trace_types_enabled = types;
48 TRACE_PMEM_BEGIN = start;
49 TRACE_PMEM_SIZE = size;
51 trace_types_enabled = 0;
56 struct capability monitor_ep;
58 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
59 int sprint_cap(char *buf, size_t len, struct capability *cap)
62 case ObjType_PhysAddr:
63 return snprintf(buf, len,
64 "physical address range cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
65 cap->u.physaddr.base, cap->u.physaddr.bytes);
68 return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
69 cap->u.ram.base, cap->u.ram.bytes);
71 case ObjType_L1CNode: {
72 int ret = snprintf(buf, len, "L1 CNode cap "
73 "(base=%#"PRIxGENPADDR", allocated bytes %#"PRIxGENSIZE
74 ", rights mask %#"PRIxCAPRIGHTS")",
75 get_address(cap), get_size(cap),
76 cap->u.l1cnode.rightsmask);
80 case ObjType_L2CNode: {
81 int ret = snprintf(buf, len, "L2 CNode cap "
82 "(base=%#"PRIxGENPADDR", rights mask %#"PRIxCAPRIGHTS")",
83 get_address(cap), cap->u.l1cnode.rightsmask);
87 case ObjType_Dispatcher:
88 return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
91 return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
92 cap->u.frame.base, cap->u.frame.bytes);
94 case ObjType_DevFrame:
95 return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
96 cap->u.devframe.base, cap->u.devframe.bytes);
98 case ObjType_VNode_ARM_l1:
99 return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
100 cap->u.vnode_arm_l1.base);
102 case ObjType_VNode_ARM_l2:
103 return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
104 cap->u.vnode_arm_l2.base);
106 case ObjType_VNode_AARCH64_l0:
107 return snprintf(buf, len, "AARCH64 L0 table at 0x%" PRIxGENPADDR,
108 cap->u.vnode_aarch64_l0.base);
110 case ObjType_VNode_AARCH64_l1:
111 return snprintf(buf, len, "AARCH64 L1 table at 0x%" PRIxGENPADDR,
112 cap->u.vnode_aarch64_l1.base);
114 case ObjType_VNode_AARCH64_l2:
115 return snprintf(buf, len, "AARCH64 L2 table at 0x%" PRIxGENPADDR,
116 cap->u.vnode_aarch64_l2.base);
118 case ObjType_VNode_AARCH64_l3:
119 return snprintf(buf, len, "AARCH64 L3 table at 0x%" PRIxGENPADDR,
120 cap->u.vnode_aarch64_l3.base);
122 case ObjType_VNode_x86_32_ptable:
123 return snprintf(buf, len, "x86_32 Page table at 0x%" PRIxGENPADDR,
124 cap->u.vnode_x86_32_ptable.base);
126 case ObjType_VNode_x86_32_pdir:
127 return snprintf(buf, len, "x86_32 Page directory at 0x%" PRIxGENPADDR,
128 cap->u.vnode_x86_32_pdir.base);
130 case ObjType_VNode_x86_32_pdpt:
131 return snprintf(buf, len, "x86_32 PDPT at 0x%" PRIxGENPADDR,
132 cap->u.vnode_x86_32_pdpt.base);
134 case ObjType_VNode_x86_64_ptable:
135 return snprintf(buf, len, "x86_64 Page table at 0x%" PRIxGENPADDR,
136 cap->u.vnode_x86_64_ptable.base);
138 case ObjType_VNode_x86_64_pdir:
139 return snprintf(buf, len, "x86_64 Page directory at 0x%" PRIxGENPADDR,
140 cap->u.vnode_x86_64_pdir.base);
142 case ObjType_VNode_x86_64_pdpt:
143 return snprintf(buf, len, "x86_64 PDPT at 0x%" PRIxGENPADDR,
144 cap->u.vnode_x86_64_pdpt.base);
146 case ObjType_VNode_x86_64_pml4:
147 return snprintf(buf, len, "x86_64 PML4 at 0x%" PRIxGENPADDR,
148 cap->u.vnode_x86_64_pml4.base);
150 case ObjType_Frame_Mapping:
151 return snprintf(buf, len, "Frame Mapping (Frame cap @%p, "
152 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
153 cap->u.frame_mapping.cap,
154 cap->u.frame_mapping.pte,
155 cap->u.frame_mapping.pte_count);
157 case ObjType_DevFrame_Mapping:
158 return snprintf(buf, len, "DevFrame Mapping (DevFrame cap @%p, "
159 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
160 cap->u.devframe_mapping.cap,
161 cap->u.devframe_mapping.pte,
162 cap->u.devframe_mapping.pte_count);
164 case ObjType_VNode_x86_64_pml4_Mapping:
165 return snprintf(buf, len, "x86_64 PML4 Mapping (x86_64 PML4 cap @%p, "
166 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
167 cap->u.vnode_x86_64_pml4_mapping.cap,
168 cap->u.vnode_x86_64_pml4_mapping.pte,
169 cap->u.vnode_x86_64_pml4_mapping.pte_count);
171 case ObjType_VNode_x86_64_pdpt_Mapping:
172 return snprintf(buf, len, "x86_64 PDPT Mapping (x86_64 PDPT cap @%p, "
173 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
174 cap->u.vnode_x86_64_pdpt_mapping.cap,
175 cap->u.vnode_x86_64_pdpt_mapping.pte,
176 cap->u.vnode_x86_64_pdpt_mapping.pte_count);
178 case ObjType_VNode_x86_64_pdir_Mapping:
179 return snprintf(buf, len, "x86_64 PDIR Mapping (x86_64 PDIR cap @%p, "
180 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
181 cap->u.vnode_x86_64_pdir_mapping.cap,
182 cap->u.vnode_x86_64_pdir_mapping.pte,
183 cap->u.vnode_x86_64_pdir_mapping.pte_count);
185 case ObjType_VNode_x86_64_ptable_Mapping:
186 return snprintf(buf, len, "x86_64 PTABLE Mapping (x86_64 PTABLE cap @%p, "
187 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
188 cap->u.vnode_x86_64_ptable_mapping.cap,
189 cap->u.vnode_x86_64_ptable_mapping.pte,
190 cap->u.vnode_x86_64_ptable_mapping.pte_count);
192 case ObjType_VNode_x86_32_pdpt_Mapping:
193 return snprintf(buf, len, "x86_32 PDPT Mapping (x86_32 PDPT cap @%p, "
194 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
195 cap->u.vnode_x86_32_pdpt_mapping.cap,
196 cap->u.vnode_x86_32_pdpt_mapping.pte,
197 cap->u.vnode_x86_32_pdpt_mapping.pte_count);
199 case ObjType_VNode_x86_32_pdir_Mapping:
200 return snprintf(buf, len, "x86_32 PDIR Mapping (x86_32 PDIR cap @%p, "
201 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
202 cap->u.vnode_x86_32_pdir_mapping.cap,
203 cap->u.vnode_x86_32_pdir_mapping.pte,
204 cap->u.vnode_x86_32_pdir_mapping.pte_count);
206 case ObjType_VNode_x86_32_ptable_Mapping:
207 return snprintf(buf, len, "x86_32 PTABLE Mapping (x86_32 PTABLE cap @%p, "
208 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
209 cap->u.vnode_x86_32_ptable_mapping.cap,
210 cap->u.vnode_x86_32_ptable_mapping.pte,
211 cap->u.vnode_x86_32_ptable_mapping.pte_count);
213 case ObjType_VNode_ARM_l1_Mapping:
214 return snprintf(buf, len, "ARM l1 Mapping (ARM l1 cap @%p, "
215 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
216 cap->u.vnode_arm_l1_mapping.cap,
217 cap->u.vnode_arm_l1_mapping.pte,
218 cap->u.vnode_arm_l1_mapping.pte_count);
220 case ObjType_VNode_ARM_l2_Mapping:
221 return snprintf(buf, len, "ARM l2 Mapping (ARM l2 cap @%p, "
222 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
223 cap->u.vnode_arm_l2_mapping.cap,
224 cap->u.vnode_arm_l2_mapping.pte,
225 cap->u.vnode_arm_l2_mapping.pte_count);
227 case ObjType_VNode_AARCH64_l0_Mapping:
228 return snprintf(buf, len, "AARCH64 l0 Mapping (AARCH64 l0 cap @%p, "
229 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
230 cap->u.vnode_aarch64_l0_mapping.cap,
231 cap->u.vnode_aarch64_l0_mapping.pte,
232 cap->u.vnode_aarch64_l0_mapping.pte_count);
234 case ObjType_VNode_AARCH64_l1_Mapping:
235 return snprintf(buf, len, "AARCH64 l1 Mapping (AARCH64 l1 cap @%p, "
236 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
237 cap->u.vnode_aarch64_l1_mapping.cap,
238 cap->u.vnode_aarch64_l1_mapping.pte,
239 cap->u.vnode_aarch64_l1_mapping.pte_count);
241 case ObjType_VNode_AARCH64_l2_Mapping:
242 return snprintf(buf, len, "AARCH64 l2 Mapping (AARCH64 l2 cap @%p, "
243 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
244 cap->u.vnode_aarch64_l2_mapping.cap,
245 cap->u.vnode_aarch64_l2_mapping.pte,
246 cap->u.vnode_aarch64_l2_mapping.pte_count);
248 case ObjType_VNode_AARCH64_l3_Mapping:
249 return snprintf(buf, len, "AARCH64 l3 Mapping (AARCH64 l3 cap @%p, "
250 "pte @0x%"PRIxLVADDR", pte_count=%hu)",
251 cap->u.vnode_aarch64_l3_mapping.cap,
252 cap->u.vnode_aarch64_l3_mapping.pte,
253 cap->u.vnode_aarch64_l3_mapping.pte_count);
255 case ObjType_IRQTable:
256 return snprintf(buf, len, "IRQTable cap");
258 case ObjType_IRQDest:
259 return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", cpu: %"PRIu64")",
260 cap->u.irqdest.vector, cap->u.irqdest.cpu);
262 case ObjType_EndPoint:
263 return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
264 cap->u.endpoint.listener, cap->u.endpoint.epoffset);
267 return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
268 cap->u.io.start, cap->u.io.end);
271 return snprintf(buf, len, "Kernel cap");
273 case ObjType_KernelControlBlock:
274 return snprintf(buf, len, "Kernel control block");
277 return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
278 " core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
279 cap->u.id.core_local_id);
281 case ObjType_PerfMon:
282 return snprintf(buf, len, "PerfMon cap");
285 return snprintf(buf, len, "Null capability (empty slot)");
288 return snprintf(buf, len, "IPI cap");
291 return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
295 void caps_trace(const char *func, int line, struct cte *cte, const char *msg)
298 sprint_cap(cap_buf, 512, &cte->cap);
302 dispatcher_handle_t handle = dcb_current->disp;
303 struct dispatcher_shared_generic *disp =
304 get_dispatcher_shared_generic(handle);
305 snprintf(disp_buf, 64, "from %.*s", DISP_NAME_LEN, disp->name);
308 strcpy(disp_buf, "no disp");
311 printk(LOG_WARN, "%s: %s:%d: %s %p %s"
312 " (owner:%" PRIuCOREID ", rc:%d/ra:%d/rd:%d)\n",
313 disp_buf, func, line, (msg ? : ""), cte, cap_buf, cte->mdbnode.owner,
314 cte->mdbnode.remote_copies, cte->mdbnode.remote_ancs,
315 cte->mdbnode.remote_descs);
319 * ID capability core_local_id counter.
321 static uint32_t id_cap_counter = 1;
324 * Sets #dest equal to #src
326 * #dest cannot be in use.
328 static errval_t set_cap(struct capability *dest, struct capability *src)
330 /* Parameter checking */
332 assert(dest != NULL);
334 debug(SUBSYS_CAPS, "Copying cap from %#"PRIxLPADDR" to %#"PRIxLPADDR"\n",
335 mem_to_local_phys((lvaddr_t)cte_for_cap(src)),
336 mem_to_local_phys((lvaddr_t)cte_for_cap(dest)));
338 // Reserved object bits must always be greater/equal to actual object size
339 assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
341 // Cannot overwrite an already existing cap
342 if (dest->type != ObjType_Null) {
343 return SYS_ERR_SLOT_IN_USE;
346 memcpy(dest, src, sizeof(struct capability));
351 * \brief Determine how many objects can be created in a specified region.
353 * This function computes the number of objects that can be created by a call
356 * \param type Type of objects to create.
357 * \param srcsize Size of memory area in bytes
358 * \param objsize For variable-sized objects, size multiplier
360 * \return Number of objects to be created, or zero on error
363 // If you create more capability types you need to deal with them
364 // in the table below.
365 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
366 static size_t caps_max_numobjs(enum objtype type, gensize_t srcsize, gensize_t objsize)
369 case ObjType_PhysAddr:
372 case ObjType_DevFrame:
373 if (objsize > srcsize) {
376 return srcsize / objsize;
379 case ObjType_L1CNode:
380 if (srcsize < OBJSIZE_L2CNODE || objsize < OBJSIZE_L2CNODE) {
381 // disallow L1 CNode to be smaller than 16kB.
384 return srcsize / objsize;
387 case ObjType_L2CNode:
388 if (srcsize < OBJSIZE_L2CNODE || objsize != OBJSIZE_L2CNODE) {
389 // disallow L2 CNode creation if source too small or objsize wrong
392 return srcsize / objsize;
396 case ObjType_VNode_x86_64_pml4:
397 case ObjType_VNode_x86_64_pdpt:
398 case ObjType_VNode_x86_64_pdir:
399 case ObjType_VNode_x86_64_ptable:
400 case ObjType_VNode_x86_32_pdpt:
401 case ObjType_VNode_x86_32_pdir:
402 case ObjType_VNode_x86_32_ptable:
403 case ObjType_VNode_ARM_l1:
404 case ObjType_VNode_ARM_l2:
405 case ObjType_VNode_AARCH64_l0:
406 case ObjType_VNode_AARCH64_l1:
407 case ObjType_VNode_AARCH64_l2:
408 case ObjType_VNode_AARCH64_l3:
410 if (srcsize < vnode_objsize(type)) {
413 return srcsize / vnode_objsize(type);
417 case ObjType_Dispatcher:
418 if (srcsize < OBJSIZE_DISPATCHER) {
421 return srcsize / OBJSIZE_DISPATCHER;
424 case ObjType_KernelControlBlock:
425 if (srcsize < OBJSIZE_KCB) {
428 return srcsize / OBJSIZE_KCB;
432 case ObjType_IRQTable:
433 case ObjType_IRQDest:
436 case ObjType_EndPoint:
438 case ObjType_Notify_IPI:
439 case ObjType_PerfMon:
441 case ObjType_VNode_ARM_l1_Mapping:
442 case ObjType_VNode_ARM_l2_Mapping:
443 case ObjType_VNode_AARCH64_l0_Mapping:
444 case ObjType_VNode_AARCH64_l1_Mapping:
445 case ObjType_VNode_AARCH64_l2_Mapping:
446 case ObjType_VNode_AARCH64_l3_Mapping:
447 case ObjType_VNode_x86_64_pml4_Mapping:
448 case ObjType_VNode_x86_64_pdpt_Mapping:
449 case ObjType_VNode_x86_64_pdir_Mapping:
450 case ObjType_VNode_x86_64_ptable_Mapping:
451 case ObjType_VNode_x86_32_pdpt_Mapping:
452 case ObjType_VNode_x86_32_pdir_Mapping:
453 case ObjType_VNode_x86_32_ptable_Mapping:
454 case ObjType_DevFrame_Mapping:
455 case ObjType_Frame_Mapping:
459 panic("invalid type");
465 * \brief Initialize the objects for which local caps are about to be created.
467 * For the meaning of the parameters, see the 'caps_create' function.
469 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
471 static errval_t caps_zero_objects(enum objtype type, lpaddr_t lpaddr,
472 gensize_t objsize, size_t count)
474 assert(type < ObjType_Num);
476 // Virtual address of the memory the kernel object resides in
477 // XXX: A better of doing this,
478 // this is creating caps that the kernel cannot address.
479 // It assumes that the cap is not of the type which will have to zeroed out.
481 if(lpaddr < PADDR_SPACE_LIMIT) {
482 lvaddr = local_phys_to_mem(lpaddr);
490 debug(SUBSYS_CAPS, "Frame: zeroing %zu bytes @%#"PRIxLPADDR"\n",
491 (size_t)objsize * count, lpaddr);
492 TRACE(KERNEL, BZERO, 1);
493 memset((void*)lvaddr, 0, objsize * count);
494 TRACE(KERNEL, BZERO, 0);
497 case ObjType_L1CNode:
498 case ObjType_L2CNode:
499 debug(SUBSYS_CAPS, "L%dCNode: zeroing %zu bytes @%#"PRIxLPADDR"\n",
500 type == ObjType_L1CNode ? 1 : 2, (size_t)objsize * count,
502 TRACE(KERNEL, BZERO, 1);
503 memset((void*)lvaddr, 0, objsize * count);
504 TRACE(KERNEL, BZERO, 0);
507 case ObjType_VNode_ARM_l1:
508 case ObjType_VNode_ARM_l2:
509 case ObjType_VNode_AARCH64_l0:
510 case ObjType_VNode_AARCH64_l1:
511 case ObjType_VNode_AARCH64_l2:
512 case ObjType_VNode_AARCH64_l3:
513 case ObjType_VNode_x86_32_ptable:
514 case ObjType_VNode_x86_32_pdir:
515 case ObjType_VNode_x86_32_pdpt:
516 case ObjType_VNode_x86_64_ptable:
517 case ObjType_VNode_x86_64_pdir:
518 case ObjType_VNode_x86_64_pdpt:
519 case ObjType_VNode_x86_64_pml4:
520 // objsize is size of VNode; but not given as such
521 objsize = vnode_objsize(type);
522 debug(SUBSYS_CAPS, "VNode: zeroing %zu bytes @%#"PRIxLPADDR"\n",
523 (size_t)objsize * count, lpaddr);
524 TRACE(KERNEL, BZERO, 1);
525 memset((void*)lvaddr, 0, objsize * count);
526 TRACE(KERNEL, BZERO, 0);
529 case ObjType_Dispatcher:
530 debug(SUBSYS_CAPS, "Dispatcher: zeroing %zu bytes @%#"PRIxLPADDR"\n",
531 ((size_t) OBJSIZE_DISPATCHER) * count, lpaddr);
532 TRACE(KERNEL, BZERO, 1);
533 memset((void*)lvaddr, 0, OBJSIZE_DISPATCHER * count);
534 TRACE(KERNEL, BZERO, 0);
537 case ObjType_KernelControlBlock:
538 debug(SUBSYS_CAPS, "KCB: zeroing %zu bytes @%#"PRIxLPADDR"\n",
539 ((size_t) OBJSIZE_KCB) * count, lpaddr);
540 TRACE(KERNEL, BZERO, 1);
541 memset((void*)lvaddr, 0, OBJSIZE_KCB * count);
542 TRACE(KERNEL, BZERO, 0);
546 debug(SUBSYS_CAPS, "Not zeroing %zu bytes @%#"PRIxLPADDR" for type %d\n",
547 (size_t)objsize * count, lpaddr, (int)type);
556 * \brief Create capabilities to kernel objects.
558 * This function creates 'count' kernel objects of 'type' into the memory
559 * area, based at 'addr' and of size 'objsize'. For each created kernel
560 * object, a capability is created to it and put consecutively into the array
561 * of CTEs pointed to by 'caps'. The array needs to have the appropriate size
562 * to hold all created caps. Some kernel objects can have a variable size. In
563 * that case, 'objsize' should be non-zero. and give the size multiplier. *
565 * \param type Type of objects to create.
566 * \param lpaddr Base address in the local address space.
567 * \param size Size of memory area as bytes.
568 * \param objsize For variable-sized objects, size in bytes.
569 * \param count Number of objects to be created
570 * (count <= caps_max_numobjs(type, size, objsize))
571 * \param dest_caps Pointer to array of CTEs to hold created caps.
575 // If you create more capability types you need to deal with them
576 // in the table below.
577 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
579 static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, gensize_t size,
580 gensize_t objsize, size_t count, coreid_t owner,
581 struct cte *dest_caps)
585 /* Parameter checking */
586 assert(dest_caps != NULL);
587 assert(type != ObjType_Null);
588 assert(type < ObjType_Num);
590 // objsize is 0 for non-sized types (e.g. VNodes)
591 // TODO cleanup semantics for type == CNode
592 //assert(objsize % BASE_PAGE_SIZE == 0);
593 assert(!type_is_mapping(type));
595 genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
597 debug(SUBSYS_CAPS, "creating caps for %#"PRIxGENPADDR
598 ", %" PRIuGENSIZE " bytes, objsize=%"PRIuGENSIZE
599 ", count=%zu, owner=%d, type=%d\n",
600 genpaddr, size, objsize, count, (int)owner, (int)type);
602 // Virtual address of the memory the kernel object resides in
603 // XXX: A better of doing this,
604 // this is creating caps that the kernel cannot address.
605 // It assumes that the cap is not of the type which will have to zeroed out.
607 if(lpaddr < PADDR_SPACE_LIMIT) {
608 lvaddr = local_phys_to_mem(lpaddr);
613 /* Initialize the created capability */
614 struct capability temp_cap;
615 memset(&temp_cap, 0, sizeof(struct capability));
616 temp_cap.type = type;
617 // XXX: Handle rights!
618 temp_cap.rights = CAPRIGHTS_ALLRIGHTS;
620 debug(SUBSYS_CAPS, "owner = %d, my_core_id = %d\n", owner, my_core_id);
621 if (owner == my_core_id) {
622 // If we're creating new local objects, they need to be cleared
623 err = caps_zero_objects(type, lpaddr, objsize, count);
624 if (err_is_fail(err)) {
632 /* Set the type specific fields and insert into #dest_caps */
635 for(dest_i = 0; dest_i < count; dest_i++) {
636 // Initialize type specific fields
637 temp_cap.u.frame.base = genpaddr + dest_i * objsize;
638 temp_cap.u.frame.bytes = objsize;
639 assert((get_size(&temp_cap) & BASE_PAGE_MASK) == 0);
640 // Insert the capability
641 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
642 if (err_is_fail(err)) {
648 case ObjType_PhysAddr:
649 for(dest_i = 0; dest_i < count; dest_i++) {
650 // Initialize type specific fields
651 temp_cap.u.physaddr.base = genpaddr + dest_i * objsize;
652 temp_cap.u.physaddr.bytes = objsize;
653 // Insert the capability
654 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
655 if (err_is_fail(err)) {
662 for(dest_i = 0; dest_i < count; dest_i++) {
663 // Initialize type specific fields
664 temp_cap.u.ram.base = genpaddr + dest_i * objsize;
665 temp_cap.u.ram.bytes = objsize;
666 // Insert the capabilities
667 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
668 if (err_is_fail(err)) {
674 case ObjType_DevFrame:
675 for(dest_i = 0; dest_i < count; dest_i++) {
676 // Initialize type specific fields
677 temp_cap.u.devframe.base = genpaddr + dest_i * objsize;
678 temp_cap.u.devframe.bytes = objsize;
679 // Insert the capabilities
680 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
681 if (err_is_fail(err)) {
687 case ObjType_L1CNode:
688 for (dest_i = 0; dest_i < count; dest_i++) {
689 assert(objsize >= OBJSIZE_L2CNODE);
690 assert(objsize % OBJSIZE_L2CNODE == 0);
691 temp_cap.u.l1cnode.cnode = lpaddr + dest_i * objsize;
692 temp_cap.u.l1cnode.allocated_bytes = objsize;
693 // XXX: implement CNode cap rights
694 temp_cap.u.l1cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
695 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
696 if (err_is_fail(err)) {
702 case ObjType_L2CNode:
703 for (dest_i = 0; dest_i < count; dest_i++) {
704 temp_cap.u.l2cnode.cnode = lpaddr + dest_i * objsize;
705 // XXX: implement CNode cap rights
706 temp_cap.u.l2cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
707 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
708 if (err_is_fail(err)) {
714 case ObjType_VNode_ARM_l1:
716 size_t objsize_vnode = vnode_objsize(type);
718 for(dest_i = 0; dest_i < count; dest_i++) {
719 // Initialize type specific fields
720 temp_cap.u.vnode_arm_l1.base =
721 genpaddr + dest_i * objsize_vnode;
724 // Insert the capability
725 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
726 if (err_is_fail(err)) {
734 case ObjType_VNode_ARM_l2:
736 size_t objsize_vnode = vnode_objsize(type);
738 for(dest_i = 0; dest_i < count; dest_i++) {
739 // Initialize type specific fields
740 temp_cap.u.vnode_arm_l2.base =
741 genpaddr + dest_i * objsize_vnode;
743 // Insert the capability
744 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
745 if (err_is_fail(err)) {
752 case ObjType_VNode_AARCH64_l0:
754 size_t objsize_vnode = vnode_objsize(type);
756 for(dest_i = 0; dest_i < count; dest_i++) {
757 // Initialize type specific fields
758 temp_cap.u.vnode_aarch64_l0.base =
759 genpaddr + dest_i * objsize_vnode;
761 // Insert the capability
762 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
763 if (err_is_fail(err)) {
771 case ObjType_VNode_AARCH64_l1:
773 size_t objsize_vnode = vnode_objsize(type);
775 for(dest_i = 0; dest_i < count; dest_i++) {
776 // Initialize type specific fields
777 temp_cap.u.vnode_aarch64_l1.base =
778 genpaddr + dest_i * objsize_vnode;
780 // Insert the capability
781 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
782 if (err_is_fail(err)) {
790 case ObjType_VNode_AARCH64_l2:
792 size_t objsize_vnode = vnode_objsize(type);
794 for(dest_i = 0; dest_i < count; dest_i++) {
795 // Initialize type specific fields
796 temp_cap.u.vnode_aarch64_l2.base =
797 genpaddr + dest_i * objsize_vnode;
799 // Insert the capability
800 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
802 if (err_is_fail(err)) {
809 case ObjType_VNode_AARCH64_l3:
811 size_t objsize_vnode = vnode_objsize(type);
813 for(dest_i = 0; dest_i < count; dest_i++) {
814 // Initialize type specific fields
815 temp_cap.u.vnode_aarch64_l3.base =
816 genpaddr + dest_i * objsize_vnode;
818 // Insert the capability
819 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
820 if (err_is_fail(err)) {
827 case ObjType_VNode_x86_32_ptable:
829 size_t objsize_vnode = vnode_objsize(type);
831 for(dest_i = 0; dest_i < count; dest_i++) {
832 // Initialize type specific fields
833 temp_cap.u.vnode_x86_32_ptable.base =
834 genpaddr + dest_i * objsize_vnode;
836 // Insert the capability
837 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
838 if (err_is_fail(err)) {
845 case ObjType_VNode_x86_32_pdir:
847 size_t objsize_vnode = vnode_objsize(type);
849 for(dest_i = 0; dest_i < count; dest_i++) {
850 // Initialize type specific fields
851 temp_cap.u.vnode_x86_32_pdir.base =
852 genpaddr + dest_i * objsize_vnode;
854 #if defined(__i386__) && !defined(CONFIG_PAE)
855 // Make it a good PDE by inserting kernel/mem VSpaces
856 lpaddr = gen_phys_to_local_phys(temp_cap.u.vnode_x86_32_pdir.base);
857 paging_x86_32_make_good_pdir(lpaddr);
860 // Insert the capability
861 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
862 if (err_is_fail(err)) {
869 case ObjType_VNode_x86_32_pdpt:
871 size_t objsize_vnode = vnode_objsize(type);
873 for(dest_i = 0; dest_i < count; dest_i++) {
874 // Initialize type specific fields
875 temp_cap.u.vnode_x86_32_pdir.base =
876 genpaddr + dest_i * objsize_vnode;
878 #if defined(__i386__) && defined(CONFIG_PAE)
879 // Make it a good PDPTE by inserting kernel/mem VSpaces
881 gen_phys_to_local_phys(temp_cap.u.vnode_x86_32_pdpt.base);
882 paging_x86_32_make_good_pdpte(var);
885 // Insert the capability
886 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
887 if (err_is_fail(err)) {
894 case ObjType_VNode_x86_64_ptable:
896 size_t objsize_vnode = vnode_objsize(type);
898 for(dest_i = 0; dest_i < count; dest_i++) {
899 // Initialize type specific fields
900 temp_cap.u.vnode_x86_64_ptable.base =
901 genpaddr + dest_i * objsize_vnode;
903 // Insert the capability
904 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
905 if (err_is_fail(err)) {
912 case ObjType_VNode_x86_64_pdir:
914 size_t objsize_vnode = vnode_objsize(type);
916 for(dest_i = 0; dest_i < count; dest_i++) {
917 // Initialize type specific fields
918 temp_cap.u.vnode_x86_64_pdir.base =
919 genpaddr + dest_i * objsize_vnode;
921 // Insert the capability
922 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
923 if (err_is_fail(err)) {
930 case ObjType_VNode_x86_64_pdpt:
932 size_t objsize_vnode = vnode_objsize(type);
934 for(dest_i = 0; dest_i < count; dest_i++) {
935 // Initialize type specific fields
936 temp_cap.u.vnode_x86_64_pdpt.base =
937 genpaddr + dest_i * objsize_vnode;
939 // Insert the capability
940 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
941 if (err_is_fail(err)) {
948 case ObjType_VNode_x86_64_pml4:
950 size_t objsize_vnode = vnode_objsize(type);
952 for(dest_i = 0; dest_i < count; dest_i++) {
953 // Initialize type specific fields
954 temp_cap.u.vnode_x86_64_pml4.base =
955 genpaddr + dest_i * objsize_vnode;
957 #if defined(__x86_64__) || defined(__k1om__)
958 // Make it a good PML4 by inserting kernel/mem VSpaces
959 lpaddr_t var = gen_phys_to_local_phys(get_address(&temp_cap));
960 paging_x86_64_make_good_pml4(var);
963 // Insert the capability
964 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
965 if (err_is_fail(err)) {
973 case ObjType_Dispatcher:
974 assert(OBJSIZE_DISPATCHER >= sizeof(struct dcb));
976 for(dest_i = 0; dest_i < count; dest_i++) {
977 // Initialize type specific fields
978 temp_cap.u.dispatcher.dcb = (struct dcb *)
979 (lvaddr + dest_i * OBJSIZE_DISPATCHER);
980 // Insert the capability
981 err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
982 if (err_is_fail(err)) {
989 // ID type does not refer to a kernel object
992 assert(objsize == 0);
995 // Prevent wrap around
996 if (id_cap_counter >= UINT32_MAX) {
997 return SYS_ERR_ID_SPACE_EXHAUSTED;
1000 // Generate a new ID, core_local_id monotonically increases
1001 temp_cap.u.id.coreid = my_core_id;
1002 temp_cap.u.id.core_local_id = id_cap_counter++;
1004 // Insert the capability
1005 err = set_cap(&dest_caps->cap, &temp_cap);
1009 temp_cap.u.io.start = 0;
1010 temp_cap.u.io.end = 65535;
1013 case ObjType_IRQSrc:
1014 /* Caller has to set vec_start and vec_end */
1015 case ObjType_Kernel:
1017 case ObjType_IRQTable:
1018 case ObjType_IRQDest:
1019 case ObjType_EndPoint:
1020 case ObjType_Notify_IPI:
1021 case ObjType_PerfMon:
1022 // These types do not refer to a kernel object
1023 assert(lpaddr == 0);
1025 assert(objsize == 0);
1028 // Insert the capability
1029 err = set_cap(&dest_caps->cap, &temp_cap);
1030 if (err_is_ok(err)) {
1035 case ObjType_KernelControlBlock:
1036 assert(OBJSIZE_KCB >= sizeof(struct kcb));
1038 for(size_t i = 0; i < count; i++) {
1039 // Initialize type specific fields
1040 temp_cap.u.kernelcontrolblock.kcb = (struct kcb *)
1041 (lvaddr + i * OBJSIZE_KCB);
1042 // Insert the capability
1043 err = set_cap(&dest_caps[i].cap, &temp_cap);
1044 if (err_is_fail(err)) {
1051 panic("Unhandled capability type or capability of this type cannot"
1055 if (err_is_fail(err)) {
1056 // Revert the partially initialized caps to zero
1057 for (size_t i = 0; i < dest_i; i++) {
1058 memset(&dest_caps[i], 0, sizeof(dest_caps[i]));
1063 // Set the owner for all the new caps
1064 for (size_t i = 0; i < dest_i; i++) {
1065 dest_caps[i].mdbnode.owner = owner;
1073 * Look up a capability in two-level cspace rooted at `rootcn`.
1075 errval_t caps_lookup_slot(struct capability *rootcn, capaddr_t cptr,
1076 uint8_t level, struct cte **ret, CapRights rights)
1078 TRACE(KERNEL, CAP_LOOKUP_SLOT, 0);
1080 cslot_t l1index, l2index;
1081 l1index = (cptr >> L2_CNODE_BITS) & MASK(CPTR_BITS-L2_CNODE_BITS);
1082 l2index = cptr & MASK(L2_CNODE_BITS);
1084 assert(ret != NULL);
1085 assert(rootcn != NULL);
1088 debug(SUBSYS_CAPS, "%s called with level=%hhu, from %p\n",
1089 __FUNCTION__, level,
1090 (void*)kernel_virt_to_elf_addr(__builtin_return_address(0)));
1091 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1092 return SYS_ERR_CAP_LOOKUP_DEPTH;
1096 // level 0 means that we do not do any resolution and just return the cte
1099 *ret = cte_for_cap(rootcn);
1100 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1104 if (rootcn->type != ObjType_L1CNode) {
1105 debug(SUBSYS_CAPS, "%s: rootcn->type = %d, called from %p\n",
1106 __FUNCTION__, rootcn->type,
1107 (void*)kernel_virt_to_elf_addr(__builtin_return_address(0)));
1108 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1109 // XXX: think about errors
1110 return SYS_ERR_CNODE_TYPE;
1112 assert(rootcn->type == ObjType_L1CNode);
1114 if (l1index >= cnode_get_slots(rootcn)) {
1115 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1116 debug(SUBSYS_CAPS, "%s: l1index = %"PRIuCSLOT", slots= %zu\n",
1117 __FUNCTION__, l1index, cnode_get_slots(rootcn));
1118 return SYS_ERR_L1_CNODE_INDEX;
1121 /* Apply rights to L1 CNode */
1122 if ((rootcn->rights & rights) != rights) {
1123 debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
1124 "Passed rights = %u, cnode_cap->rights = %u\n",
1125 rights, rootcn->rights);
1126 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1127 return SYS_ERR_CNODE_RIGHTS;
1130 struct cte *l2cnode = caps_locate_slot(get_address(rootcn), l1index);
1132 // level == 1 means that we terminate after looking up the slot in the L1
1135 if (l2cnode->cap.type == ObjType_Null) {
1136 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1137 return SYS_ERR_CAP_NOT_FOUND;
1140 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1144 // L2 CNode in given L1 slot does not exist
1145 if (l2cnode->cap.type == ObjType_Null) {
1146 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1147 debug(SUBSYS_CAPS, "%s: l2cnode is NULL\n", __FUNCTION__);
1148 return SYS_ERR_CNODE_NOT_FOUND;
1150 if (l2cnode->cap.type != ObjType_L2CNode) {
1151 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1152 debug(SUBSYS_CAPS, "%s: l2cnode->type = %d\n", __FUNCTION__,
1154 return SYS_ERR_CNODE_TYPE;
1156 assert(l2cnode->cap.type == ObjType_L2CNode);
1158 assert(l2index < L2_CNODE_SLOTS);
1160 /* Apply rights to L2 CNode */
1161 if ((l2cnode->cap.rights & rights) != rights) {
1162 debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
1163 "Passed rights = %u, cnode_cap->rights = %u\n",
1164 rights, l2cnode->cap.rights);
1165 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1166 return SYS_ERR_CNODE_RIGHTS;
1169 struct cte *cte = caps_locate_slot(get_address(&l2cnode->cap), l2index);
1170 if (cte->cap.type == ObjType_Null) {
1171 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1172 return SYS_ERR_CAP_NOT_FOUND;
1177 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1182 * Wrapper for caps_lookup_slot returning capability instead of cte.
1184 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
1185 uint8_t level, struct capability **ret, CapRights rights)
1187 TRACE(KERNEL, CAP_LOOKUP_CAP, 0);
1189 struct cte *ret_cte;
1190 errval_t err = caps_lookup_slot(cnode_cap, cptr, level, &ret_cte, rights);
1191 if (err_is_fail(err)) {
1194 *ret = &ret_cte->cap;
1195 TRACE(KERNEL, CAP_LOOKUP_CAP, 1);
1200 * \brief Create a capability from an existing capability metadata.
1202 * Used when sending capabilities across cores. The metadata is sent across
1203 * cores and the receiving monitor can create the new capability on its core.
1205 * \bug Does not check that supplied owner matches existing copies of cap.
1207 errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
1208 int cnode_level, cslot_t dest_slot, coreid_t owner,
1209 struct capability *src)
1211 TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 0);
1213 struct capability *cnode;
1214 err = caps_lookup_cap(root, cnode_cptr, cnode_level, &cnode,
1215 CAPRIGHTS_READ_WRITE);
1216 if (err_is_fail(err)) {
1217 return err_push(err, SYS_ERR_SLOT_LOOKUP_FAIL);
1219 if (cnode->type != ObjType_L1CNode &&
1220 cnode->type != ObjType_L2CNode)
1222 return SYS_ERR_CNODE_TYPE;
1225 struct cte *dest = caps_locate_slot(get_address(cnode), dest_slot);
1227 err = set_cap(&dest->cap, src);
1228 if (err_is_fail(err)) {
1232 dest->mdbnode.owner = owner;
1234 err = mdb_insert(dest);
1235 assert(err_is_ok(err));
1237 struct cte *neighbour = NULL;
1239 && (neighbour = mdb_predecessor(dest))
1240 && !is_copy(&dest->cap, &neighbour->cap))
1245 && (neighbour = mdb_successor(dest))
1246 && !is_copy(&dest->cap, &neighbour->cap))
1252 assert(!neighbour->mdbnode.in_delete);
1253 assert(neighbour->mdbnode.owner == owner);
1254 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
1256 CP_ATTR(remote_copies);
1257 CP_ATTR(remote_ancs);
1258 CP_ATTR(remote_descs);
1262 dest->mdbnode.locked = false;
1263 if (owner != my_core_id) {
1264 // For foreign caps it does not really matter if ancestors or
1265 // descendants exist
1266 dest->mdbnode.remote_copies = true;
1267 dest->mdbnode.remote_ancs = false;
1268 dest->mdbnode.remote_descs = false;
1271 // We just created a new copy of a owned capability from nothing.
1272 // This is either caused by a retype, or by sharing a capability
1273 // that does not care about locality.
1274 // XXX: This should probably be done more explicitly -MN
1275 if (distcap_needs_locality(dest->cap.type)) {
1276 // Retype, so have ancestors and no descendants
1277 dest->mdbnode.remote_copies = false;
1278 dest->mdbnode.remote_ancs = true;
1279 dest->mdbnode.remote_descs = false;
1282 dest->mdbnode.remote_copies = false;
1283 dest->mdbnode.remote_ancs = false;
1284 dest->mdbnode.remote_descs = false;
1289 TRACE_CAP_MSG("created", dest);
1291 TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 1);
1295 //{{{1 Capability creation
1297 /// check arguments, return true iff ok
1298 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
1300 static bool check_caps_create_arguments(enum objtype type,
1301 size_t bytes, size_t objsize,
1304 gensize_t base_mask = BASE_PAGE_MASK;
1305 if (type_is_vnode(type)) {
1306 base_mask = vnode_objsize(type) - 1;
1308 /* mappable types need to be at least BASE_PAGE_SIZEd */
1309 if (type_is_mappable(type)) {
1310 /* source size not multiple of or not aligned to BASE_PAGE_SIZE */
1311 if (bytes & base_mask) {
1312 debug(SUBSYS_CAPS, "source size not multiple of BASE_PAGE_SIZE\n");
1315 /* objsize > 0 and not multiple of BASE_PAGE_SIZE */
1316 if (objsize > 0 && objsize & base_mask) {
1317 debug(SUBSYS_CAPS, "object size not multiple of BASE_PAGE_SIZE\n");
1321 /* check that bytes can be evenly divided into objsize sized chunks */
1322 if (exact && bytes > 0 && objsize > 0) {
1323 if (bytes % objsize) {
1324 debug(SUBSYS_CAPS, "source size cannot be evenly divided into object size-sized chunks\n");
1326 return bytes % objsize == 0;
1332 if (type == ObjType_L1CNode) {
1333 /* L1 CNode minimum size is OBJSIZE_L2CNODE */
1334 if (bytes < OBJSIZE_L2CNODE || objsize < OBJSIZE_L2CNODE) {
1335 debug(SUBSYS_CAPS, "source size or L1 CNode objsize < OBJSIZE_L2CNODE\n");
1338 /* check that bytes can be evenly divided into L1 CNodes of objsize */
1339 if (exact && (bytes % objsize != 0)) {
1340 debug(SUBSYS_CAPS, "source not evenly divisible into L1 CNodes of objsize\n");
1343 /* L1 CNode size must be multiple of 1UL << OBJBITS_CTE */
1344 return objsize % (1UL << OBJBITS_CTE) == 0;
1347 if (type == ObjType_L2CNode) {
1348 /* L2 CNode size must be OBJSIZE_L2CNODE */
1349 if (bytes < OBJSIZE_L2CNODE || objsize != OBJSIZE_L2CNODE) {
1350 debug(SUBSYS_CAPS, "source size < or L2 CNode objsize != OBJSIZE_L2CNODE\n");
1353 if (exact && (bytes % objsize != 0)) {
1354 debug(SUBSYS_CAPS, "source not evenly divisible into L2 CNodes of objsize\n");
1360 /* special case Dispatcher which is 1kB right now */
1361 if (type == ObjType_Dispatcher) {
1362 if (bytes & (OBJSIZE_DISPATCHER - 1)) {
1365 if (objsize > 0 && objsize != OBJSIZE_DISPATCHER) {
1372 // All other types do not need special alignments/offsets
1377 /** Create caps to new kernel objects.
1378 * This takes the size of the memory region in bytes, and the size of
1379 * individual objects in bytes. The following needs to hold:
1380 * bytes % objbytes == 0
1382 errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bytes,
1383 size_t objsize, coreid_t owner, struct cte *caps)
1385 TRACE(KERNEL, CAP_CREATE_NEW, 0);
1386 /* Parameter checking */
1387 assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1388 debug(SUBSYS_CAPS, "caps_create_new: type = %d, addr = %#"PRIxLPADDR
1389 ", bytes=%zu, objsize=%zu\n", type, addr, bytes, objsize);
1390 assert(check_caps_create_arguments(type, bytes, objsize, false));
1391 assert(addr == 0 || check_caps_create_arguments(type, bytes, objsize, true));
1393 size_t numobjs = caps_max_numobjs(type, bytes, objsize);
1394 assert(numobjs > 0);
1395 // XXX: Dispatcher creation is kind of hacky right now :(
1396 // Consider allowing non-mappable types to be < BASE_PAGE_SIZE
1397 //if (type == ObjType_Dispatcher) {
1401 /* Create the new capabilities */
1402 errval_t err = caps_create(type, addr, bytes, objsize, numobjs, owner, caps);
1403 if (err_is_fail(err)) {
1407 // Handle the mapping database
1408 set_init_mapping(caps, numobjs);
1410 TRACE_CAP_MSG("created", &caps[0]);
1412 TRACE(KERNEL, CAP_CREATE_NEW, 1);
1416 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
1418 /// Create `count` new caps of `type` from `offset` in src, and put them in
1419 /// `dest_cnode` starting at `dest_slot`.
1420 errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
1421 struct capability *dest_cnode, cslot_t dest_slot,
1422 struct cte *src_cte, gensize_t offset,
1425 TRACE(KERNEL, CAP_RETYPE, 0);
1427 genpaddr_t base = 0;
1430 bool do_range_check = false;
1431 struct capability *src_cap = &src_cte->cap;
1433 /* Parameter checking */
1434 assert(type != ObjType_Null);
1435 assert(type < ObjType_Num);
1436 if (type == ObjType_Null || type >= ObjType_Num) {
1437 return SYS_ERR_INVALID_RETYPE;
1440 debug(SUBSYS_CAPS, "%s: Retyping to type=%d, from offset=%" PRIuGENSIZE
1441 ", objsize=%" PRIuGENSIZE ", count=%zu\n",
1442 __FUNCTION__, type, offset, objsize, count);
1444 /* check that offset into source cap is multiple of BASE_PAGE_SIZE */
1445 if (src_cap->type != ObjType_IRQSrc && offset % BASE_PAGE_SIZE != 0) {
1446 return SYS_ERR_RETYPE_INVALID_OFFSET;
1448 assert(offset % BASE_PAGE_SIZE == 0 || src_cap->type == ObjType_IRQSrc);
1450 // check that size is multiple of BASE_PAGE_SIZE for mappable types
1451 gensize_t base_size = BASE_PAGE_SIZE;
1452 if (type_is_vnode(type)) {
1453 base_size = vnode_objsize(type);
1455 if (type_is_mappable(type) && objsize % base_size != 0) {
1456 debug(SUBSYS_CAPS, "%s: objsize = %"PRIuGENSIZE"\n", __FUNCTION__, objsize);
1457 return SYS_ERR_INVALID_SIZE;
1459 else if (type == ObjType_L1CNode && objsize % OBJSIZE_L2CNODE != 0)
1461 printk(LOG_WARN, "%s: CNode: objsize = %" PRIuGENSIZE "\n", __FUNCTION__, objsize);
1462 return SYS_ERR_INVALID_SIZE;
1464 else if (type == ObjType_L2CNode && objsize != OBJSIZE_L2CNODE)
1466 printk(LOG_WARN, "%s: L2CNode: objsize = %"PRIuGENSIZE"\n", __FUNCTION__, objsize);
1467 return SYS_ERR_INVALID_SIZE;
1469 assert((type_is_mappable(type) && objsize % base_size == 0) ||
1470 (type == ObjType_L1CNode && objsize % OBJSIZE_L2CNODE == 0 &&
1471 objsize >= OBJSIZE_L2CNODE) ||
1472 (type == ObjType_L2CNode && objsize == OBJSIZE_L2CNODE) ||
1473 !type_is_mappable(type));
1475 /* No explicit retypes to Mapping allowed */
1476 if (type_is_mapping(type)) {
1477 return SYS_ERR_RETYPE_MAPPING_EXPLICIT;
1481 TRACE_CAP_MSG("retyping", src_cte);
1483 /* Check retypability */
1484 err = is_retypeable(src_cte, src_cap->type, type, from_monitor);
1485 if (err_is_fail(err)) {
1486 if (err_no(err) != SYS_ERR_REVOKE_FIRST) {
1487 printk(LOG_NOTE, "caps_retype: is_retypeable failed: %"PRIuERRV"\n", err);
1488 debug(SUBSYS_CAPS, "caps_retype: is_retypeable failed\n");
1492 "caps_retype: is_retypeable() returned SYS_ERR_REVOKE_FIRST, doing range check\n");
1493 // We handle err_revoke_first fine-grained checking below, as it
1494 // might happen for non-overlapping regions.
1496 // TODO: move the range checking into is_retypeable() or even
1497 // is_revoked_first(), -SG 2016-04-18
1498 do_range_check = true;
1501 // from here: src cap type is one of these.
1502 assert(src_cap->type == ObjType_PhysAddr ||
1503 src_cap->type == ObjType_RAM ||
1504 src_cap->type == ObjType_Dispatcher ||
1505 src_cap->type == ObjType_Frame ||
1506 src_cap->type == ObjType_DevFrame ||
1507 src_cap->type == ObjType_IRQSrc);
1509 if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
1510 base = get_address(src_cap);
1511 size = get_size(src_cap);
1514 maxobjs = caps_max_numobjs(type, get_size(src_cap), objsize);
1515 debug(SUBSYS_CAPS, "maximum possible new object count: %zu\n", maxobjs);
1518 debug(SUBSYS_CAPS, "caps_retype: maxobjs == 0\n");
1519 return SYS_ERR_INVALID_SIZE;
1522 if (count > maxobjs) {
1523 debug(SUBSYS_CAPS, "caps_retype: maxobjs = %zu, count = %zu\n", maxobjs, count);
1524 return SYS_ERR_RETYPE_INVALID_COUNT;
1526 // from here: count <= maxobjs
1527 assert(count <= maxobjs);
1528 // make sure nobody calls with the old behaviour
1530 return SYS_ERR_RETYPE_INVALID_COUNT;
1534 /* check that we can create `count` objs from `offset` in source, and
1535 * update base accordingly */
1536 if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
1537 // TODO: convince ourselves that this is the only condition on offset
1538 if (offset + count * objsize > get_size(src_cap)) {
1539 debug(SUBSYS_CAPS, "caps_retype: cannot create all %zu objects"
1540 " of size 0x%" PRIxGENSIZE " from offset 0x%" PRIxGENSIZE "\n",
1541 count, objsize, offset);
1542 return SYS_ERR_RETYPE_INVALID_OFFSET;
1544 // adjust base address for new objects
1547 // Check whether we got SYS_ERR_REVOKE_FIRST because of
1548 // non-overlapping child
1549 if (do_range_check) {
1550 int find_range_result = 0;
1551 struct cte *found_cte = NULL;
1552 err = mdb_find_range(get_type_root(src_cap->type), base, objsize * count,
1553 MDB_RANGE_FOUND_SURROUNDING, &found_cte, &find_range_result);
1554 // this should never return an error unless we mess up the
1555 // non-user supplied arguments
1556 if (err_is_fail(err)) {
1557 printk(LOG_WARN, "mdb_find_range returned: %"PRIuERRV"\n", err);
1559 assert(err_is_ok(err));
1560 // return REVOKE_FIRST, if we found a cap inside the region
1561 // (FOUND_INNER == 2) or overlapping the region (FOUND_PARTIAL == 3)
1562 if (find_range_result >= MDB_RANGE_FOUND_INNER) {
1564 "%s: found existing region inside, or overlapping requested region:\n",
1566 debug(SUBSYS_CAPS, "%s: our region: %#"PRIxGENPADDR"--%#"PRIxGENPADDR"\n",
1567 __FUNCTION__, base, base+objsize*count);
1568 if (found_cte && kernel_loglevel >= LOG_DEBUG &&
1569 kernel_log_subsystem_mask & SUBSYS_CAPS)
1572 sprint_cap(capbuf, 128, &found_cte->cap);
1573 printk(LOG_NOTE, "%s: cap=%s\n", __FUNCTION__, capbuf);
1574 if (type_is_mapping(found_cte->cap.type)) {
1575 sprint_cap(capbuf, 128, found_cte->cap.u.frame_mapping.cap);
1576 printk(LOG_NOTE, "%s: ... is mapping for cap=%s\n",
1577 __FUNCTION__, capbuf);
1579 assert(get_address(&found_cte->cap) >= base &&
1580 get_address(&found_cte->cap) < base+objsize*count);
1582 return SYS_ERR_REVOKE_FIRST;
1584 // return REVOKE_FIRST, if we found a cap that isn't our source
1585 // (or a copy of our source) covering the whole requested region.
1586 else if (find_range_result == MDB_RANGE_FOUND_SURROUNDING &&
1587 !is_copy(&found_cte->cap, src_cap))
1590 "%s: found non source region fully covering requested region\n",
1592 return SYS_ERR_REVOKE_FIRST;
1597 /* check that destination slots all fit within target cnode */
1598 if (dest_slot + count > cnode_get_slots(dest_cnode)) {
1599 debug(SUBSYS_CAPS, "caps_retype: dest slots don't fit in cnode\n");
1600 return SYS_ERR_SLOTS_INVALID;
1603 /* check that destination slots are all empty */
1604 debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1606 get_address(dest_cnode), (int)dest_slot);
1607 for (cslot_t i = 0; i < count; i++) {
1608 if (caps_locate_slot(get_address(dest_cnode), dest_slot + i)->cap.type
1610 debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1611 (int)(dest_slot + i));
1612 return SYS_ERR_SLOTS_IN_USE;
1616 /* Check that L1 CNode is destination when creating L2 CNode */
1617 if (type == ObjType_L2CNode) {
1618 debug(SUBSYS_CAPS, "caps_retype: check that dest cnode is L1"
1619 " when creating L2 CNodes\n");
1620 if (dest_cnode->type != ObjType_L1CNode &&
1621 dest_cnode->type != ObjType_L2CNode)
1623 panic("L2 CNode can only be created in L1 or L2 CNode\n");
1627 // IRQSrc specific checks
1628 uint64_t vec_start_new = offset;
1629 uint64_t vec_end_new = objsize;
1630 if(src_cap->type == ObjType_IRQSrc){
1632 // Check new range is valid
1633 if(vec_start_new > vec_end_new){
1634 return SYS_ERR_RETYPE_INVALID_OFFSET;
1637 // Check vec_start_new in range
1638 if(!(src_cap->u.irqsrc.vec_start <= vec_start_new &&
1639 vec_start_new <= src_cap->u.irqsrc.vec_end)){
1640 return SYS_ERR_RETYPE_INVALID_OFFSET;
1643 // Check vec_end_new in range
1644 if(!(src_cap->u.irqsrc.vec_start <= vec_end_new &&
1645 vec_end_new <= src_cap->u.irqsrc.vec_end)){
1646 return SYS_ERR_RETYPE_INVALID_OBJSIZE;
1651 /* create new caps */
1652 struct cte *dest_cte =
1653 caps_locate_slot(get_address(dest_cnode), dest_slot);
1654 if(type == ObjType_IRQSrc){
1655 // Pass special arguments
1656 err = caps_create(type, 0, 0, 0, 1, my_core_id, dest_cte);
1658 dest_cte->cap.u.irqsrc.vec_start = vec_start_new;
1659 dest_cte->cap.u.irqsrc.vec_end = vec_end_new;
1662 err = caps_create(type, base, size, objsize, count, my_core_id, dest_cte);
1664 if (err_is_fail(err)) {
1665 debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
1666 return err_push(err, SYS_ERR_RETYPE_CREATE);
1669 /* special initialisation for endpoint caps */
1670 if (type == ObjType_EndPoint) {
1671 assert(src_cap->type == ObjType_Dispatcher);
1673 struct capability *dest_cap = &dest_cte->cap;
1674 dest_cap->u.endpoint.listener = src_cap->u.dispatcher.dcb;
1677 /* Handle mapping */
1678 for (size_t i = 0; i < count; i++) {
1679 mdb_insert(&dest_cte[i]);
1682 #ifdef TRACE_PMEM_CAPS
1683 for (size_t i = 0; i < count; i++) {
1684 TRACE_CAP_MSG("created", &dest_cte[i]);
1688 TRACE(KERNEL, CAP_RETYPE, 1);
1692 /// Check the validity of a retype operation
1693 errval_t is_retypeable(struct cte *src_cte, enum objtype src_type,
1694 enum objtype dest_type, bool from_monitor)
1696 if (!is_well_founded(src_type, dest_type)) {
1697 return SYS_ERR_INVALID_RETYPE;
1698 } else if (!is_revoked_first(src_cte, src_type)){
1699 //printf("err_revoke_first: (%p, %d, %d)\n", src_cte, src_type, dest_type);
1700 return SYS_ERR_REVOKE_FIRST;
1701 } else if (dest_type == ObjType_EndPoint && src_cte->mdbnode.owner == my_core_id) {
1702 // XXX: because of the current "multi-retype" hack for endpoints, a
1703 // dispatcher->endpoint retype can happen irrespective of the existence
1704 // of descendants on any core.
1705 // However, we only do this for locally owned caps as the owner should
1706 // be notified that the cap has remote descendants
1708 } else if (!from_monitor && (src_cte->mdbnode.owner != my_core_id
1709 || src_cte->mdbnode.remote_descs)) {
1710 return SYS_ERR_RETRY_THROUGH_MONITOR;
1716 /// Create copies to a slot within a cnode
1717 errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
1718 struct cte *src_cte, bool mint, uintptr_t param1,
1721 /* Parameter Checking */
1722 assert(dest_cnode_cte->cap.type == ObjType_L1CNode ||
1723 dest_cnode_cte->cap.type == ObjType_L2CNode);
1725 // only allow L2 CNodes and BSP KCB in L1 CNode
1726 // XXX: BSPKCB should not be in rootcn...
1727 if (dest_cnode_cte->cap.type == ObjType_L1CNode &&
1728 src_cte->cap.type != ObjType_L2CNode &&
1729 src_cte->cap.type != ObjType_KernelControlBlock)
1731 printk(LOG_WARN, "trying to copy cap type %d into cap type %d\n",
1732 src_cte->cap.type, dest_cnode_cte->cap.type);
1733 return SYS_ERR_DEST_TYPE_INVALID;
1736 struct cte *dest_cte;
1737 dest_cte = caps_locate_slot(get_address(&dest_cnode_cte->cap), dest_slot);
1738 return caps_copy_to_cte(dest_cte, src_cte, mint, param1, param2);
1742 /// Create copies to a cte
1743 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
1744 errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
1745 uintptr_t param1, uintptr_t param2)
1748 /* Parameter checking */
1750 assert(dest_cte != NULL);
1751 assert(src_cte != NULL);
1753 struct capability *src_cap = &src_cte->cap;
1754 struct capability *dest_cap = &dest_cte->cap;
1755 // NULL caps cannot be copied/minted
1756 if (src_cap->type == ObjType_Null) {
1757 return SYS_ERR_CAP_NOT_FOUND;
1759 // Parameters should be 0 if not minting
1761 assert(param1 == 0);
1762 assert(param2 == 0);
1765 assert(!src_cte->mdbnode.in_delete);
1767 /* Insert #source_cap into #dest_cap */
1768 err = set_cap(dest_cap, src_cap);
1769 if (err_is_fail(err)) {
1773 /* Transfer MDB attributes that must be equal for all copies */
1774 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1777 CP_ATTR(remote_copies);
1778 CP_ATTR(remote_ancs);
1779 CP_ATTR(remote_descs);
1784 TRACE_CAP_MSG("copied to", dest_cte);
1785 // Handle mapping here only for non-mint operations
1786 // (mint can change eq fields which would make the early insertion
1787 // invalid in some cases)
1788 mdb_insert(dest_cte);
1792 TRACE_CAP_MSG("minting to", dest_cte);
1795 /* For minting, set the specified parameters */
1796 // Process source-specific parameters for minting
1797 // XXX: If failure, revert the insertion
1798 switch(src_cap->type) {
1799 case ObjType_EndPoint:
1800 // XXX: FIXME: check that buffer offset lies wholly within the disp frame
1801 // can't easily enforce this here, because the dispatcher frame may not
1803 /* if (param1 < sizeof(struct dispatcher) ||
1804 dest_cap->u.endpoint.listener->disp == NULL ||
1805 param2 < IDC_RECV_LENGTH ||
1806 param1 + sizeof(struct idc_endpoint) + param2 * sizeof(uintptr_t) >
1807 (1UL << dest_cap->u.endpoint.listener->disp_cte.cap.u.frame.bits)) {
1808 return SYS_ERR_INVALID_EPBUF;
1810 if (param2 < LMP_RECV_HEADER_LENGTH) {
1811 return SYS_ERR_INVALID_EPLEN;
1813 dest_cap->u.endpoint.epoffset = param1;
1814 dest_cap->u.endpoint.epbuflen = param2;
1818 if(src_cap->u.io.start <= param1) {
1819 dest_cap->u.io.start = param1;
1821 if(src_cap->u.io.end >= param2) {
1822 dest_cap->u.io.end = param2;
1827 // Unhandled source type for mint
1828 return SYS_ERR_INVALID_SOURCE_TYPE;
1831 // Insert after doing minting operation
1832 mdb_insert(dest_cte);