3 * \brief Kernel capability management implementation.
7 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
18 #include <barrelfish_kpi/syscalls.h>
19 #include <barrelfish_kpi/paging_arch.h>
20 #include <barrelfish_kpi/lmp.h>
22 #include <capabilities.h>
23 #include <cap_predicates.h>
27 #include <paging_kernel_arch.h>
29 #include <mdb/mdb_tree.h>
30 #include <trace/trace.h>
31 #include <trace_definitions/trace_defs.h>
34 /// Sets the specified number of low-order bits to 1
35 #define MASK(bits) ((1UL << bits) - 1)
37 #ifdef TRACE_PMEM_CAPS
38 uint64_t trace_types_enabled = TRACE_TYPES_ENABLED_INITIAL;
39 genpaddr_t TRACE_PMEM_BEGIN = TRACE_PMEM_BEGIN_INITIAL;
40 gensize_t TRACE_PMEM_SIZE = TRACE_PMEM_SIZE_INITIAL;
42 void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
45 trace_types_enabled = types;
46 TRACE_PMEM_BEGIN = start;
47 TRACE_PMEM_SIZE = size;
49 trace_types_enabled = false;
54 struct capability monitor_ep;
56 int sprint_cap(char *buf, size_t len, struct capability *cap)
59 case ObjType_PhysAddr:
60 return snprintf(buf, len,
61 "physical address range cap (0x%" PRIxGENPADDR ":%u)",
62 cap->u.physaddr.base, cap->u.physaddr.bits);
65 return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":%u)",
66 cap->u.ram.base, cap->u.ram.bits);
69 int ret = snprintf(buf, len, "CNode cap "
70 "(bits %u, rights mask 0x%" PRIxCAPRIGHTS ")",
71 cap->u.cnode.bits, cap->u.cnode.rightsmask);
72 if (cap->u.cnode.guard_size != 0 && ret < len) {
73 ret += snprintf(&buf[ret], len - ret, " (guard 0x%" PRIxCADDR ":%u)",
74 cap->u.cnode.guard, cap->u.cnode.guard_size);
79 case ObjType_Dispatcher:
80 return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
83 return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":%u)",
84 cap->u.frame.base, cap->u.frame.bits);
86 case ObjType_DevFrame:
87 return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":%u)",
88 cap->u.frame.base, cap->u.devframe.bits);
90 case ObjType_VNode_ARM_l1:
91 return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
92 cap->u.vnode_arm_l1.base);
94 case ObjType_VNode_ARM_l2:
95 return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
96 cap->u.vnode_arm_l2.base);
98 case ObjType_VNode_x86_32_ptable:
99 return snprintf(buf, len, "x86_32 Page table at 0x%" PRIxGENPADDR,
100 cap->u.vnode_x86_32_ptable.base);
102 case ObjType_VNode_x86_32_pdir:
103 return snprintf(buf, len, "x86_32 Page directory at 0x%" PRIxGENPADDR,
104 cap->u.vnode_x86_32_pdir.base);
106 case ObjType_VNode_x86_32_pdpt:
107 return snprintf(buf, len, "x86_32 PDPT at 0x%" PRIxGENPADDR,
108 cap->u.vnode_x86_32_pdpt.base);
110 case ObjType_VNode_x86_64_ptable:
111 return snprintf(buf, len, "x86_64 Page table at 0x%" PRIxGENPADDR,
112 cap->u.vnode_x86_64_ptable.base);
114 case ObjType_VNode_x86_64_pdir:
115 return snprintf(buf, len, "x86_64 Page directory at 0x%" PRIxGENPADDR,
116 cap->u.vnode_x86_64_pdir.base);
118 case ObjType_VNode_x86_64_pdpt:
119 return snprintf(buf, len, "x86_64 PDPT at 0x%" PRIxGENPADDR,
120 cap->u.vnode_x86_64_pdpt.base);
122 case ObjType_VNode_x86_64_pml4:
123 return snprintf(buf, len, "x86_64 PML4 at 0x%" PRIxGENPADDR,
124 cap->u.vnode_x86_64_pml4.base);
126 case ObjType_IRQTable:
127 return snprintf(buf, len, "IRQTable cap");
129 case ObjType_EndPoint:
130 return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
131 cap->u.endpoint.listener, cap->u.endpoint.epoffset);
134 return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
135 cap->u.io.start, cap->u.io.end);
138 return snprintf(buf, len, "Kernel cap");
141 return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
142 " core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
143 cap->u.id.core_local_id);
145 case ObjType_PerfMon:
146 return snprintf(buf, len, "PerfMon cap");
149 return snprintf(buf, len, "Null capability (empty slot)");
152 return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
156 void caps_trace(const char *func, int line, struct cte *cte, const char *msg)
159 sprint_cap(cap_buf, 512, &cte->cap);
163 dispatcher_handle_t handle = dcb_current->disp;
164 struct dispatcher_shared_generic *disp =
165 get_dispatcher_shared_generic(handle);
166 snprintf(disp_buf, 64, "from %.*s", DISP_NAME_LEN, disp->name);
169 strcpy(disp_buf, "no disp");
172 printk(LOG_WARN, "%s: %s:%d: %s %p %s"
173 " (owner:%" PRIuCOREID ", rc:%d/ra:%d/rd:%d)\n",
174 disp_buf, func, line, (msg ? : ""), cte, cap_buf, cte->mdbnode.owner,
175 cte->mdbnode.remote_copies, cte->mdbnode.remote_ancs,
176 cte->mdbnode.remote_descs);
180 * ID capability core_local_id counter.
182 static uint32_t id_cap_counter = 1;
185 * Sets #dest equal to #src
187 * #dest cannot be in use.
189 static errval_t set_cap(struct capability *dest, struct capability *src)
191 /* Parameter checking */
193 assert(dest != NULL);
195 // Reserved object bits must always be greater/equal to actual object size
196 assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
198 // Cannot overwrite an already existing cap
199 if (dest->type != ObjType_Null) {
200 return SYS_ERR_SLOT_IN_USE;
203 memcpy(dest, src, sizeof(struct capability));
208 * \brief Determine how many objects can be created in a specified region.
210 * This function computes the number of objects that can be created by a call
213 * \param type Type of objects to create.
214 * \param bits Size of memory area as 2^bits.
215 * \param objbits For variable-sized objects, size multiplier as 2^bits.
217 * \return Number of objects to be created, or zero on error
220 // If you create more capability types you need to deal with them
221 // in the table below.
222 STATIC_ASSERT(27 == ObjType_Num, "Knowledge of all cap types");
224 static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
227 case ObjType_PhysAddr:
230 case ObjType_DevFrame:
231 if (objbits > bits) {
234 return 1UL << (bits - objbits);
238 if (bits < OBJBITS_CTE || objbits > bits - OBJBITS_CTE) {
241 return 1UL << (bits - OBJBITS_CTE - objbits);
244 case ObjType_VNode_x86_64_pml4:
245 case ObjType_VNode_x86_64_pdpt:
246 case ObjType_VNode_x86_64_pdir:
247 case ObjType_VNode_x86_64_ptable:
248 case ObjType_VNode_x86_32_pdpt:
249 case ObjType_VNode_x86_32_pdir:
250 case ObjType_VNode_x86_32_ptable:
251 case ObjType_VNode_ARM_l1:
252 case ObjType_VNode_ARM_l2:
254 size_t objbits_vnode = vnode_objbits(type);
255 if (bits < objbits_vnode) {
258 return 1UL << (bits - objbits_vnode);
262 case ObjType_Dispatcher:
263 if (bits < OBJBITS_DISPATCHER) {
266 return 1UL << (bits - OBJBITS_DISPATCHER);
269 case ObjType_KernelControlBlock:
270 if (bits < OBJBITS_KCB) {
273 return 1UL << (bits - OBJBITS_KCB);
277 case ObjType_IRQTable:
279 case ObjType_EndPoint:
281 case ObjType_Notify_RCK:
282 case ObjType_Notify_IPI:
283 case ObjType_PerfMon:
288 panic("invalid type");
294 * \brief Initialize the objects for which local caps are about to be created.
296 * For the meaning of the parameters, see the 'caps_create' function.
298 STATIC_ASSERT(ObjType_Num == 27, "Knowledge of all cap types");
300 static errval_t caps_init_objects(enum objtype type, lpaddr_t lpaddr, uint8_t
301 bits, uint8_t objbits, size_t numobjs)
303 // Virtual address of the memory the kernel object resides in
304 // XXX: A better of doing this,
305 // this is creating caps that the kernel cannot address.
306 // It assumes that the cap is not of the type which will have to zeroed out.
308 if(lpaddr < PADDR_SPACE_LIMIT) {
309 lvaddr = local_phys_to_mem(lpaddr);
317 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
318 // XXX: SCC hack, while we don't have a devframe allocator
319 if(lpaddr + ((lpaddr_t)1 << bits) < PADDR_SPACE_LIMIT) {
320 memset((void*)lvaddr, 0, (lvaddr_t)1 << bits);
322 printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
323 " uninitialized\n", lpaddr);
325 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
329 case ObjType_VNode_ARM_l1:
330 case ObjType_VNode_ARM_l2:
331 case ObjType_VNode_x86_32_ptable:
332 case ObjType_VNode_x86_32_pdir:
333 case ObjType_VNode_x86_32_pdpt:
334 case ObjType_VNode_x86_64_ptable:
335 case ObjType_VNode_x86_64_pdir:
336 case ObjType_VNode_x86_64_pdpt:
337 case ObjType_VNode_x86_64_pml4:
338 case ObjType_Dispatcher:
339 case ObjType_KernelControlBlock:
340 TRACE(KERNEL, BZERO, 1);
341 memset((void*)lvaddr, 0, 1UL << bits);
342 TRACE(KERNEL, BZERO, 0);
354 * \brief Create capabilities to kernel objects.
356 * This function creates kernel objects of 'type' into the memory
357 * area, based at 'addr' and of size 2^'bits', so they completely fill the
358 * area. For each created kernel object, a capability is created to it and
359 * put consecutively into the array of CTEs pointed to by 'caps'. The array
360 * needs to have the appropriate size to hold all created caps. Some kernel
361 * objects can have a variable size. In that case, 'objbits' should be non-zero
362 * and give the a size multiplier as 2^'objbits'.
364 * \param type Type of objects to create.
365 * \param addr Base address in the local address space.
366 * \param bits Size of memory area as 2^bits.
367 * \param objbits For variable-sized objects, size multiplier as 2^bits.
368 * \param numobjs Number of objects to be created, from caps_numobjs()
369 * \param dest_caps Pointer to array of CTEs to hold created caps.
373 // If you create more capability types you need to deal with them
374 // in the table below.
375 STATIC_ASSERT(27 == ObjType_Num, "Knowledge of all cap types");
377 static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, uint8_t bits,
378 uint8_t objbits, size_t numobjs, coreid_t owner,
379 struct cte *dest_caps)
383 /* Parameter checking */
384 assert(dest_caps != NULL);
385 assert(type != ObjType_Null);
386 assert(type < ObjType_Num);
389 genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
391 // Virtual address of the memory the kernel object resides in
392 // XXX: A better of doing this,
393 // this is creating caps that the kernel cannot address.
394 // It assumes that the cap is not of the type which will have to zeroed out.
396 if(lpaddr < PADDR_SPACE_LIMIT) {
397 lvaddr = local_phys_to_mem(lpaddr);
402 /* Initialize the created capability */
403 struct capability src_cap;
404 memset(&src_cap, 0, sizeof(struct capability));
406 // XXX: Handle rights!
407 src_cap.rights = CAPRIGHTS_ALLRIGHTS;
409 if (owner == my_core_id) {
410 // If we're creating new local objects, they need to be initialized
411 err = caps_init_objects(type, lpaddr, bits, objbits, numobjs);
412 if (err_is_fail(err)) {
420 /* Set the type specific fields and insert into #dest_caps */
423 TRACE(KERNEL, BZERO, 1);
424 // XXX: SCC hack, while we don't have a devframe allocator
425 if(lpaddr + ((lpaddr_t)1 << bits) < PADDR_SPACE_LIMIT) {
426 memset((void*)lvaddr, 0, (lvaddr_t)1 << bits);
428 printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
429 " uninitialized\n", lpaddr);
431 TRACE(KERNEL, BZERO, 0);
432 for(dest_i = 0; dest_i < numobjs; dest_i++) {
433 // Initialize type specific fields
434 src_cap.u.frame.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
435 src_cap.u.frame.bits = objbits;
436 // Insert the capabilities
437 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
438 if (err_is_fail(err)) {
444 case ObjType_PhysAddr:
445 for(dest_i = 0; dest_i < numobjs; dest_i++) {
446 // Initialize type specific fields
447 src_cap.u.physaddr.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
448 src_cap.u.physaddr.bits = objbits;
449 // Insert the capabilities
450 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
451 if (err_is_fail(err)) {
458 for(dest_i = 0; dest_i < numobjs; dest_i++) {
459 // Initialize type specific fields
460 src_cap.u.ram.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
461 src_cap.u.ram.bits = objbits;
462 // Insert the capabilities
463 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
464 if (err_is_fail(err)) {
470 case ObjType_DevFrame:
471 for(dest_i = 0; dest_i < numobjs; dest_i++) {
472 // Initialize type specific fields
473 src_cap.u.devframe.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
474 src_cap.u.devframe.bits = objbits;
475 // Insert the capabilities
476 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
477 if (err_is_fail(err)) {
484 assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
485 TRACE(KERNEL, BZERO, 1);
486 memset((void*)lvaddr, 0, 1UL << bits);
487 TRACE(KERNEL, BZERO, 0);
489 for(dest_i = 0; dest_i < numobjs; dest_i++) {
490 // Initialize type specific fields
491 src_cap.u.cnode.cnode =
492 lpaddr + dest_i * ((lpaddr_t)1 << (objbits + OBJBITS_CTE));
493 src_cap.u.cnode.bits = objbits;
494 src_cap.u.cnode.guard = 0;
495 src_cap.u.cnode.guard_size = 0;
496 // XXX: Handle rights!
497 src_cap.u.cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
498 // Insert the capability
499 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
500 if (err_is_fail(err)) {
506 case ObjType_VNode_ARM_l1:
508 size_t objbits_vnode = vnode_objbits(type);
510 TRACE(KERNEL, BZERO, 1);
511 memset((void*)lvaddr, 0, 1UL << bits);
512 TRACE(KERNEL, BZERO, 0);
514 for(dest_i = 0; dest_i < numobjs; dest_i++) {
515 // Initialize type specific fields
516 src_cap.u.vnode_arm_l1.base =
517 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
520 // Insert kernel/mem mappings into new table.
522 gen_phys_to_local_phys(
523 local_phys_to_mem(src_cap.u.vnode_arm_l1.base)
529 // Insert the capability
530 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
531 if (err_is_fail(err)) {
539 case ObjType_VNode_ARM_l2:
541 size_t objbits_vnode = vnode_objbits(type);
543 TRACE(KERNEL, BZERO, 1);
544 memset((void*)lvaddr, 0, 1UL << bits);
545 TRACE(KERNEL, BZERO, 0);
547 for(dest_i = 0; dest_i < numobjs; dest_i++) {
548 // Initialize type specific fields
549 src_cap.u.vnode_arm_l2.base =
550 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
552 // Insert the capability
553 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
554 if (err_is_fail(err)) {
561 case ObjType_VNode_x86_32_ptable:
563 size_t objbits_vnode = vnode_objbits(type);
565 TRACE(KERNEL, BZERO, 1);
566 memset((void*)lvaddr, 0, 1UL << bits);
567 TRACE(KERNEL, BZERO, 0);
569 for(dest_i = 0; dest_i < numobjs; dest_i++) {
570 // Initialize type specific fields
571 src_cap.u.vnode_x86_32_ptable.base =
572 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
574 // Insert the capability
575 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
576 if (err_is_fail(err)) {
583 case ObjType_VNode_x86_32_pdir:
585 size_t objbits_vnode = vnode_objbits(type);
587 TRACE(KERNEL, BZERO, 1);
588 memset((void*)lvaddr, 0, 1UL << bits);
589 TRACE(KERNEL, BZERO, 0);
591 for(dest_i = 0; dest_i < numobjs; dest_i++) {
592 // Initialize type specific fields
593 src_cap.u.vnode_x86_32_pdir.base =
594 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
596 #if defined(__i386__) && !defined(CONFIG_PAE)
597 // Make it a good PDE by inserting kernel/mem VSpaces
598 lpaddr = gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdir.base);
599 paging_x86_32_make_good_pdir(lpaddr);
602 // Insert the capability
603 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
604 if (err_is_fail(err)) {
611 case ObjType_VNode_x86_32_pdpt:
613 size_t objbits_vnode = vnode_objbits(type);
615 TRACE(KERNEL, BZERO, 1);
616 memset((void*)lvaddr, 0, 1UL << bits);
617 TRACE(KERNEL, BZERO, 0);
619 for(dest_i = 0; dest_i < numobjs; dest_i++) {
620 // Initialize type specific fields
621 src_cap.u.vnode_x86_32_pdir.base =
622 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
624 #if defined(__i386__) && defined(CONFIG_PAE)
625 // Make it a good PDPTE by inserting kernel/mem VSpaces
627 gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdpt.base);
628 paging_x86_32_make_good_pdpte(var);
631 // Insert the capability
632 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
633 if (err_is_fail(err)) {
640 case ObjType_VNode_x86_64_ptable:
642 size_t objbits_vnode = vnode_objbits(type);
644 TRACE(KERNEL, BZERO, 1);
645 memset((void*)lvaddr, 0, 1UL << bits);
646 TRACE(KERNEL, BZERO, 0);
648 for(dest_i = 0; dest_i < numobjs; dest_i++) {
649 // Initialize type specific fields
650 src_cap.u.vnode_x86_64_ptable.base =
651 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
653 // Insert the capability
654 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
655 if (err_is_fail(err)) {
662 case ObjType_VNode_x86_64_pdir:
664 size_t objbits_vnode = vnode_objbits(type);
666 TRACE(KERNEL, BZERO, 1);
667 memset((void*)lvaddr, 0, 1UL << bits);
668 TRACE(KERNEL, BZERO, 0);
670 for(dest_i = 0; dest_i < numobjs; dest_i++) {
671 // Initialize type specific fields
672 src_cap.u.vnode_x86_64_pdir.base =
673 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
675 // Insert the capability
676 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
677 if (err_is_fail(err)) {
684 case ObjType_VNode_x86_64_pdpt:
686 size_t objbits_vnode = vnode_objbits(type);
688 TRACE(KERNEL, BZERO, 1);
689 memset((void*)lvaddr, 0, 1UL << bits);
690 TRACE(KERNEL, BZERO, 0);
692 for(dest_i = 0; dest_i < numobjs; dest_i++) {
693 // Initialize type specific fields
694 src_cap.u.vnode_x86_64_pdpt.base =
695 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
697 // Insert the capability
698 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
699 if (err_is_fail(err)) {
706 case ObjType_VNode_x86_64_pml4:
708 size_t objbits_vnode = vnode_objbits(type);
710 TRACE(KERNEL, BZERO, 1);
711 memset((void*)lvaddr, 0, 1UL << bits);
712 TRACE(KERNEL, BZERO, 0);
714 for(dest_i = 0; dest_i < numobjs; dest_i++) {
715 // Initialize type specific fields
716 src_cap.u.vnode_x86_64_pml4.base =
717 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
720 lpaddr_t var = gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
721 paging_k1om_make_good_pml4(var);
724 // Make it a good PML4 by inserting kernel/mem VSpaces
726 gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
727 paging_x86_64_make_good_pml4(var);
731 // Insert the capability
732 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
733 if (err_is_fail(err)) {
741 case ObjType_Dispatcher:
742 assert((1UL << OBJBITS_DISPATCHER) >= sizeof(struct dcb));
743 TRACE(KERNEL, BZERO, 1);
744 memset((void*)lvaddr, 0, 1UL << bits);
745 TRACE(KERNEL, BZERO, 0);
747 for(dest_i = 0; dest_i < numobjs; dest_i++) {
748 // Initialize type specific fields
749 src_cap.u.dispatcher.dcb = (struct dcb *)
750 (lvaddr + dest_i * (1UL << OBJBITS_DISPATCHER));
751 // Insert the capability
752 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
753 if (err_is_fail(err)) {
760 // ID type does not refer to a kernel object
763 assert(objbits == 0);
764 assert(numobjs == 1);
766 // Prevent wrap around
767 if (id_cap_counter >= UINT32_MAX) {
768 return SYS_ERR_ID_SPACE_EXHAUSTED;
771 // Generate a new ID, core_local_id monotonically increases
772 src_cap.u.id.coreid = my_core_id;
773 src_cap.u.id.core_local_id = id_cap_counter++;
775 // Insert the capability
776 err = set_cap(&dest_caps->cap, &src_cap);
780 src_cap.u.io.start = 0;
781 src_cap.u.io.end = 65535;
786 case ObjType_IRQTable:
787 case ObjType_EndPoint:
788 case ObjType_Notify_RCK:
789 case ObjType_Notify_IPI:
790 case ObjType_PerfMon:
791 // These types do not refer to a kernel object
794 assert(objbits == 0);
795 assert(numobjs == 1);
797 // Insert the capability
798 err = set_cap(&dest_caps->cap, &src_cap);
799 if (err_is_ok(err)) {
804 case ObjType_KernelControlBlock:
805 assert((1UL << OBJBITS_KCB) >= sizeof(struct dcb));
807 for(size_t i = 0; i < numobjs; i++) {
808 // Initialize type specific fields
809 src_cap.u.kernelcontrolblock.kcb = (struct kcb *)
810 (lvaddr + i * (1UL << OBJBITS_DISPATCHER));
811 // Insert the capability
812 err = set_cap(&dest_caps[i].cap, &src_cap);
813 if (err_is_fail(err)) {
820 panic("Unhandled capability type or capability of this type cannot"
824 if (err_is_fail(err)) {
825 // Revert the partially initialized caps to zero
826 for (size_t i = 0; i < dest_i; i++) {
827 memset(&dest_caps[i], 0, sizeof(dest_caps[i]));
832 // Set the owner for all the new caps
833 for (size_t i = 0; i < dest_i; i++) {
834 dest_caps[i].mdbnode.owner = owner;
842 * Look up a capability.
844 * Starting from #cnode_cap, recursively lookup the capability at #cptr
849 errval_t caps_lookup_slot(struct capability *cnode_cap, capaddr_t cptr,
850 uint8_t vbits, struct cte **ret, CapRights rights)
852 TRACE(KERNEL, CAP_LOOKUP_SLOT, 0);
853 /* parameter checking */
854 assert(cnode_cap != NULL);
856 /* Can only resolve CNode type */
857 if (cnode_cap->type != ObjType_CNode) {
858 debug(SUBSYS_CAPS, "caps_lookup_slot: Cap to lookup not of type CNode\n"
859 "cnode_cap->type = %u\n", cnode_cap->type);
860 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
861 return SYS_ERR_CNODE_TYPE;
864 /* Apply rights to this CNode */
865 if ((cnode_cap->rights & rights) != rights) {
866 debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
867 "Passed rights = %u, cnode_cap->rights = %u\n",
868 rights, cnode_cap->rights);
869 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
870 return SYS_ERR_CNODE_RIGHTS;
873 /* Number of bits resolved by this cnode (guard and bits) */
874 uint8_t bits_resolved = cnode_cap->u.cnode.bits +
875 cnode_cap->u.cnode.guard_size;
876 // All CNodes must resolve at least one bit
877 assert(bits_resolved > 0);
878 // If lookup exceeded expected depth then table is malformed
879 if (bits_resolved > vbits) {
880 debug(SUBSYS_CAPS, "caps_lookup_slot: Lookup exceeded valid bits\n"
881 "Cnode bits = %u, guard size = %u, valid bits = %u, bits_resolved = %u\n",
882 cnode_cap->u.cnode.bits, cnode_cap->u.cnode.guard_size,
883 vbits, bits_resolved);
884 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
885 return SYS_ERR_DEPTH_EXCEEDED;
888 /* Guard-check (bit-mask of guard in cptr must match guard in cnode cap) */
889 capaddr_t cptr_guard = (cptr >> (vbits - cnode_cap->u.cnode.guard_size))
890 & MASK(cnode_cap->u.cnode.guard_size);
891 if (cptr_guard != cnode_cap->u.cnode.guard) {
892 debug(SUBSYS_CAPS, "caps_lookup_slot: guard check failed\n"
893 "Computed guard = %"PRIuCADDR", "
894 "Cnode guard = %"PRIxCADDR", bits = %u\n",
895 cptr_guard, cnode_cap->u.cnode.guard,
896 cnode_cap->u.cnode.guard_size);
897 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
898 return SYS_ERR_GUARD_MISMATCH;
901 /* Locate capability in this cnode */
902 // Offset into the cnode
903 size_t offset = (cptr >> (vbits - bits_resolved)) &
904 MASK(cnode_cap->u.cnode.bits);
905 // The capability at the offset
906 struct cte *next_slot = caps_locate_slot(cnode_cap->u.cnode.cnode, offset);
907 // Do not return NULL type capability
908 if (next_slot->cap.type == ObjType_Null) {
909 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
910 return SYS_ERR_CAP_NOT_FOUND;
913 /* Number of bits left to resolve */
914 int bitsleft = vbits - bits_resolved;
915 // If all bits have been resolved, return the capability
918 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
922 /* If next capability is not of type cnode, return it */
923 // XXX: Is this consistent?
924 if (next_slot->cap.type != ObjType_CNode) {
926 TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
930 /* Descend to next level */
931 return caps_lookup_slot(&next_slot->cap, cptr, bitsleft, ret, rights);
935 * Wrapper for caps_lookup_slot returning capability instead of cte.
937 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
938 uint8_t vbits, struct capability **ret, CapRights rights)
940 TRACE(KERNEL, CAP_LOOKUP_CAP, 0);
942 errval_t err = caps_lookup_slot(cnode_cap, cptr, vbits, &ret_cte, rights);
943 if (err_is_fail(err)) {
946 *ret = &ret_cte->cap;
947 TRACE(KERNEL, CAP_LOOKUP_CAP, 1);
952 * \brief Create a capability from an existing capability metadata.
954 * Used when sending capabilities across cores. The metadata is sent across
955 * cores and the receiving monitor can create the new capability on its core.
957 * \bug Does not check that supplied owner matches existing copies of cap.
959 errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
960 int cnode_vbits, cslot_t dest_slot, coreid_t owner,
961 struct capability *src)
963 TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 0);
965 struct capability *cnode;
966 err = caps_lookup_cap(root, cnode_cptr, cnode_vbits, &cnode,
967 CAPRIGHTS_READ_WRITE);
968 if (err_is_fail(err)) {
969 return err_push(err, SYS_ERR_SLOT_LOOKUP_FAIL);
971 if (cnode->type != ObjType_CNode) {
972 return SYS_ERR_CNODE_TYPE;
975 struct cte *dest = caps_locate_slot(cnode->u.cnode.cnode, dest_slot);
977 err = set_cap(&dest->cap, src);
978 if (err_is_fail(err)) {
982 dest->mdbnode.owner = owner;
984 err = mdb_insert(dest);
985 assert(err_is_ok(err));
987 struct cte *neighbour = NULL;
989 && (neighbour = mdb_predecessor(dest))
990 && !is_copy(&dest->cap, &neighbour->cap))
995 && (neighbour = mdb_successor(dest))
996 && !is_copy(&dest->cap, &neighbour->cap))
1002 assert(!neighbour->mdbnode.in_delete);
1003 assert(neighbour->mdbnode.owner == owner);
1004 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
1006 CP_ATTR(remote_copies);
1007 CP_ATTR(remote_ancs);
1008 CP_ATTR(remote_descs);
1012 dest->mdbnode.locked = false;
1013 if (owner != my_core_id) {
1014 // For foreign caps it does not really matter if ancestors or
1015 // descendants exist
1016 dest->mdbnode.remote_copies = true;
1017 dest->mdbnode.remote_ancs = false;
1018 dest->mdbnode.remote_descs = false;
1021 // We just created a new copy of a owned capability from nothing.
1022 // This is either caused by a retype, or by sharing a capability
1023 // that does not care about locality.
1024 // XXX: This should probably be done more explicitly -MN
1025 if (distcap_needs_locality(dest->cap.type)) {
1026 // Retype, so have ancestors and no descendants
1027 dest->mdbnode.remote_copies = false;
1028 dest->mdbnode.remote_ancs = true;
1029 dest->mdbnode.remote_descs = false;
1032 dest->mdbnode.remote_copies = false;
1033 dest->mdbnode.remote_ancs = false;
1034 dest->mdbnode.remote_descs = false;
1039 TRACE_CAP_MSG("created", dest);
1041 TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 1);
1045 /// Create caps to new kernel objects.
1046 errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bits,
1047 size_t objbits, coreid_t owner, struct cte *caps)
1049 TRACE(KERNEL, CAP_CREATE_NEW, 0);
1050 /* Parameter checking */
1051 assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1053 size_t numobjs = caps_numobjs(type, bits, objbits);
1054 assert(numobjs > 0);
1056 /* Create the new capabilities */
1057 errval_t err = caps_create(type, addr, bits, objbits, numobjs, owner, caps);
1058 if (err_is_fail(err)) {
1062 // Handle the mapping database
1063 set_init_mapping(caps, numobjs);
1065 TRACE_CAP_MSG("created", &caps[0]);
1067 TRACE(KERNEL, CAP_CREATE_NEW, 1);
1073 errval_t caps_retype(enum objtype type, size_t objbits,
1074 struct capability *dest_cnode, cslot_t dest_slot,
1075 struct cte *src_cte, bool from_monitor)
1077 TRACE(KERNEL, CAP_RETYPE, 0);
1080 genpaddr_t base = 0;
1083 /* Parameter checking */
1084 assert(type != ObjType_Null);
1085 assert(type < ObjType_Num);
1087 struct capability *src_cap = &src_cte->cap;
1089 TRACE_CAP_MSG("retyping", src_cte);
1091 /* Check retypability */
1092 err = is_retypeable(src_cte, src_cap->type, type, from_monitor);
1093 if (err_is_fail(err)) {
1094 debug(SUBSYS_CAPS, "caps_retype: is_retypeable failed\n");
1098 /* Create Destination caps as per source and destination type */
1099 switch(src_cap->type) {
1100 case ObjType_PhysAddr:
1101 bits = src_cap->u.physaddr.bits;
1102 base = src_cap->u.physaddr.base;
1106 bits = src_cap->u.ram.bits;
1107 base = src_cap->u.ram.base;
1110 case ObjType_Dispatcher:
1115 bits = src_cap->u.frame.bits;
1116 base = src_cap->u.frame.base;
1119 case ObjType_DevFrame:
1120 bits = src_cap->u.devframe.bits;
1121 base = src_cap->u.devframe.base;
1125 panic("Unreachable case");
1128 /* determine number of objects to be created */
1129 numobjs = caps_numobjs(type, bits, objbits);
1132 debug(SUBSYS_CAPS, "caps_retype: numobjs == 0\n");
1133 return SYS_ERR_INVALID_SIZE_BITS;
1135 // debug(SUBSYS_CAPS, "caps_retype: numobjs == %d\n", (int)numobjs);
1137 /* check that destination slots all fit within target cnode */
1138 if (dest_slot + numobjs > (1UL << dest_cnode->u.cnode.bits)) {
1139 debug(SUBSYS_CAPS, "caps_retype: dest slots don't fit in cnode\n");
1140 return SYS_ERR_SLOTS_INVALID;
1143 /* check that destination slots are all empty */
1144 debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1146 dest_cnode->u.cnode.cnode, (int)dest_slot);
1147 for (cslot_t i = 0; i < numobjs; i++) {
1148 if (caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot + i)->cap.type
1150 debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1151 (int)(dest_slot + i));
1152 return SYS_ERR_SLOTS_IN_USE;
1156 /* create new caps */
1157 struct cte *dest_cte =
1158 caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot);
1159 err = caps_create(type, base, bits, objbits, numobjs, my_core_id, dest_cte);
1160 if (err_is_fail(err)) {
1161 debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
1162 return err_push(err, SYS_ERR_RETYPE_CREATE);
1165 /* special initialisation for endpoint caps */
1166 if (type == ObjType_EndPoint) {
1167 assert(src_cap->type == ObjType_Dispatcher);
1168 assert(numobjs == 1);
1169 struct capability *dest_cap = &dest_cte->cap;
1170 dest_cap->u.endpoint.listener = src_cap->u.dispatcher.dcb;
1173 /* Handle mapping */
1174 for (size_t i = 0; i < numobjs; i++) {
1175 mdb_insert(&dest_cte[i]);
1178 #ifdef TRACE_PMEM_CAPS
1179 for (size_t i = 0; i < numobjs; i++) {
1180 TRACE_CAP_MSG("created", &dest_cte[i]);
1184 TRACE(KERNEL, CAP_RETYPE, 1);
1188 /// Check the validity of a retype operation
1189 errval_t is_retypeable(struct cte *src_cte, enum objtype src_type,
1190 enum objtype dest_type, bool from_monitor)
1192 if (!is_well_founded(src_type, dest_type)) {
1193 return SYS_ERR_INVALID_RETYPE;
1194 } else if (!is_revoked_first(src_cte, src_type)){
1195 printf("err_revoke_first: (%p, %d, %d)\n", src_cte, src_type, dest_type);
1196 return SYS_ERR_REVOKE_FIRST;
1197 } else if (dest_type == ObjType_EndPoint && src_cte->mdbnode.owner == my_core_id) {
1198 // XXX: because of the current "multi-retype" hack for endpoints, a
1199 // dispatcher->endpoint retype can happen irrespective of the existence
1200 // of descendents on any core.
1201 // Howevery, we only do this for locally owned caps as the owner should
1202 // be notified that the cap has remote descendants
1204 } else if (!from_monitor && (src_cte->mdbnode.owner != my_core_id
1205 || src_cte->mdbnode.remote_descs)) {
1206 return SYS_ERR_RETRY_THROUGH_MONITOR;
1212 /// Create copies to a slot within a cnode
1213 errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
1214 struct cte *src_cte, bool mint, uintptr_t param1,
1217 /* Parameter Checking */
1218 assert(dest_cnode_cte->cap.type == ObjType_CNode);
1220 struct cte *dest_cte;
1221 dest_cte = caps_locate_slot(dest_cnode_cte->cap.u.cnode.cnode, dest_slot);
1222 return caps_copy_to_cte(dest_cte, src_cte, mint, param1, param2);
1226 /// Create copies to a cte
1227 errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
1228 uintptr_t param1, uintptr_t param2)
1231 /* Parameter checking */
1233 assert(dest_cte != NULL);
1234 assert(src_cte != NULL);
1236 struct capability *src_cap = &src_cte->cap;
1237 struct capability *dest_cap = &dest_cte->cap;
1238 // NULL caps cannot be copied/minted
1239 if (src_cap->type == ObjType_Null) {
1240 return SYS_ERR_CAP_NOT_FOUND;
1242 // Parameters should be 0 if not minting
1244 assert(param1 == 0);
1245 assert(param2 == 0);
1248 assert(!src_cte->mdbnode.in_delete);
1250 /* Insert #source_cap into #dest_cap */
1251 err = set_cap(dest_cap, src_cap);
1252 if (err_is_fail(err)) {
1256 /* Transfer MDB attributes that must be equal for all copies */
1257 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1260 CP_ATTR(remote_copies);
1261 CP_ATTR(remote_ancs);
1262 CP_ATTR(remote_descs);
1267 TRACE_CAP_MSG("copied to", dest_cte);
1268 // Handle mapping here only for non-mint operations
1269 // (mint can change eq fields which would make the early insertion
1270 // invalid in some cases)
1271 mdb_insert(dest_cte);
1275 TRACE_CAP_MSG("minting to", dest_cte);
1278 /* For minting, set the specified parameters */
1279 // Process source-specific parameters for minting
1280 // XXX: If failure, revert the insertion
1281 switch(src_cap->type) {
1283 if (param2 > CPTR_BITS) {
1284 return SYS_ERR_GUARD_SIZE_OVERFLOW;
1286 dest_cap->u.cnode.guard = param1;
1287 dest_cap->u.cnode.guard_size = param2;
1290 case ObjType_EndPoint:
1291 // XXX: FIXME: check that buffer offset lies wholly within the disp frame
1292 // can't easily enforce this here, because the dispatcher frame may not
1294 /* if (param1 < sizeof(struct dispatcher) ||
1295 dest_cap->u.endpoint.listener->disp == NULL ||
1296 param2 < IDC_RECV_LENGTH ||
1297 param1 + sizeof(struct idc_endpoint) + param2 * sizeof(uintptr_t) >
1298 (1UL << dest_cap->u.endpoint.listener->disp_cte.cap.u.frame.bits)) {
1299 return SYS_ERR_INVALID_EPBUF;
1301 if (param2 < LMP_RECV_HEADER_LENGTH) {
1302 return SYS_ERR_INVALID_EPLEN;
1304 dest_cap->u.endpoint.epoffset = param1;
1305 dest_cap->u.endpoint.epbuflen = param2;
1309 if(src_cap->u.io.start <= param1) {
1310 dest_cap->u.io.start = param1;
1312 if(src_cap->u.io.end >= param2) {
1313 dest_cap->u.io.end = param2;
1318 // Unhandled source type for mint
1319 return SYS_ERR_INVALID_SOURCE_TYPE;
1322 // Insert after doing minting operation
1323 mdb_insert(dest_cte);