T119: implement syscall and monitor interface to debug_print_capabilities
[barrelfish] / kernel / capabilities.c
1 /**
2  * \file
3  * \brief Kernel capability management implementation.
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
8  * All rights reserved.
9  *
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.
13  */
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <kernel.h>
18 #include <barrelfish_kpi/syscalls.h>
19 #include <barrelfish_kpi/paging_arch.h>
20 #include <barrelfish_kpi/lmp.h>
21 #include <offsets.h>
22 #include <capabilities.h>
23 #include <cap_predicates.h>
24 #include <distcaps.h>
25 #include <dispatch.h>
26 #include <kcb.h>
27 #include <paging_kernel_arch.h>
28 #include <mdb/mdb.h>
29 #include <mdb/mdb_tree.h>
30 #include <trace/trace.h>
31 #include <trace_definitions/trace_defs.h>
32 #include <wakeup.h>
33
34 /// Sets the specified number of low-order bits to 1
35 #define MASK(bits)      ((1UL << bits) - 1)
36
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;
41
42 void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
43 {
44     if (types) {
45         trace_types_enabled = types;
46         TRACE_PMEM_BEGIN = start;
47         TRACE_PMEM_SIZE = size;
48     } else {
49         trace_types_enabled = false;
50     }
51 }
52 #endif
53
54 struct capability monitor_ep;
55
56 int sprint_cap(char *buf, size_t len, struct capability *cap)
57 {
58     switch (cap->type) {
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);
63
64     case ObjType_RAM:
65         return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":%u)",
66                         cap->u.ram.base, cap->u.ram.bits);
67
68     case ObjType_CNode: {
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);
75         }
76         return ret;
77     }
78
79     case ObjType_Dispatcher:
80         return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
81
82     case ObjType_Frame:
83         return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":%u)",
84                         cap->u.frame.base, cap->u.frame.bits);
85
86     case ObjType_DevFrame:
87         return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":%u)",
88                         cap->u.frame.base, cap->u.devframe.bits);
89
90     case ObjType_VNode_ARM_l1:
91         return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
92                         cap->u.vnode_arm_l1.base);
93
94     case ObjType_VNode_ARM_l2:
95         return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
96                         cap->u.vnode_arm_l2.base);
97
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);
101
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);
105
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);
109
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);
113
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);
117
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);
121
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);
125
126     case ObjType_IRQTable:
127         return snprintf(buf, len, "IRQTable cap");
128
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);
132
133     case ObjType_IO:
134         return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
135                         cap->u.io.start, cap->u.io.end);
136
137     case ObjType_Kernel:
138         return snprintf(buf, len, "Kernel cap");
139
140     case ObjType_ID:
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);
144
145     case ObjType_PerfMon:
146         return snprintf(buf, len, "PerfMon cap");
147
148     case ObjType_Null:
149         return snprintf(buf, len, "Null capability (empty slot)");
150
151     default:
152         return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
153     }
154 }
155
156 void caps_trace(const char *func, int line, struct cte *cte, const char *msg)
157 {
158     char cap_buf[512];
159     sprint_cap(cap_buf, 512, &cte->cap);
160
161     char disp_buf[64];
162     if (dcb_current) {
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);
167     }
168     else {
169         strcpy(disp_buf, "no disp");
170     }
171
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);
177 }
178
179 /**
180  * ID capability core_local_id counter.
181  */
182 static uint32_t id_cap_counter = 1;
183
184 /**
185  *  Sets #dest equal to #src
186  *
187  * #dest cannot be in use.
188  */
189 static errval_t set_cap(struct capability *dest, struct capability *src)
190 {
191     /* Parameter checking */
192     assert(src  != NULL);
193     assert(dest != NULL);
194
195     // Reserved object bits must always be greater/equal to actual object size
196     assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
197
198     // Cannot overwrite an already existing cap
199     if (dest->type != ObjType_Null) {
200         return SYS_ERR_SLOT_IN_USE;
201     }
202
203     memcpy(dest, src, sizeof(struct capability));
204     return SYS_ERR_OK;
205 }
206
207 /**
208  * \brief Determine how many objects can be created in a specified region.
209  *
210  * This function computes the number of objects that can be created by a call
211  * to caps_create().
212  *
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.
216  *
217  * \return Number of objects to be created, or zero on error
218  */
219
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");
223
224 static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
225 {
226     switch(type) {
227     case ObjType_PhysAddr:
228     case ObjType_RAM:
229     case ObjType_Frame:
230     case ObjType_DevFrame:
231         if (objbits > bits) {
232             return 0;
233         } else {
234             return 1UL << (bits - objbits);
235         }
236
237     case ObjType_CNode:
238         if (bits < OBJBITS_CTE || objbits > bits - OBJBITS_CTE) {
239             return 0;
240         } else {
241             return 1UL << (bits - OBJBITS_CTE - objbits);
242         }
243
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:
253     {
254         size_t objbits_vnode = vnode_objbits(type);
255         if (bits < objbits_vnode) {
256             return 0;
257         } else {
258             return 1UL << (bits - objbits_vnode);
259         }
260     }
261
262     case ObjType_Dispatcher:
263         if (bits < OBJBITS_DISPATCHER) {
264             return 0;
265         } else {
266             return 1UL << (bits - OBJBITS_DISPATCHER);
267         }
268
269     case ObjType_KernelControlBlock:
270         if (bits < OBJBITS_KCB) {
271             return 0;
272         } else {
273             return 1UL << (bits - OBJBITS_KCB);
274         }
275
276     case ObjType_Kernel:
277     case ObjType_IRQTable:
278     case ObjType_IO:
279     case ObjType_EndPoint:
280     case ObjType_ID:
281     case ObjType_Notify_RCK:
282     case ObjType_Notify_IPI:
283     case ObjType_PerfMon:
284     case ObjType_IPI:
285         return 1;
286
287     default:
288         panic("invalid type");
289         return 0;
290     }
291 }
292
293 /**
294  * \brief Initialize the objects for which local caps are about to be created.
295  *
296  * For the meaning of the parameters, see the 'caps_create' function.
297  */
298 STATIC_ASSERT(ObjType_Num == 27, "Knowledge of all cap types");
299
300 static errval_t caps_init_objects(enum objtype type, lpaddr_t lpaddr, uint8_t
301                                   bits, uint8_t objbits, size_t numobjs)
302 {
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.
307     lvaddr_t lvaddr;
308     if(lpaddr < PADDR_SPACE_LIMIT) {
309         lvaddr = local_phys_to_mem(lpaddr);
310     } else {
311         lvaddr = 0;
312     }
313
314     switch (type) {
315
316     case ObjType_Frame:
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);
321         } else {
322             printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
323                    " uninitialized\n", lpaddr);
324         }
325         trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
326         break;
327
328     case ObjType_CNode:
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);
343         break;
344
345     default:
346         break;
347
348     }
349
350     return SYS_ERR_OK;
351 }
352
353 /**
354  * \brief Create capabilities to kernel objects.
355  *
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'.
363  *
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.
370  *
371  * \return Error code
372  */
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");
376
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)
380 {
381     errval_t err;
382
383     /* Parameter checking */
384     assert(dest_caps != NULL);
385     assert(type != ObjType_Null);
386     assert(type < ObjType_Num);
387     assert(numobjs > 0);
388
389     genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
390
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.
395     lvaddr_t lvaddr;
396     if(lpaddr < PADDR_SPACE_LIMIT) {
397         lvaddr = local_phys_to_mem(lpaddr);
398     } else {
399         lvaddr = 0;
400     }
401
402     /* Initialize the created capability */
403     struct capability src_cap;
404     memset(&src_cap, 0, sizeof(struct capability));
405     src_cap.type = type;
406     // XXX: Handle rights!
407     src_cap.rights = CAPRIGHTS_ALLRIGHTS;
408
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)) {
413             return err;
414         }
415     }
416
417     size_t dest_i = 0;
418     err = SYS_ERR_OK;
419
420     /* Set the type specific fields and insert into #dest_caps */
421     switch(type) {
422     case ObjType_Frame:
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);
427         } else {
428             printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
429                    " uninitialized\n", lpaddr);
430         }
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)) {
439                 break;
440             }
441         }
442         break;
443
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)) {
452                 break;
453             }
454         }
455         break;
456
457     case ObjType_RAM:
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)) {
465                 break;
466             }
467         }
468         break;
469
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)) {
478                 break;
479             }
480         }
481         break;
482
483     case ObjType_CNode:
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);
488
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)) {
501                 break;
502             }
503         }
504         break;
505
506     case ObjType_VNode_ARM_l1:
507     {
508         size_t objbits_vnode = vnode_objbits(type);
509
510         TRACE(KERNEL, BZERO, 1);
511         memset((void*)lvaddr, 0, 1UL << bits);
512         TRACE(KERNEL, BZERO, 0);
513
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);
518
519 #ifdef __arm__
520             // Insert kernel/mem mappings into new table.
521             paging_make_good(
522                 gen_phys_to_local_phys(
523                     local_phys_to_mem(src_cap.u.vnode_arm_l1.base)
524                 ),
525                 1u << objbits_vnode
526                 );
527 #endif
528
529             // Insert the capability
530             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
531             if (err_is_fail(err)) {
532                 break;
533             }
534         }
535
536         break;
537     }
538
539     case ObjType_VNode_ARM_l2:
540     {
541         size_t objbits_vnode = vnode_objbits(type);
542
543         TRACE(KERNEL, BZERO, 1);
544         memset((void*)lvaddr, 0, 1UL << bits);
545         TRACE(KERNEL, BZERO, 0);
546
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);
551
552             // Insert the capability
553             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
554             if (err_is_fail(err)) {
555                 break;
556             }
557         }
558         break;
559     }
560
561     case ObjType_VNode_x86_32_ptable:
562     {
563         size_t objbits_vnode = vnode_objbits(type);
564
565         TRACE(KERNEL, BZERO, 1);
566         memset((void*)lvaddr, 0, 1UL << bits);
567         TRACE(KERNEL, BZERO, 0);
568
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);
573
574             // Insert the capability
575             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
576             if (err_is_fail(err)) {
577                 break;
578             }
579         }
580         break;
581     }
582
583     case ObjType_VNode_x86_32_pdir:
584     {
585         size_t objbits_vnode = vnode_objbits(type);
586
587         TRACE(KERNEL, BZERO, 1);
588         memset((void*)lvaddr, 0, 1UL << bits);
589         TRACE(KERNEL, BZERO, 0);
590
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);
595
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);
600 #endif
601
602             // Insert the capability
603             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
604             if (err_is_fail(err)) {
605                 break;
606             }
607         }
608         break;
609     }
610
611     case ObjType_VNode_x86_32_pdpt:
612     {
613         size_t objbits_vnode = vnode_objbits(type);
614
615         TRACE(KERNEL, BZERO, 1);
616         memset((void*)lvaddr, 0, 1UL << bits);
617         TRACE(KERNEL, BZERO, 0);
618
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);
623
624 #if defined(__i386__) && defined(CONFIG_PAE)
625             // Make it a good PDPTE by inserting kernel/mem VSpaces
626             lpaddr_t var =
627                 gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdpt.base);
628             paging_x86_32_make_good_pdpte(var);
629 #endif
630
631             // Insert the capability
632             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
633             if (err_is_fail(err)) {
634                 break;
635             }
636         }
637         break;
638     }
639
640     case ObjType_VNode_x86_64_ptable:
641     {
642         size_t objbits_vnode = vnode_objbits(type);
643
644         TRACE(KERNEL, BZERO, 1);
645         memset((void*)lvaddr, 0, 1UL << bits);
646         TRACE(KERNEL, BZERO, 0);
647
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);
652
653             // Insert the capability
654             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
655             if (err_is_fail(err)) {
656                 break;
657             }
658         }
659         break;
660     }
661
662     case ObjType_VNode_x86_64_pdir:
663     {
664         size_t objbits_vnode = vnode_objbits(type);
665
666         TRACE(KERNEL, BZERO, 1);
667         memset((void*)lvaddr, 0, 1UL << bits);
668         TRACE(KERNEL, BZERO, 0);
669
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);
674
675             // Insert the capability
676             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
677             if (err_is_fail(err)) {
678                 break;
679             }
680         }
681         break;
682     }
683
684     case ObjType_VNode_x86_64_pdpt:
685     {
686         size_t objbits_vnode = vnode_objbits(type);
687
688         TRACE(KERNEL, BZERO, 1);
689         memset((void*)lvaddr, 0, 1UL << bits);
690         TRACE(KERNEL, BZERO, 0);
691
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);
696
697             // Insert the capability
698             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
699             if (err_is_fail(err)) {
700                 break;
701             }
702         }
703         break;
704     }
705
706     case ObjType_VNode_x86_64_pml4:
707     {
708         size_t objbits_vnode = vnode_objbits(type);
709
710         TRACE(KERNEL, BZERO, 1);
711         memset((void*)lvaddr, 0, 1UL << bits);
712         TRACE(KERNEL, BZERO, 0);
713
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);
718
719 #if defined(__x86_64__) || defined(__k1om__)
720             // Make it a good PML4 by inserting kernel/mem VSpaces
721             lpaddr_t var = gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
722             paging_x86_64_make_good_pml4(var);
723 #endif
724
725             // Insert the capability
726             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
727             if (err_is_fail(err)) {
728                 break;
729             }
730         }
731
732         break;
733     }
734
735     case ObjType_Dispatcher:
736         assert((1UL << OBJBITS_DISPATCHER) >= sizeof(struct dcb));
737         TRACE(KERNEL, BZERO, 1);
738         memset((void*)lvaddr, 0, 1UL << bits);
739         TRACE(KERNEL, BZERO, 0);
740
741         for(dest_i = 0; dest_i < numobjs; dest_i++) {
742             // Initialize type specific fields
743             src_cap.u.dispatcher.dcb = (struct dcb *)
744                 (lvaddr + dest_i * (1UL << OBJBITS_DISPATCHER));
745             // Insert the capability
746             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
747             if (err_is_fail(err)) {
748                 break;
749             }
750         }
751         break;
752
753     case ObjType_ID:
754         // ID type does not refer to a kernel object
755         assert(lpaddr  == 0);
756         assert(bits    == 0);
757         assert(objbits == 0);
758         assert(numobjs == 1);
759
760         // Prevent wrap around
761         if (id_cap_counter >= UINT32_MAX) {
762             return SYS_ERR_ID_SPACE_EXHAUSTED;
763         }
764
765         // Generate a new ID, core_local_id monotonically increases
766         src_cap.u.id.coreid = my_core_id;
767         src_cap.u.id.core_local_id = id_cap_counter++;
768
769         // Insert the capability
770         err = set_cap(&dest_caps->cap, &src_cap);
771         break;
772
773     case ObjType_IO:
774         src_cap.u.io.start = 0;
775         src_cap.u.io.end   = 65535;
776         /* fall through */
777
778     case ObjType_Kernel:
779     case ObjType_IPI:
780     case ObjType_IRQTable:
781     case ObjType_EndPoint:
782     case ObjType_Notify_RCK:
783     case ObjType_Notify_IPI:
784     case ObjType_PerfMon:
785         // These types do not refer to a kernel object
786         assert(lpaddr  == 0);
787         assert(bits    == 0);
788         assert(objbits == 0);
789         assert(numobjs == 1);
790
791         // Insert the capability
792         err = set_cap(&dest_caps->cap, &src_cap);
793         if (err_is_ok(err)) {
794             dest_i = 1;
795         }
796         break;
797
798     case ObjType_KernelControlBlock:
799         assert((1UL << OBJBITS_KCB) >= sizeof(struct dcb));
800
801         for(size_t i = 0; i < numobjs; i++) {
802             // Initialize type specific fields
803             src_cap.u.kernelcontrolblock.kcb = (struct kcb *)
804                 (lvaddr + i * (1UL << OBJBITS_DISPATCHER));
805             // Insert the capability
806             err = set_cap(&dest_caps[i].cap, &src_cap);
807             if (err_is_fail(err)) {
808                 return err;
809             }
810         }
811         return SYS_ERR_OK;
812
813     default:
814         panic("Unhandled capability type or capability of this type cannot"
815               " be created");
816     }
817
818     if (err_is_fail(err)) {
819         // Revert the partially initialized caps to zero
820         for (size_t i = 0; i < dest_i; i++) {
821             memset(&dest_caps[i], 0, sizeof(dest_caps[i]));
822         }
823         return err;
824     }
825     else {
826         // Set the owner for all the new caps
827         for (size_t i = 0; i < dest_i; i++) {
828             dest_caps[i].mdbnode.owner = owner;
829         }
830     }
831
832     return SYS_ERR_OK;
833 }
834
835 /**
836  * Look up a capability.
837  *
838  * Starting from #cnode_cap, recursively lookup the capability at #cptr
839  * with #vbits.
840  *
841  * \bug Handle rights
842  */
843 errval_t caps_lookup_slot(struct capability *cnode_cap, capaddr_t cptr,
844                           uint8_t vbits, struct cte **ret, CapRights rights)
845 {
846     TRACE(KERNEL, CAP_LOOKUP_SLOT, 0);
847     /* parameter checking */
848     assert(cnode_cap != NULL);
849
850     /* Can only resolve CNode type */
851     if (cnode_cap->type != ObjType_CNode) {
852         debug(SUBSYS_CAPS, "caps_lookup_slot: Cap to lookup not of type CNode\n"
853               "cnode_cap->type = %u\n", cnode_cap->type);
854         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
855         return SYS_ERR_CNODE_TYPE;
856     }
857
858     /* Apply rights to this CNode */
859     if ((cnode_cap->rights & rights) != rights) {
860         debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
861               "Passed rights = %u, cnode_cap->rights = %u\n",
862               rights, cnode_cap->rights);
863         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
864         return SYS_ERR_CNODE_RIGHTS;
865     }
866
867     /* Number of bits resolved by this cnode (guard and bits) */
868     uint8_t bits_resolved = cnode_cap->u.cnode.bits +
869         cnode_cap->u.cnode.guard_size;
870     // All CNodes must resolve at least one bit
871     assert(bits_resolved > 0);
872     // If lookup exceeded expected depth then table is malformed
873     if (bits_resolved > vbits) {
874         debug(SUBSYS_CAPS, "caps_lookup_slot: Lookup exceeded valid bits\n"
875               "Cnode bits = %u, guard size = %u, valid bits = %u, bits_resolved = %u\n",
876               cnode_cap->u.cnode.bits, cnode_cap->u.cnode.guard_size,
877               vbits, bits_resolved);
878         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
879         return SYS_ERR_DEPTH_EXCEEDED;
880     }
881
882     /* Guard-check (bit-mask of guard in cptr must match guard in cnode cap) */
883     capaddr_t cptr_guard = (cptr >> (vbits - cnode_cap->u.cnode.guard_size))
884         & MASK(cnode_cap->u.cnode.guard_size);
885     if (cptr_guard != cnode_cap->u.cnode.guard) {
886         debug(SUBSYS_CAPS, "caps_lookup_slot: guard check failed\n"
887               "Computed guard = %"PRIuCADDR", "
888               "Cnode guard = %"PRIxCADDR", bits = %u\n",
889               cptr_guard, cnode_cap->u.cnode.guard,
890               cnode_cap->u.cnode.guard_size);
891         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
892         return SYS_ERR_GUARD_MISMATCH;
893     }
894
895     /* Locate capability in this cnode */
896     // Offset into the cnode
897     size_t offset = (cptr >> (vbits - bits_resolved)) &
898         MASK(cnode_cap->u.cnode.bits);
899     // The capability at the offset
900     struct cte *next_slot = caps_locate_slot(cnode_cap->u.cnode.cnode, offset);
901     // Do not return NULL type capability
902     if (next_slot->cap.type == ObjType_Null) {
903         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
904         return SYS_ERR_CAP_NOT_FOUND;
905     }
906
907     /* Number of bits left to resolve */
908     int bitsleft = vbits - bits_resolved;
909     // If all bits have been resolved, return the capability
910     if(bitsleft == 0) {
911         *ret = next_slot;
912         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
913         return SYS_ERR_OK;
914     }
915
916     /* If next capability is not of type cnode, return it */
917     // XXX: Is this consistent?
918     if (next_slot->cap.type != ObjType_CNode) {
919         *ret = next_slot;
920         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
921         return SYS_ERR_OK;
922     }
923
924     /* Descend to next level */
925     return caps_lookup_slot(&next_slot->cap, cptr, bitsleft, ret, rights);
926 }
927
928 /**
929  * Wrapper for caps_lookup_slot returning capability instead of cte.
930  */
931 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
932                          uint8_t vbits, struct capability **ret, CapRights rights)
933 {
934     TRACE(KERNEL, CAP_LOOKUP_CAP, 0);
935     struct cte *ret_cte;
936     errval_t err = caps_lookup_slot(cnode_cap, cptr, vbits, &ret_cte, rights);
937     if (err_is_fail(err)) {
938         return err;
939     }
940     *ret = &ret_cte->cap;
941     TRACE(KERNEL, CAP_LOOKUP_CAP, 1);
942     return SYS_ERR_OK;
943 }
944
945 /**
946  * \brief Create a capability from an existing capability metadata.
947  *
948  * Used when sending capabilities across cores. The metadata is sent across
949  * cores and the receiving monitor can create the new capability on its core.
950  *
951  * \bug Does not check that supplied owner matches existing copies of cap.
952  */
953 errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
954                                    int cnode_vbits, cslot_t dest_slot, coreid_t owner,
955                                    struct capability *src)
956 {
957     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 0);
958     errval_t err;
959     struct capability *cnode;
960     err = caps_lookup_cap(root, cnode_cptr, cnode_vbits, &cnode,
961                           CAPRIGHTS_READ_WRITE);
962     if (err_is_fail(err)) {
963         return err_push(err, SYS_ERR_SLOT_LOOKUP_FAIL);
964     }
965     if (cnode->type != ObjType_CNode) {
966         return SYS_ERR_CNODE_TYPE;
967     }
968
969     struct cte *dest = caps_locate_slot(cnode->u.cnode.cnode, dest_slot);
970
971     err = set_cap(&dest->cap, src);
972     if (err_is_fail(err)) {
973         return err;
974     }
975
976     dest->mdbnode.owner = owner;
977
978     err = mdb_insert(dest);
979     assert(err_is_ok(err));
980
981     struct cte *neighbour = NULL;
982     if (!neighbour
983         && (neighbour = mdb_predecessor(dest))
984         && !is_copy(&dest->cap, &neighbour->cap))
985     {
986         neighbour = NULL;
987     }
988     if (!neighbour
989         && (neighbour = mdb_successor(dest))
990         && !is_copy(&dest->cap, &neighbour->cap))
991     {
992         neighbour = NULL;
993     }
994
995     if (neighbour) {
996         assert(!neighbour->mdbnode.in_delete);
997         assert(neighbour->mdbnode.owner == owner);
998 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
999         CP_ATTR(locked);
1000         CP_ATTR(remote_copies);
1001         CP_ATTR(remote_ancs);
1002         CP_ATTR(remote_descs);
1003 #undef CP_ATTR
1004     }
1005     else {
1006         dest->mdbnode.locked = false;
1007         if (owner != my_core_id) {
1008             // For foreign caps it does not really matter if ancestors or
1009             // descendants exist
1010             dest->mdbnode.remote_copies = true;
1011             dest->mdbnode.remote_ancs = false;
1012             dest->mdbnode.remote_descs = false;
1013         }
1014         else {
1015             // We just created a new copy of a owned capability from nothing.
1016             // This is either caused by a retype, or by sharing a capability
1017             // that does not care about locality.
1018             // XXX: This should probably be done more explicitly -MN
1019             if (distcap_needs_locality(dest->cap.type)) {
1020                 // Retype, so have ancestors and no descendants
1021                 dest->mdbnode.remote_copies = false;
1022                 dest->mdbnode.remote_ancs = true;
1023                 dest->mdbnode.remote_descs = false;
1024             }
1025             else {
1026                 dest->mdbnode.remote_copies = false;
1027                 dest->mdbnode.remote_ancs = false;
1028                 dest->mdbnode.remote_descs = false;
1029             }
1030         }
1031     }
1032
1033     TRACE_CAP_MSG("created", dest);
1034
1035     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 1);
1036     return SYS_ERR_OK;
1037 }
1038
1039 /// Create caps to new kernel objects.
1040 errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bits,
1041                          size_t objbits, coreid_t owner, struct cte *caps)
1042 {
1043     TRACE(KERNEL, CAP_CREATE_NEW, 0);
1044     /* Parameter checking */
1045     assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1046
1047     size_t numobjs = caps_numobjs(type, bits, objbits);
1048     assert(numobjs > 0);
1049
1050     /* Create the new capabilities */
1051     errval_t err = caps_create(type, addr, bits, objbits, numobjs, owner, caps);
1052     if (err_is_fail(err)) {
1053         return err;
1054     }
1055
1056     // Handle the mapping database
1057     set_init_mapping(caps, numobjs);
1058
1059     TRACE_CAP_MSG("created", &caps[0]);
1060
1061     TRACE(KERNEL, CAP_CREATE_NEW, 1);
1062     return SYS_ERR_OK;
1063 }
1064
1065
1066 /// Retype caps
1067 errval_t caps_retype(enum objtype type, size_t objbits,
1068                      struct capability *dest_cnode, cslot_t dest_slot,
1069                      struct cte *src_cte, bool from_monitor)
1070 {
1071     TRACE(KERNEL, CAP_RETYPE, 0);
1072     size_t numobjs;
1073     uint8_t bits = 0;
1074     genpaddr_t base = 0;
1075     errval_t err;
1076
1077     /* Parameter checking */
1078     assert(type != ObjType_Null);
1079     assert(type < ObjType_Num);
1080
1081     struct capability *src_cap = &src_cte->cap;
1082
1083     TRACE_CAP_MSG("retyping", src_cte);
1084
1085     /* Check retypability */
1086     err = is_retypeable(src_cte, src_cap->type, type, from_monitor);
1087     if (err_is_fail(err)) {
1088         debug(SUBSYS_CAPS, "caps_retype: is_retypeable failed\n");
1089         return err;
1090     }
1091
1092     /* Create Destination caps as per source and destination type */
1093     switch(src_cap->type) {
1094     case ObjType_PhysAddr:
1095         bits = src_cap->u.physaddr.bits;
1096         base = src_cap->u.physaddr.base;
1097         break;
1098
1099     case ObjType_RAM:
1100         bits = src_cap->u.ram.bits;
1101         base = src_cap->u.ram.base;
1102         break;
1103
1104     case ObjType_Dispatcher:
1105         bits = base = 0;
1106         break;
1107
1108     case ObjType_Frame:
1109         bits = src_cap->u.frame.bits;
1110         base = src_cap->u.frame.base;
1111         break;
1112
1113     case ObjType_DevFrame:
1114         bits = src_cap->u.devframe.bits;
1115         base = src_cap->u.devframe.base;
1116         break;
1117
1118     default:
1119         panic("Unreachable case");
1120     }
1121
1122     /* determine number of objects to be created */
1123     numobjs = caps_numobjs(type, bits, objbits);
1124
1125     if (numobjs == 0) {
1126         debug(SUBSYS_CAPS, "caps_retype: numobjs == 0\n");
1127         return SYS_ERR_INVALID_SIZE_BITS;
1128     }
1129    // debug(SUBSYS_CAPS, "caps_retype: numobjs == %d\n", (int)numobjs);
1130
1131     /* check that destination slots all fit within target cnode */
1132     if (dest_slot + numobjs > (1UL << dest_cnode->u.cnode.bits)) {
1133         debug(SUBSYS_CAPS, "caps_retype: dest slots don't fit in cnode\n");
1134         return SYS_ERR_SLOTS_INVALID;
1135     }
1136
1137     /* check that destination slots are all empty */
1138     debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1139           " dest_slot %d\n",
1140           dest_cnode->u.cnode.cnode, (int)dest_slot);
1141     for (cslot_t i = 0; i < numobjs; i++) {
1142         if (caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot + i)->cap.type
1143             != ObjType_Null) {
1144             debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1145                   (int)(dest_slot + i));
1146             return SYS_ERR_SLOTS_IN_USE;
1147         }
1148     }
1149
1150     /* create new caps */
1151     struct cte *dest_cte =
1152         caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot);
1153     err = caps_create(type, base, bits, objbits, numobjs, my_core_id, dest_cte);
1154     if (err_is_fail(err)) {
1155         debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
1156         return err_push(err, SYS_ERR_RETYPE_CREATE);
1157     }
1158
1159     /* special initialisation for endpoint caps */
1160     if (type == ObjType_EndPoint) {
1161         assert(src_cap->type == ObjType_Dispatcher);
1162         assert(numobjs == 1);
1163         struct capability *dest_cap = &dest_cte->cap;
1164         dest_cap->u.endpoint.listener = src_cap->u.dispatcher.dcb;
1165     }
1166
1167     /* Handle mapping */
1168     for (size_t i = 0; i < numobjs; i++) {
1169         mdb_insert(&dest_cte[i]);
1170     }
1171
1172 #ifdef TRACE_PMEM_CAPS
1173     for (size_t i = 0; i < numobjs; i++) {
1174         TRACE_CAP_MSG("created", &dest_cte[i]);
1175     }
1176 #endif
1177
1178     TRACE(KERNEL, CAP_RETYPE, 1);
1179     return SYS_ERR_OK;
1180 }
1181
1182 /// Check the validity of a retype operation
1183 errval_t is_retypeable(struct cte *src_cte, enum objtype src_type,
1184                        enum objtype dest_type, bool from_monitor)
1185 {
1186     if (!is_well_founded(src_type, dest_type)) {
1187         return SYS_ERR_INVALID_RETYPE;
1188     } else if (!is_revoked_first(src_cte, src_type)){
1189         printf("err_revoke_first: (%p, %d, %d)\n", src_cte, src_type, dest_type);
1190         return SYS_ERR_REVOKE_FIRST;
1191     } else if (dest_type == ObjType_EndPoint && src_cte->mdbnode.owner == my_core_id) {
1192         // XXX: because of the current "multi-retype" hack for endpoints, a
1193         // dispatcher->endpoint retype can happen irrespective of the existence
1194         // of descendents on any core.
1195         // Howevery, we only do this for locally owned caps as the owner should
1196         // be notified that the cap has remote descendants
1197         return SYS_ERR_OK;
1198     } else if (!from_monitor && (src_cte->mdbnode.owner != my_core_id
1199                                  || src_cte->mdbnode.remote_descs)) {
1200         return SYS_ERR_RETRY_THROUGH_MONITOR;
1201     } else {
1202         return SYS_ERR_OK;
1203     }
1204 }
1205
1206 /// Create copies to a slot within a cnode
1207 errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
1208                             struct cte *src_cte, bool mint, uintptr_t param1,
1209                             uintptr_t param2)
1210 {
1211     /* Parameter Checking */
1212     assert(dest_cnode_cte->cap.type == ObjType_CNode);
1213
1214     struct cte *dest_cte;
1215     dest_cte = caps_locate_slot(dest_cnode_cte->cap.u.cnode.cnode, dest_slot);
1216     return caps_copy_to_cte(dest_cte, src_cte, mint, param1, param2);
1217
1218 }
1219
1220 /// Create copies to a cte
1221 errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
1222                           uintptr_t param1, uintptr_t param2)
1223 {
1224     errval_t err;
1225     /* Parameter checking */
1226     // Null checking
1227     assert(dest_cte != NULL);
1228     assert(src_cte != NULL);
1229
1230     struct capability *src_cap  = &src_cte->cap;
1231     struct capability *dest_cap = &dest_cte->cap;
1232     // NULL caps cannot be copied/minted
1233     if (src_cap->type == ObjType_Null) {
1234         return SYS_ERR_CAP_NOT_FOUND;
1235     }
1236     // Parameters should be 0 if not minting
1237     if (!mint) {
1238         assert(param1 == 0);
1239         assert(param2 == 0);
1240     }
1241
1242     assert(!src_cte->mdbnode.in_delete);
1243
1244     /* Insert #source_cap into #dest_cap */
1245     err = set_cap(dest_cap, src_cap);
1246     if (err_is_fail(err)) {
1247         return err;
1248     }
1249
1250     /* Transfer MDB attributes that must be equal for all copies */
1251 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1252     CP_ATTR(owner);
1253     CP_ATTR(locked);
1254     CP_ATTR(remote_copies);
1255     CP_ATTR(remote_ancs);
1256     CP_ATTR(remote_descs);
1257 #undef CP_ATTR
1258
1259     /* Copy is done */
1260     if(!mint) {
1261         TRACE_CAP_MSG("copied to", dest_cte);
1262         // Handle mapping here only for non-mint operations
1263         // (mint can change eq fields which would make the early insertion
1264         // invalid in some cases)
1265         mdb_insert(dest_cte);
1266         return SYS_ERR_OK;
1267     }
1268     else {
1269         TRACE_CAP_MSG("minting to", dest_cte);
1270     }
1271
1272     /* For minting, set the specified parameters */
1273     // Process source-specific parameters for minting
1274     // XXX: If failure, revert the insertion
1275     switch(src_cap->type) {
1276     case ObjType_CNode:
1277         if (param2 > CPTR_BITS) {
1278             return SYS_ERR_GUARD_SIZE_OVERFLOW;
1279         }
1280         dest_cap->u.cnode.guard      = param1;
1281         dest_cap->u.cnode.guard_size = param2;
1282         break;
1283
1284     case ObjType_EndPoint:
1285         // XXX: FIXME: check that buffer offset lies wholly within the disp frame
1286         // can't easily enforce this here, because the dispatcher frame may not
1287         // yet be setup
1288 /*        if (param1 < sizeof(struct dispatcher) ||
1289             dest_cap->u.endpoint.listener->disp == NULL ||
1290             param2 < IDC_RECV_LENGTH ||
1291             param1 + sizeof(struct idc_endpoint) + param2 * sizeof(uintptr_t) >
1292             (1UL << dest_cap->u.endpoint.listener->disp_cte.cap.u.frame.bits)) {
1293             return SYS_ERR_INVALID_EPBUF;
1294         }*/
1295         if (param2 < LMP_RECV_HEADER_LENGTH) {
1296             return SYS_ERR_INVALID_EPLEN;
1297         }
1298         dest_cap->u.endpoint.epoffset = param1;
1299         dest_cap->u.endpoint.epbuflen = param2;
1300         break;
1301
1302     case ObjType_IO:
1303         if(src_cap->u.io.start  <= param1) {
1304             dest_cap->u.io.start = param1;
1305         }
1306         if(src_cap->u.io.end  >= param2) {
1307             dest_cap->u.io.end = param2;
1308         }
1309         break;
1310
1311     default:
1312         // Unhandled source type for mint
1313         return SYS_ERR_INVALID_SOURCE_TYPE;
1314     }
1315
1316     // Insert after doing minting operation
1317     mdb_insert(dest_cte);
1318
1319     return SYS_ERR_OK;
1320 }
1321
1322
1323 // If you create more capability types you need to deal with them
1324 // in the table below.
1325 STATIC_ASSERT(27 == ObjType_Num, "Knowledge of all cap types");
1326
1327
1328 errval_t
1329 caps_debug_print(struct cte *c)
1330 {
1331     printk(LOG_NOTE, "%s\n", __FUNCTION__);
1332     switch (c->cap.type) {
1333     // all cap types
1334     case ObjType_CNode: {
1335         struct CNode *cn = &(c->cap.u.cnode);
1336         for (cslot_t slot = 0; slot < 1UL << cn->bits; slot++) {
1337
1338             errval_t err = caps_debug_print(
1339                     (struct cte *) local_phys_to_mem(
1340                             cn->cnode + slot * sizeof(*c)));
1341             if (err_is_fail(err)) {
1342                 return err;
1343             }
1344         }
1345         break;
1346     }
1347     case ObjType_Frame: {
1348         break;
1349     }
1350     default: {
1351         // Unhandled source type for mint
1352         return SYS_ERR_INVALID_SOURCE_TYPE;
1353     }
1354     }
1355
1356     return SYS_ERR_OK;
1357 }