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>
26 #include <paging_kernel_arch.h>
28 #include <mdb/mdb_tree.h>
29 #include <trace/trace.h>
30 #include <trace_definitions/trace_defs.h>
33 /// Sets the specified number of low-order bits to 1
34 #define MASK(bits) ((1UL << bits) - 1)
36 #ifdef TRACE_PMEM_CAPS
37 uint64_t trace_types_enabled = TRACE_TYPES_ENABLED_INITIAL;
38 genpaddr_t TRACE_PMEM_BEGIN = TRACE_PMEM_BEGIN_INITIAL;
39 gensize_t TRACE_PMEM_SIZE = TRACE_PMEM_SIZE_INITIAL;
41 void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
44 trace_types_enabled = types;
45 TRACE_PMEM_BEGIN = start;
46 TRACE_PMEM_SIZE = size;
48 trace_types_enabled = false;
53 struct capability monitor_ep;
55 int sprint_cap(char *buf, size_t len, struct capability *cap)
58 case ObjType_PhysAddr:
59 return snprintf(buf, len,
60 "physical address range cap (0x%" PRIxGENPADDR ":%u)",
61 cap->u.physaddr.base, cap->u.physaddr.bits);
64 return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":%u)",
65 cap->u.ram.base, cap->u.ram.bits);
68 int ret = snprintf(buf, len, "CNode cap "
69 "(bits %u, rights mask 0x%" PRIxCAPRIGHTS ")",
70 cap->u.cnode.bits, cap->u.cnode.rightsmask);
71 if (cap->u.cnode.guard_size != 0 && ret < len) {
72 ret += snprintf(&buf[ret], len - ret, " (guard 0x%" PRIxCADDR ":%u)",
73 cap->u.cnode.guard, cap->u.cnode.guard_size);
78 case ObjType_Dispatcher:
79 return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
82 return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":%u)",
83 cap->u.frame.base, cap->u.frame.bits);
85 case ObjType_DevFrame:
86 return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":%u)",
87 cap->u.frame.base, cap->u.devframe.bits);
89 case ObjType_VNode_ARM_l1:
90 return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
91 cap->u.vnode_arm_l1.base);
93 case ObjType_VNode_ARM_l2:
94 return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
95 cap->u.vnode_arm_l2.base);
97 case ObjType_VNode_x86_32_ptable:
98 return snprintf(buf, len, "x86_32 Page table at 0x%" PRIxGENPADDR,
99 cap->u.vnode_x86_32_ptable.base);
101 case ObjType_VNode_x86_32_pdir:
102 return snprintf(buf, len, "x86_32 Page directory at 0x%" PRIxGENPADDR,
103 cap->u.vnode_x86_32_pdir.base);
105 case ObjType_VNode_x86_32_pdpt:
106 return snprintf(buf, len, "x86_32 PDPT at 0x%" PRIxGENPADDR,
107 cap->u.vnode_x86_32_pdpt.base);
109 case ObjType_VNode_x86_64_ptable:
110 return snprintf(buf, len, "x86_64 Page table at 0x%" PRIxGENPADDR,
111 cap->u.vnode_x86_64_ptable.base);
113 case ObjType_VNode_x86_64_pdir:
114 return snprintf(buf, len, "x86_64 Page directory at 0x%" PRIxGENPADDR,
115 cap->u.vnode_x86_64_pdir.base);
117 case ObjType_VNode_x86_64_pdpt:
118 return snprintf(buf, len, "x86_64 PDPT at 0x%" PRIxGENPADDR,
119 cap->u.vnode_x86_64_pdpt.base);
121 case ObjType_VNode_x86_64_pml4:
122 return snprintf(buf, len, "x86_64 PML4 at 0x%" PRIxGENPADDR,
123 cap->u.vnode_x86_64_pml4.base);
125 case ObjType_IRQTable:
126 return snprintf(buf, len, "IRQTable cap");
128 case ObjType_EndPoint:
129 return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
130 cap->u.endpoint.listener, cap->u.endpoint.epoffset);
133 return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
134 cap->u.io.start, cap->u.io.end);
137 return snprintf(buf, len, "Kernel cap");
140 return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
141 " core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
142 cap->u.id.core_local_id);
144 case ObjType_PerfMon:
145 return snprintf(buf, len, "PerfMon cap");
148 return snprintf(buf, len, "Null capability (empty slot)");
151 return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
155 void caps_trace(const char *func, int line, struct cte *cte, const char *msg)
158 sprint_cap(cap_buf, 512, &cte->cap);
162 dispatcher_handle_t handle = dcb_current->disp;
163 struct dispatcher_shared_generic *disp =
164 get_dispatcher_shared_generic(handle);
165 snprintf(disp_buf, 64, "from %.*s", DISP_NAME_LEN, disp->name);
168 strcpy(disp_buf, "no disp");
171 printk(LOG_WARN, "%s: %s:%d: %s %p %s"
172 " (owner:%" PRIuCOREID ", rc:%d/ra:%d/rd:%d)\n",
173 disp_buf, func, line, (msg ? : ""), cte, cap_buf, cte->mdbnode.owner,
174 cte->mdbnode.remote_copies, cte->mdbnode.remote_ancs,
175 cte->mdbnode.remote_descs);
179 * ID capability core_local_id counter.
181 static uint32_t id_cap_counter = 1;
184 * Sets #dest equal to #src
186 * #dest cannot be in use.
188 static errval_t set_cap(struct capability *dest, struct capability *src)
190 /* Parameter checking */
192 assert(dest != NULL);
194 // Reserved object bits must always be greater/equal to actual object size
195 assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
197 // Cannot overwrite an already existing cap
198 if (dest->type != ObjType_Null) {
199 return SYS_ERR_SLOT_IN_USE;
202 memcpy(dest, src, sizeof(struct capability));
207 * \brief Determine how many objects can be created in a specified region.
209 * This function computes the number of objects that can be created by a call
212 * \param type Type of objects to create.
213 * \param bits Size of memory area as 2^bits.
214 * \param objbits For variable-sized objects, size multiplier as 2^bits.
216 * \return Number of objects to be created, or zero on error
219 // If you create more capability types you need to deal with them
220 // in the table below.
221 STATIC_ASSERT(ObjType_Num == 25, "Knowledge of all cap types");
223 static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
226 case ObjType_PhysAddr:
229 case ObjType_DevFrame:
230 if (objbits > bits) {
233 return 1UL << (bits - objbits);
237 if (bits < OBJBITS_CTE || objbits > bits - OBJBITS_CTE) {
240 return 1UL << (bits - OBJBITS_CTE - objbits);
243 case ObjType_VNode_x86_64_pml4:
244 case ObjType_VNode_x86_64_pdpt:
245 case ObjType_VNode_x86_64_pdir:
246 case ObjType_VNode_x86_64_ptable:
247 case ObjType_VNode_x86_32_pdpt:
248 case ObjType_VNode_x86_32_pdir:
249 case ObjType_VNode_x86_32_ptable:
250 case ObjType_VNode_ARM_l1:
251 case ObjType_VNode_ARM_l2:
253 size_t objbits_vnode = vnode_objbits(type);
254 if (bits < objbits_vnode) {
257 return 1UL << (bits - objbits_vnode);
261 case ObjType_Dispatcher:
262 if (bits < OBJBITS_DISPATCHER) {
265 return 1UL << (bits - OBJBITS_DISPATCHER);
269 case ObjType_IRQTable:
271 case ObjType_EndPoint:
273 case ObjType_Notify_RCK:
274 case ObjType_Notify_IPI:
275 case ObjType_PerfMon:
279 panic("invalid type");
285 * \brief Initialize the objects for which local caps are about to be created.
287 * For the meaning of the parameters, see the 'caps_create' function.
289 STATIC_ASSERT(ObjType_Num == 25, "Knowledge of all cap types");
291 static errval_t caps_init_objects(enum objtype type, lpaddr_t lpaddr, uint8_t
292 bits, uint8_t objbits, size_t numobjs)
294 // Virtual address of the memory the kernel object resides in
295 // XXX: A better of doing this,
296 // this is creating caps that the kernel cannot address.
297 // It assumes that the cap is not of the type which will have to zeroed out.
299 if(lpaddr < PADDR_SPACE_LIMIT) {
300 lvaddr = local_phys_to_mem(lpaddr);
308 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
309 // XXX: SCC hack, while we don't have a devframe allocator
310 if(lpaddr + ((lpaddr_t)1 << bits) < PADDR_SPACE_LIMIT) {
311 memset((void*)lvaddr, 0, (lvaddr_t)1 << bits);
313 printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
314 " uninitialized\n", lpaddr);
316 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
320 case ObjType_VNode_ARM_l1:
321 case ObjType_VNode_ARM_l2:
322 case ObjType_VNode_x86_32_ptable:
323 case ObjType_VNode_x86_32_pdir:
324 case ObjType_VNode_x86_32_pdpt:
325 case ObjType_VNode_x86_64_ptable:
326 case ObjType_VNode_x86_64_pdir:
327 case ObjType_VNode_x86_64_pdpt:
328 case ObjType_VNode_x86_64_pml4:
329 case ObjType_Dispatcher:
330 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
331 memset((void*)lvaddr, 0, 1UL << bits);
332 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
344 * \brief Create capabilities to kernel objects.
346 * This function creates kernel objects of 'type' into the memory
347 * area, based at 'addr' and of size 2^'bits', so they completely fill the
348 * area. For each created kernel object, a capability is created to it and
349 * put consecutively into the array of CTEs pointed to by 'caps'. The array
350 * needs to have the appropriate size to hold all created caps. Some kernel
351 * objects can have a variable size. In that case, 'objbits' should be non-zero
352 * and give the a size multiplier as 2^'objbits'.
354 * \param type Type of objects to create.
355 * \param addr Base address in the local address space.
356 * \param bits Size of memory area as 2^bits.
357 * \param objbits For variable-sized objects, size multiplier as 2^bits.
358 * \param numobjs Number of objects to be created, from caps_numobjs()
359 * \param dest_caps Pointer to array of CTEs to hold created caps.
363 // If you create more capability types you need to deal with them
364 // in the table below.
365 STATIC_ASSERT(ObjType_Num == 25, "Knowledge of all cap types");
367 static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, uint8_t bits,
368 uint8_t objbits, size_t numobjs, coreid_t owner,
369 struct cte *dest_caps)
373 /* Parameter checking */
374 assert(dest_caps != NULL);
375 assert(type != ObjType_Null);
376 assert(type < ObjType_Num);
379 genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
381 // Virtual address of the memory the kernel object resides in
382 // XXX: A better of doing this,
383 // this is creating caps that the kernel cannot address.
384 // It assumes that the cap is not of the type which will have to zeroed out.
386 if(lpaddr < PADDR_SPACE_LIMIT) {
387 lvaddr = local_phys_to_mem(lpaddr);
392 /* Initialize the created capability */
393 struct capability src_cap;
394 memset(&src_cap, 0, sizeof(struct capability));
396 // XXX: Handle rights!
397 src_cap.rights = CAPRIGHTS_ALLRIGHTS;
399 if (owner == my_core_id) {
400 // If we're creating new local objects, they need to be initialized
401 err = caps_init_objects(type, lpaddr, bits, objbits, numobjs);
402 if (err_is_fail(err)) {
410 /* Set the type specific fields and insert into #dest_caps */
413 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
414 // XXX: SCC hack, while we don't have a devframe allocator
415 if(lpaddr + ((lpaddr_t)1 << bits) < PADDR_SPACE_LIMIT) {
416 memset((void*)lvaddr, 0, (lvaddr_t)1 << bits);
418 printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
419 " uninitialized\n", lpaddr);
421 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
422 for(dest_i = 0; dest_i < numobjs; dest_i++) {
423 // Initialize type specific fields
424 src_cap.u.frame.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
425 src_cap.u.frame.bits = objbits;
426 // Insert the capabilities
427 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
428 if (err_is_fail(err)) {
434 case ObjType_PhysAddr:
435 for(dest_i = 0; dest_i < numobjs; dest_i++) {
436 // Initialize type specific fields
437 src_cap.u.physaddr.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
438 src_cap.u.physaddr.bits = objbits;
439 // Insert the capabilities
440 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
441 if (err_is_fail(err)) {
448 for(dest_i = 0; dest_i < numobjs; dest_i++) {
449 // Initialize type specific fields
450 src_cap.u.ram.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
451 src_cap.u.ram.bits = objbits;
452 // Insert the capabilities
453 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
454 if (err_is_fail(err)) {
460 case ObjType_DevFrame:
461 for(dest_i = 0; dest_i < numobjs; dest_i++) {
462 // Initialize type specific fields
463 src_cap.u.devframe.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
464 src_cap.u.devframe.bits = objbits;
465 // Insert the capabilities
466 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
467 if (err_is_fail(err)) {
474 assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
475 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
476 memset((void*)lvaddr, 0, 1UL << bits);
477 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
479 for(dest_i = 0; dest_i < numobjs; dest_i++) {
480 // Initialize type specific fields
481 src_cap.u.cnode.cnode =
482 lpaddr + dest_i * ((lpaddr_t)1 << (objbits + OBJBITS_CTE));
483 src_cap.u.cnode.bits = objbits;
484 src_cap.u.cnode.guard = 0;
485 src_cap.u.cnode.guard_size = 0;
486 // XXX: Handle rights!
487 src_cap.u.cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
488 // Insert the capability
489 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
490 if (err_is_fail(err)) {
496 case ObjType_VNode_ARM_l1:
498 size_t objbits_vnode = vnode_objbits(type);
500 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
501 memset((void*)lvaddr, 0, 1UL << bits);
502 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
504 for(dest_i = 0; dest_i < numobjs; dest_i++) {
505 // Initialize type specific fields
506 src_cap.u.vnode_arm_l1.base =
507 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
510 // Insert kernel/mem mappings into new table.
512 gen_phys_to_local_phys(
513 local_phys_to_mem(src_cap.u.vnode_arm_l1.base)
519 // Insert the capability
520 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
521 if (err_is_fail(err)) {
529 case ObjType_VNode_ARM_l2:
531 size_t objbits_vnode = vnode_objbits(type);
533 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
534 memset((void*)lvaddr, 0, 1UL << bits);
535 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
537 for(dest_i = 0; dest_i < numobjs; dest_i++) {
538 // Initialize type specific fields
539 src_cap.u.vnode_arm_l2.base =
540 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
542 // Insert the capability
543 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
544 if (err_is_fail(err)) {
551 case ObjType_VNode_x86_32_ptable:
553 size_t objbits_vnode = vnode_objbits(type);
555 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
556 memset((void*)lvaddr, 0, 1UL << bits);
557 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
559 for(dest_i = 0; dest_i < numobjs; dest_i++) {
560 // Initialize type specific fields
561 src_cap.u.vnode_x86_32_ptable.base =
562 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
564 // Insert the capability
565 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
566 if (err_is_fail(err)) {
573 case ObjType_VNode_x86_32_pdir:
575 size_t objbits_vnode = vnode_objbits(type);
577 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
578 memset((void*)lvaddr, 0, 1UL << bits);
579 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
581 for(dest_i = 0; dest_i < numobjs; dest_i++) {
582 // Initialize type specific fields
583 src_cap.u.vnode_x86_32_pdir.base =
584 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
586 #if defined(__i386__) && !defined(CONFIG_PAE)
587 // Make it a good PDE by inserting kernel/mem VSpaces
588 lpaddr = gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdir.base);
589 paging_x86_32_make_good_pdir(lpaddr);
592 // Insert the capability
593 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
594 if (err_is_fail(err)) {
601 case ObjType_VNode_x86_32_pdpt:
603 size_t objbits_vnode = vnode_objbits(type);
605 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
606 memset((void*)lvaddr, 0, 1UL << bits);
607 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
609 for(dest_i = 0; dest_i < numobjs; dest_i++) {
610 // Initialize type specific fields
611 src_cap.u.vnode_x86_32_pdir.base =
612 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
614 #if defined(__i386__) && defined(CONFIG_PAE)
615 // Make it a good PDPTE by inserting kernel/mem VSpaces
617 gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdpt.base);
618 paging_x86_32_make_good_pdpte(var);
621 // Insert the capability
622 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
623 if (err_is_fail(err)) {
630 case ObjType_VNode_x86_64_ptable:
632 size_t objbits_vnode = vnode_objbits(type);
634 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
635 memset((void*)lvaddr, 0, 1UL << bits);
636 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
638 for(dest_i = 0; dest_i < numobjs; dest_i++) {
639 // Initialize type specific fields
640 src_cap.u.vnode_x86_64_ptable.base =
641 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
643 // Insert the capability
644 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
645 if (err_is_fail(err)) {
652 case ObjType_VNode_x86_64_pdir:
654 size_t objbits_vnode = vnode_objbits(type);
656 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
657 memset((void*)lvaddr, 0, 1UL << bits);
658 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
660 for(dest_i = 0; dest_i < numobjs; dest_i++) {
661 // Initialize type specific fields
662 src_cap.u.vnode_x86_64_pdir.base =
663 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
665 // Insert the capability
666 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
667 if (err_is_fail(err)) {
674 case ObjType_VNode_x86_64_pdpt:
676 size_t objbits_vnode = vnode_objbits(type);
678 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
679 memset((void*)lvaddr, 0, 1UL << bits);
680 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
682 for(dest_i = 0; dest_i < numobjs; dest_i++) {
683 // Initialize type specific fields
684 src_cap.u.vnode_x86_64_pdpt.base =
685 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
687 // Insert the capability
688 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
689 if (err_is_fail(err)) {
696 case ObjType_VNode_x86_64_pml4:
698 size_t objbits_vnode = vnode_objbits(type);
700 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
701 memset((void*)lvaddr, 0, 1UL << bits);
702 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
704 for(dest_i = 0; dest_i < numobjs; dest_i++) {
705 // Initialize type specific fields
706 src_cap.u.vnode_x86_64_pml4.base =
707 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
710 lpaddr_t var = gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
711 paging_k1om_make_good_pml4(var);
714 // Make it a good PML4 by inserting kernel/mem VSpaces
716 gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
717 paging_x86_64_make_good_pml4(var);
721 // Insert the capability
722 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
723 if (err_is_fail(err)) {
731 case ObjType_Dispatcher:
732 assert((1UL << OBJBITS_DISPATCHER) >= sizeof(struct dcb));
733 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
734 memset((void*)lvaddr, 0, 1UL << bits);
735 trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
737 for(dest_i = 0; dest_i < numobjs; dest_i++) {
738 // Initialize type specific fields
739 src_cap.u.dispatcher.dcb = (struct dcb *)
740 (lvaddr + dest_i * (1UL << OBJBITS_DISPATCHER));
741 // Insert the capability
742 err = set_cap(&dest_caps[dest_i].cap, &src_cap);
743 if (err_is_fail(err)) {
750 // ID type does not refer to a kernel object
753 assert(objbits == 0);
754 assert(numobjs == 1);
756 // Prevent wrap around
757 if (id_cap_counter >= UINT32_MAX) {
758 return SYS_ERR_ID_SPACE_EXHAUSTED;
761 // Generate a new ID, core_local_id monotonically increases
762 src_cap.u.id.coreid = my_core_id;
763 src_cap.u.id.core_local_id = id_cap_counter++;
765 // Insert the capability
766 err = set_cap(&dest_caps->cap, &src_cap);
770 src_cap.u.io.start = 0;
771 src_cap.u.io.end = 65535;
775 case ObjType_IRQTable:
776 case ObjType_EndPoint:
777 case ObjType_Notify_RCK:
778 case ObjType_Notify_IPI:
779 case ObjType_PerfMon:
780 // These types do not refer to a kernel object
783 assert(objbits == 0);
784 assert(numobjs == 1);
786 // Insert the capability
787 err = set_cap(&dest_caps->cap, &src_cap);
788 if (err_is_ok(err)) {
794 panic("Unhandled capability type or capability of this type cannot"
798 if (err_is_fail(err)) {
799 // Revert the partially initialized caps to zero
800 for (size_t i = 0; i < dest_i; i++) {
801 memset(&dest_caps[i], 0, sizeof(dest_caps[i]));
806 // Set the owner for all the new caps
807 for (size_t i = 0; i < dest_i; i++) {
808 dest_caps[i].mdbnode.owner = owner;
816 * Look up a capability.
818 * Starting from #cnode_cap, recursively lookup the capability at #cptr
823 errval_t caps_lookup_slot(struct capability *cnode_cap, capaddr_t cptr,
824 uint8_t vbits, struct cte **ret, CapRights rights)
826 /* parameter checking */
827 assert(cnode_cap != NULL);
829 /* Can only resolve CNode type */
830 if (cnode_cap->type != ObjType_CNode) {
831 debug(SUBSYS_CAPS, "caps_lookup_slot: Cap to lookup not of type CNode\n"
832 "cnode_cap->type = %u\n", cnode_cap->type);
833 return SYS_ERR_CNODE_TYPE;
836 /* Apply rights to this CNode */
837 if ((cnode_cap->rights & rights) != rights) {
838 debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
839 "Passed rights = %u, cnode_cap->rights = %u\n",
840 rights, cnode_cap->rights);
841 return SYS_ERR_CNODE_RIGHTS;
844 /* Number of bits resolved by this cnode (guard and bits) */
845 uint8_t bits_resolved = cnode_cap->u.cnode.bits +
846 cnode_cap->u.cnode.guard_size;
847 // All CNodes must resolve at least one bit
848 assert(bits_resolved > 0);
849 // If lookup exceeded expected depth then table is malformed
850 if (bits_resolved > vbits) {
851 debug(SUBSYS_CAPS, "caps_lookup_slot: Lookup exceeded valid bits\n"
852 "Cnode bits = %u, guard size = %u, valid bits = %u, bits_resolved = %u\n",
853 cnode_cap->u.cnode.bits, cnode_cap->u.cnode.guard_size,
854 vbits, bits_resolved);
855 return SYS_ERR_DEPTH_EXCEEDED;
858 /* Guard-check (bit-mask of guard in cptr must match guard in cnode cap) */
859 capaddr_t cptr_guard = (cptr >> (vbits - cnode_cap->u.cnode.guard_size))
860 & MASK(cnode_cap->u.cnode.guard_size);
861 if (cptr_guard != cnode_cap->u.cnode.guard) {
862 debug(SUBSYS_CAPS, "caps_lookup_slot: guard check failed\n"
863 "Computed guard = %"PRIuCADDR", "
864 "Cnode guard = %"PRIxCADDR", bits = %u\n",
865 cptr_guard, cnode_cap->u.cnode.guard,
866 cnode_cap->u.cnode.guard_size);
867 return SYS_ERR_GUARD_MISMATCH;
870 /* Locate capability in this cnode */
871 // Offset into the cnode
872 size_t offset = (cptr >> (vbits - bits_resolved)) &
873 MASK(cnode_cap->u.cnode.bits);
874 // The capability at the offset
875 struct cte *next_slot = caps_locate_slot(cnode_cap->u.cnode.cnode, offset);
876 // Do not return NULL type capability
877 if (next_slot->cap.type == ObjType_Null) {
878 return SYS_ERR_CAP_NOT_FOUND;
881 /* Number of bits left to resolve */
882 int bitsleft = vbits - bits_resolved;
883 // If all bits have been resolved, return the capability
889 /* If next capability is not of type cnode, return it */
890 // XXX: Is this consistent?
891 if (next_slot->cap.type != ObjType_CNode) {
896 /* Descend to next level */
897 return caps_lookup_slot(&next_slot->cap, cptr, bitsleft, ret, rights);
901 * Wrapper for caps_lookup_slot returning capability instead of cte.
903 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
904 uint8_t vbits, struct capability **ret, CapRights rights)
907 errval_t err = caps_lookup_slot(cnode_cap, cptr, vbits, &ret_cte, rights);
908 if (err_is_fail(err)) {
911 *ret = &ret_cte->cap;
916 * \brief Create a capability from an existing capability metadata.
918 * Used when sending capabilities across cores. The metadata is sent across
919 * cores and the receiving monitor can create the new capability on its core.
921 * \bug Does not check that supplied owner matches existing copies of cap.
923 errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
924 int cnode_vbits, cslot_t dest_slot, coreid_t owner,
925 struct capability *src)
928 struct capability *cnode;
929 err = caps_lookup_cap(root, cnode_cptr, cnode_vbits, &cnode,
930 CAPRIGHTS_READ_WRITE);
931 if (err_is_fail(err)) {
932 return err_push(err, SYS_ERR_SLOT_LOOKUP_FAIL);
934 if (cnode->type != ObjType_CNode) {
935 return SYS_ERR_CNODE_TYPE;
938 struct cte *dest = caps_locate_slot(cnode->u.cnode.cnode, dest_slot);
940 err = set_cap(&dest->cap, src);
941 if (err_is_fail(err)) {
945 dest->mdbnode.owner = owner;
947 err = mdb_insert(dest);
948 assert(err_is_ok(err));
950 struct cte *neighbour = NULL;
952 && (neighbour = mdb_predecessor(dest))
953 && !is_copy(&dest->cap, &neighbour->cap))
958 && (neighbour = mdb_successor(dest))
959 && !is_copy(&dest->cap, &neighbour->cap))
965 assert(!neighbour->mdbnode.in_delete);
966 assert(neighbour->mdbnode.owner == owner);
967 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
969 CP_ATTR(remote_copies);
970 CP_ATTR(remote_ancs);
971 CP_ATTR(remote_descs);
975 dest->mdbnode.locked = false;
976 if (owner != my_core_id) {
977 // For foreign caps it does not really matter if ancestors or
979 dest->mdbnode.remote_copies = true;
980 dest->mdbnode.remote_ancs = false;
981 dest->mdbnode.remote_descs = false;
984 // We just created a new copy of a owned capability from nothing.
985 // This is either caused by a retype, or by sharing a capability
986 // that does not care about locality.
987 // XXX: This should probably be done more explicitly -MN
988 if (distcap_needs_locality(dest->cap.type)) {
989 // Retype, so have ancestors and no descendants
990 dest->mdbnode.remote_copies = false;
991 dest->mdbnode.remote_ancs = true;
992 dest->mdbnode.remote_descs = false;
995 dest->mdbnode.remote_copies = false;
996 dest->mdbnode.remote_ancs = false;
997 dest->mdbnode.remote_descs = false;
1002 TRACE_CAP_MSG("created", dest);
1007 /// Create caps to new kernel objects.
1008 errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bits,
1009 size_t objbits, coreid_t owner, struct cte *caps)
1011 /* Parameter checking */
1012 assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1014 size_t numobjs = caps_numobjs(type, bits, objbits);
1015 assert(numobjs > 0);
1017 /* Create the new capabilities */
1018 errval_t err = caps_create(type, addr, bits, objbits, numobjs, owner, caps);
1019 if (err_is_fail(err)) {
1023 // Handle the mapping database
1024 set_init_mapping(caps, numobjs);
1026 TRACE_CAP_MSG("created", &caps[0]);
1033 errval_t caps_retype(enum objtype type, size_t objbits,
1034 struct capability *dest_cnode, cslot_t dest_slot,
1035 struct cte *src_cte, bool from_monitor)
1039 genpaddr_t base = 0;
1042 /* Parameter checking */
1043 assert(type != ObjType_Null);
1044 assert(type < ObjType_Num);
1046 struct capability *src_cap = &src_cte->cap;
1048 TRACE_CAP_MSG("retyping", src_cte);
1050 /* Check retypability */
1051 err = is_retypeable(src_cte, src_cap->type, type, from_monitor);
1052 if (err_is_fail(err)) {
1053 debug(SUBSYS_CAPS, "caps_retype: is_retypeable failed\n");
1057 /* Create Destination caps as per source and destination type */
1058 switch(src_cap->type) {
1059 case ObjType_PhysAddr:
1060 bits = src_cap->u.physaddr.bits;
1061 base = src_cap->u.physaddr.base;
1065 bits = src_cap->u.ram.bits;
1066 base = src_cap->u.ram.base;
1069 case ObjType_Dispatcher:
1074 bits = src_cap->u.frame.bits;
1075 base = src_cap->u.frame.base;
1078 case ObjType_DevFrame:
1079 bits = src_cap->u.devframe.bits;
1080 base = src_cap->u.devframe.base;
1084 panic("Unreachable case");
1087 /* determine number of objects to be created */
1088 numobjs = caps_numobjs(type, bits, objbits);
1091 debug(SUBSYS_CAPS, "caps_retype: numobjs == 0\n");
1092 return SYS_ERR_INVALID_SIZE_BITS;
1094 // debug(SUBSYS_CAPS, "caps_retype: numobjs == %d\n", (int)numobjs);
1096 /* check that destination slots all fit within target cnode */
1097 if (dest_slot + numobjs > (1UL << dest_cnode->u.cnode.bits)) {
1098 debug(SUBSYS_CAPS, "caps_retype: dest slots don't fit in cnode\n");
1099 return SYS_ERR_SLOTS_INVALID;
1102 /* check that destination slots are all empty */
1103 debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1105 dest_cnode->u.cnode.cnode, (int)dest_slot);
1106 for (cslot_t i = 0; i < numobjs; i++) {
1107 if (caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot + i)->cap.type
1109 debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1110 (int)(dest_slot + i));
1111 return SYS_ERR_SLOTS_IN_USE;
1115 /* create new caps */
1116 struct cte *dest_cte =
1117 caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot);
1118 err = caps_create(type, base, bits, objbits, numobjs, my_core_id, dest_cte);
1119 if (err_is_fail(err)) {
1120 debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
1121 return err_push(err, SYS_ERR_RETYPE_CREATE);
1124 /* special initialisation for endpoint caps */
1125 if (type == ObjType_EndPoint) {
1126 assert(src_cap->type == ObjType_Dispatcher);
1127 assert(numobjs == 1);
1128 struct capability *dest_cap = &dest_cte->cap;
1129 dest_cap->u.endpoint.listener = src_cap->u.dispatcher.dcb;
1132 /* Handle mapping */
1133 for (size_t i = 0; i < numobjs; i++) {
1134 mdb_insert(&dest_cte[i]);
1137 #ifdef TRACE_PMEM_CAPS
1138 for (size_t i = 0; i < numobjs; i++) {
1139 TRACE_CAP_MSG("created", &dest_cte[i]);
1146 /// Check the validity of a retype operation
1147 errval_t is_retypeable(struct cte *src_cte, enum objtype src_type,
1148 enum objtype dest_type, bool from_monitor)
1150 if (!is_well_founded(src_type, dest_type)) {
1151 return SYS_ERR_INVALID_RETYPE;
1152 } else if (!is_revoked_first(src_cte, src_type)){
1153 printf("err_revoke_first: (%p, %d, %d)\n", src_cte, src_type, dest_type);
1154 return SYS_ERR_REVOKE_FIRST;
1155 } else if (dest_type == ObjType_EndPoint && src_cte->mdbnode.owner == my_core_id) {
1156 // XXX: because of the current "multi-retype" hack for endpoints, a
1157 // dispatcher->endpoint retype can happen irrespective of the existence
1158 // of descendents on any core.
1159 // Howevery, we only do this for locally owned caps as the owner should
1160 // be notified that the cap has remote descendants
1162 } else if (!from_monitor && (src_cte->mdbnode.owner != my_core_id
1163 || src_cte->mdbnode.remote_descs)) {
1164 return SYS_ERR_RETRY_THROUGH_MONITOR;
1170 /// Create copies to a slot within a cnode
1171 errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
1172 struct cte *src_cte, bool mint, uintptr_t param1,
1175 /* Parameter Checking */
1176 assert(dest_cnode_cte->cap.type == ObjType_CNode);
1178 struct cte *dest_cte;
1179 dest_cte = caps_locate_slot(dest_cnode_cte->cap.u.cnode.cnode, dest_slot);
1180 return caps_copy_to_cte(dest_cte, src_cte, mint, param1, param2);
1184 /// Create copies to a cte
1185 errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
1186 uintptr_t param1, uintptr_t param2)
1189 /* Parameter checking */
1191 assert(dest_cte != NULL);
1192 assert(src_cte != NULL);
1194 struct capability *src_cap = &src_cte->cap;
1195 struct capability *dest_cap = &dest_cte->cap;
1196 // NULL caps cannot be copied/minted
1197 if (src_cap->type == ObjType_Null) {
1198 return SYS_ERR_CAP_NOT_FOUND;
1200 // Parameters should be 0 if not minting
1202 assert(param1 == 0);
1203 assert(param2 == 0);
1206 assert(!src_cte->mdbnode.in_delete);
1208 /* Insert #source_cap into #dest_cap */
1209 err = set_cap(dest_cap, src_cap);
1210 if (err_is_fail(err)) {
1214 /* Transfer MDB attributes that must be equal for all copies */
1215 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1218 CP_ATTR(remote_copies);
1219 CP_ATTR(remote_ancs);
1220 CP_ATTR(remote_descs);
1225 TRACE_CAP_MSG("copied to", dest_cte);
1226 // Handle mapping here only for non-mint operations
1227 // (mint can change eq fields which would make the early insertion
1228 // invalid in some cases)
1229 mdb_insert(dest_cte);
1233 TRACE_CAP_MSG("minting to", dest_cte);
1236 /* For minting, set the specified parameters */
1237 // Process source-specific parameters for minting
1238 // XXX: If failure, revert the insertion
1239 switch(src_cap->type) {
1241 if (param2 > CPTR_BITS) {
1242 return SYS_ERR_GUARD_SIZE_OVERFLOW;
1244 dest_cap->u.cnode.guard = param1;
1245 dest_cap->u.cnode.guard_size = param2;
1248 case ObjType_EndPoint:
1249 // XXX: FIXME: check that buffer offset lies wholly within the disp frame
1250 // can't easily enforce this here, because the dispatcher frame may not
1252 /* if (param1 < sizeof(struct dispatcher) ||
1253 dest_cap->u.endpoint.listener->disp == NULL ||
1254 param2 < IDC_RECV_LENGTH ||
1255 param1 + sizeof(struct idc_endpoint) + param2 * sizeof(uintptr_t) >
1256 (1UL << dest_cap->u.endpoint.listener->disp_cte.cap.u.frame.bits)) {
1257 return SYS_ERR_INVALID_EPBUF;
1259 if (param2 < LMP_RECV_HEADER_LENGTH) {
1260 return SYS_ERR_INVALID_EPLEN;
1262 dest_cap->u.endpoint.epoffset = param1;
1263 dest_cap->u.endpoint.epbuflen = param2;
1267 if(src_cap->u.io.start <= param1) {
1268 dest_cap->u.io.start = param1;
1270 if(src_cap->u.io.end >= param2) {
1271 dest_cap->u.io.end = param2;
1276 // Unhandled source type for mint
1277 return SYS_ERR_INVALID_SOURCE_TYPE;
1280 // Insert after doing minting operation
1281 mdb_insert(dest_cte);