Added noreturn attribute to mdb_dump_and_fail().
[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 <paging_kernel_arch.h>
27 #include <mdb/mdb.h>
28 #include <mdb/mdb_tree.h>
29 #include <trace/trace.h>
30 #include <trace_definitions/trace_defs.h>
31 #include <wakeup.h>
32
33 /// Sets the specified number of low-order bits to 1
34 #define MASK(bits)      ((1UL << bits) - 1)
35
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;
40
41 void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
42 {
43     if (types) {
44         trace_types_enabled = types;
45         TRACE_PMEM_BEGIN = start;
46         TRACE_PMEM_SIZE = size;
47     } else {
48         trace_types_enabled = false;
49     }
50 }
51 #endif
52
53 struct capability monitor_ep;
54
55 int sprint_cap(char *buf, size_t len, struct capability *cap)
56 {
57     switch (cap->type) {
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);
62
63     case ObjType_RAM:
64         return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":%u)",
65                         cap->u.ram.base, cap->u.ram.bits);
66
67     case ObjType_CNode: {
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);
74         }
75         return ret;
76     }
77
78     case ObjType_Dispatcher:
79         return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
80
81     case ObjType_Frame:
82         return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":%u)",
83                         cap->u.frame.base, cap->u.frame.bits);
84
85     case ObjType_DevFrame:
86         return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":%u)",
87                         cap->u.frame.base, cap->u.devframe.bits);
88
89     case ObjType_VNode_ARM_l1:
90         return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
91                         cap->u.vnode_arm_l1.base);
92
93     case ObjType_VNode_ARM_l2:
94         return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
95                         cap->u.vnode_arm_l2.base);
96
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);
100
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);
104
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);
108
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);
112
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);
116
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);
120
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);
124
125     case ObjType_IRQTable:
126         return snprintf(buf, len, "IRQTable cap");
127
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);
131
132     case ObjType_IO:
133         return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
134                         cap->u.io.start, cap->u.io.end);
135
136     case ObjType_Kernel:
137         return snprintf(buf, len, "Kernel cap");
138
139     case ObjType_ID:
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);
143
144     case ObjType_PerfMon:
145         return snprintf(buf, len, "PerfMon cap");
146
147     case ObjType_Null:
148         return snprintf(buf, len, "Null capability (empty slot)");
149
150     default:
151         return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
152     }
153 }
154
155 void caps_trace(const char *func, int line, struct cte *cte, const char *msg)
156 {
157     char cap_buf[512];
158     sprint_cap(cap_buf, 512, &cte->cap);
159
160     char disp_buf[64];
161     if (dcb_current) {
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);
166     }
167     else {
168         strcpy(disp_buf, "no disp");
169     }
170
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);
176 }
177
178 /**
179  * ID capability core_local_id counter.
180  */
181 static uint32_t id_cap_counter = 1;
182
183 /**
184  *  Sets #dest equal to #src
185  *
186  * #dest cannot be in use.
187  */
188 static errval_t set_cap(struct capability *dest, struct capability *src)
189 {
190     /* Parameter checking */
191     assert(src  != NULL);
192     assert(dest != NULL);
193
194     // Reserved object bits must always be greater/equal to actual object size
195     assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
196
197     // Cannot overwrite an already existing cap
198     if (dest->type != ObjType_Null) {
199         return SYS_ERR_SLOT_IN_USE;
200     }
201
202     memcpy(dest, src, sizeof(struct capability));
203     return SYS_ERR_OK;
204 }
205
206 /**
207  * \brief Determine how many objects can be created in a specified region.
208  *
209  * This function computes the number of objects that can be created by a call
210  * to caps_create().
211  *
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.
215  *
216  * \return Number of objects to be created, or zero on error
217  */
218
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");
222
223 static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
224 {
225     switch(type) {
226     case ObjType_PhysAddr:
227     case ObjType_RAM:
228     case ObjType_Frame:
229     case ObjType_DevFrame:
230         if (objbits > bits) {
231             return 0;
232         } else {
233             return 1UL << (bits - objbits);
234         }
235
236     case ObjType_CNode:
237         if (bits < OBJBITS_CTE || objbits > bits - OBJBITS_CTE) {
238             return 0;
239         } else {
240             return 1UL << (bits - OBJBITS_CTE - objbits);
241         }
242
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:
252     {
253         size_t objbits_vnode = vnode_objbits(type);
254         if (bits < objbits_vnode) {
255             return 0;
256         } else {
257             return 1UL << (bits - objbits_vnode);
258         }
259     }
260
261     case ObjType_Dispatcher:
262         if (bits < OBJBITS_DISPATCHER) {
263             return 0;
264         } else {
265             return 1UL << (bits - OBJBITS_DISPATCHER);
266         }
267
268     case ObjType_Kernel:
269     case ObjType_IRQTable:
270     case ObjType_IO:
271     case ObjType_EndPoint:
272     case ObjType_ID:
273     case ObjType_Notify_RCK:
274     case ObjType_Notify_IPI:
275     case ObjType_PerfMon:
276         return 1;
277
278     default:
279         panic("invalid type");
280         return 0;
281     }
282 }
283
284 /**
285  * \brief Initialize the objects for which local caps are about to be created.
286  *
287  * For the meaning of the parameters, see the 'caps_create' function.
288  */
289 STATIC_ASSERT(ObjType_Num == 25, "Knowledge of all cap types");
290
291 static errval_t caps_init_objects(enum objtype type, lpaddr_t lpaddr, uint8_t
292                                   bits, uint8_t objbits, size_t numobjs)
293 {
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.
298     lvaddr_t lvaddr;
299     if(lpaddr < PADDR_SPACE_LIMIT) {
300         lvaddr = local_phys_to_mem(lpaddr);
301     } else {
302         lvaddr = 0;
303     }
304
305     switch (type) {
306
307     case ObjType_Frame:
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);
312         } else {
313             printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
314                    " uninitialized\n", lpaddr);
315         }
316         trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
317         break;
318
319     case ObjType_CNode:
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);
333         break;
334
335     default:
336         break;
337
338     }
339
340     return SYS_ERR_OK;
341 }
342
343 /**
344  * \brief Create capabilities to kernel objects.
345  *
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'.
353  *
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.
360  *
361  * \return Error code
362  */
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");
366
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)
370 {
371     errval_t err;
372
373     /* Parameter checking */
374     assert(dest_caps != NULL);
375     assert(type != ObjType_Null);
376     assert(type < ObjType_Num);
377     assert(numobjs > 0);
378
379     genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
380
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.
385     lvaddr_t lvaddr;
386     if(lpaddr < PADDR_SPACE_LIMIT) {
387         lvaddr = local_phys_to_mem(lpaddr);
388     } else {
389         lvaddr = 0;
390     }
391
392     /* Initialize the created capability */
393     struct capability src_cap;
394     memset(&src_cap, 0, sizeof(struct capability));
395     src_cap.type = type;
396     // XXX: Handle rights!
397     src_cap.rights = CAPRIGHTS_ALLRIGHTS;
398
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)) {
403             return err;
404         }
405     }
406
407     size_t dest_i = 0;
408     err = SYS_ERR_OK;
409
410     /* Set the type specific fields and insert into #dest_caps */
411     switch(type) {
412     case ObjType_Frame:
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);
417         } else {
418             printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
419                    " uninitialized\n", lpaddr);
420         }
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)) {
429                 break;
430             }
431         }
432         break;
433
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)) {
442                 break;
443             }
444         }
445         break;
446
447     case ObjType_RAM:
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)) {
455                 break;
456             }
457         }
458         break;
459
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)) {
468                 break;
469             }
470         }
471         break;
472
473     case ObjType_CNode:
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);
478
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)) {
491                 break;
492             }
493         }
494         break;
495
496     case ObjType_VNode_ARM_l1:
497     {
498         size_t objbits_vnode = vnode_objbits(type);
499
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);
503
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);
508
509 #ifdef __arm__
510             // Insert kernel/mem mappings into new table.
511             paging_make_good(
512                 gen_phys_to_local_phys(
513                     local_phys_to_mem(src_cap.u.vnode_arm_l1.base)
514                 ),
515                 1u << objbits_vnode
516                 );
517 #endif
518
519             // Insert the capability
520             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
521             if (err_is_fail(err)) {
522                 break;
523             }
524         }
525
526         break;
527     }
528
529     case ObjType_VNode_ARM_l2:
530     {
531         size_t objbits_vnode = vnode_objbits(type);
532
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);
536
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);
541
542             // Insert the capability
543             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
544             if (err_is_fail(err)) {
545                 break;
546             }
547         }
548         break;
549     }
550
551     case ObjType_VNode_x86_32_ptable:
552     {
553         size_t objbits_vnode = vnode_objbits(type);
554
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);
558
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);
563
564             // Insert the capability
565             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
566             if (err_is_fail(err)) {
567                 break;
568             }
569         }
570         break;
571     }
572
573     case ObjType_VNode_x86_32_pdir:
574     {
575         size_t objbits_vnode = vnode_objbits(type);
576
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);
580
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);
585
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);
590 #endif
591
592             // Insert the capability
593             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
594             if (err_is_fail(err)) {
595                 break;
596             }
597         }
598         break;
599     }
600
601     case ObjType_VNode_x86_32_pdpt:
602     {
603         size_t objbits_vnode = vnode_objbits(type);
604
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);
608
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);
613
614 #if defined(__i386__) && defined(CONFIG_PAE)
615             // Make it a good PDPTE by inserting kernel/mem VSpaces
616             lpaddr_t var =
617                 gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdpt.base);
618             paging_x86_32_make_good_pdpte(var);
619 #endif
620
621             // Insert the capability
622             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
623             if (err_is_fail(err)) {
624                 break;
625             }
626         }
627         break;
628     }
629
630     case ObjType_VNode_x86_64_ptable:
631     {
632         size_t objbits_vnode = vnode_objbits(type);
633
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);
637
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);
642
643             // Insert the capability
644             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
645             if (err_is_fail(err)) {
646                 break;
647             }
648         }
649         break;
650     }
651
652     case ObjType_VNode_x86_64_pdir:
653     {
654         size_t objbits_vnode = vnode_objbits(type);
655
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);
659
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);
664
665             // Insert the capability
666             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
667             if (err_is_fail(err)) {
668                 break;
669             }
670         }
671         break;
672     }
673
674     case ObjType_VNode_x86_64_pdpt:
675     {
676         size_t objbits_vnode = vnode_objbits(type);
677
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);
681
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);
686
687             // Insert the capability
688             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
689             if (err_is_fail(err)) {
690                 break;
691             }
692         }
693         break;
694     }
695
696     case ObjType_VNode_x86_64_pml4:
697     {
698         size_t objbits_vnode = vnode_objbits(type);
699
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);
703
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);
708
709 #ifdef __k1om__
710             lpaddr_t var = gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
711                         paging_k1om_make_good_pml4(var);
712 #else
713 #ifdef __x86_64__
714             // Make it a good PML4 by inserting kernel/mem VSpaces
715             lpaddr_t var =
716                 gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
717             paging_x86_64_make_good_pml4(var);
718 #endif
719 #endif
720
721             // Insert the capability
722             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
723             if (err_is_fail(err)) {
724                 break;
725             }
726         }
727
728         break;
729     }
730
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);
736
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)) {
744                 break;
745             }
746         }
747         break;
748
749     case ObjType_ID:
750         // ID type does not refer to a kernel object
751         assert(lpaddr  == 0);
752         assert(bits    == 0);
753         assert(objbits == 0);
754         assert(numobjs == 1);
755
756         // Prevent wrap around
757         if (id_cap_counter >= UINT32_MAX) {
758             return SYS_ERR_ID_SPACE_EXHAUSTED;
759         }
760
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++;
764
765         // Insert the capability
766         err = set_cap(&dest_caps->cap, &src_cap);
767         break;
768
769     case ObjType_IO:
770         src_cap.u.io.start = 0;
771         src_cap.u.io.end   = 65535;
772         /* fall through */
773
774     case ObjType_Kernel:
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
781         assert(lpaddr  == 0);
782         assert(bits    == 0);
783         assert(objbits == 0);
784         assert(numobjs == 1);
785
786         // Insert the capability
787         err = set_cap(&dest_caps->cap, &src_cap);
788         if (err_is_ok(err)) {
789             dest_i = 1;
790         }
791         break;
792
793     default:
794         panic("Unhandled capability type or capability of this type cannot"
795               " be created");
796     }
797
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]));
802         }
803         return err;
804     }
805     else {
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;
809         }
810     }
811
812     return SYS_ERR_OK;
813 }
814
815 /**
816  * Look up a capability.
817  *
818  * Starting from #cnode_cap, recursively lookup the capability at #cptr
819  * with #vbits.
820  *
821  * \bug Handle rights
822  */
823 errval_t caps_lookup_slot(struct capability *cnode_cap, capaddr_t cptr,
824                           uint8_t vbits, struct cte **ret, CapRights rights)
825 {
826     /* parameter checking */
827     assert(cnode_cap != NULL);
828
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;
834     }
835
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;
842     }
843
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;
856     }
857
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;
868     }
869
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;
879     }
880
881     /* Number of bits left to resolve */
882     int bitsleft = vbits - bits_resolved;
883     // If all bits have been resolved, return the capability
884     if(bitsleft == 0) {
885         *ret = next_slot;
886         return SYS_ERR_OK;
887     }
888
889     /* If next capability is not of type cnode, return it */
890     // XXX: Is this consistent?
891     if (next_slot->cap.type != ObjType_CNode) {
892         *ret = next_slot;
893         return SYS_ERR_OK;
894     }
895
896     /* Descend to next level */
897     return caps_lookup_slot(&next_slot->cap, cptr, bitsleft, ret, rights);
898 }
899
900 /**
901  * Wrapper for caps_lookup_slot returning capability instead of cte.
902  */
903 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
904                          uint8_t vbits, struct capability **ret, CapRights rights)
905 {
906     struct cte *ret_cte;
907     errval_t err = caps_lookup_slot(cnode_cap, cptr, vbits, &ret_cte, rights);
908     if (err_is_fail(err)) {
909         return err;
910     }
911     *ret = &ret_cte->cap;
912     return SYS_ERR_OK;
913 }
914
915 /**
916  * \brief Create a capability from an existing capability metadata.
917  *
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.
920  *
921  * \bug Does not check that supplied owner matches existing copies of cap.
922  */
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)
926 {
927     errval_t err;
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);
933     }
934     if (cnode->type != ObjType_CNode) {
935         return SYS_ERR_CNODE_TYPE;
936     }
937
938     struct cte *dest = caps_locate_slot(cnode->u.cnode.cnode, dest_slot);
939
940     err = set_cap(&dest->cap, src);
941     if (err_is_fail(err)) {
942         return err;
943     }
944
945     dest->mdbnode.owner = owner;
946
947     err = mdb_insert(dest);
948     assert(err_is_ok(err));
949
950     struct cte *neighbour = NULL;
951     if (!neighbour
952         && (neighbour = mdb_predecessor(dest))
953         && !is_copy(&dest->cap, &neighbour->cap))
954     {
955         neighbour = NULL;
956     }
957     if (!neighbour
958         && (neighbour = mdb_successor(dest))
959         && !is_copy(&dest->cap, &neighbour->cap))
960     {
961         neighbour = NULL;
962     }
963
964     if (neighbour) {
965         assert(!neighbour->mdbnode.in_delete);
966         assert(neighbour->mdbnode.owner == owner);
967 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
968         CP_ATTR(locked);
969         CP_ATTR(remote_copies);
970         CP_ATTR(remote_ancs);
971         CP_ATTR(remote_descs);
972 #undef CP_ATTR
973     }
974     else {
975         dest->mdbnode.locked = false;
976         if (owner != my_core_id) {
977             // For foreign caps it does not really matter if ancestors or
978             // descendants exist
979             dest->mdbnode.remote_copies = true;
980             dest->mdbnode.remote_ancs = false;
981             dest->mdbnode.remote_descs = false;
982         }
983         else {
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;
993             }
994             else {
995                 dest->mdbnode.remote_copies = false;
996                 dest->mdbnode.remote_ancs = false;
997                 dest->mdbnode.remote_descs = false;
998             }
999         }
1000     }
1001
1002     TRACE_CAP_MSG("created", dest);
1003
1004     return SYS_ERR_OK;
1005 }
1006
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)
1010 {
1011     /* Parameter checking */
1012     assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1013
1014     size_t numobjs = caps_numobjs(type, bits, objbits);
1015     assert(numobjs > 0);
1016
1017     /* Create the new capabilities */
1018     errval_t err = caps_create(type, addr, bits, objbits, numobjs, owner, caps);
1019     if (err_is_fail(err)) {
1020         return err;
1021     }
1022
1023     // Handle the mapping database
1024     set_init_mapping(caps, numobjs);
1025
1026     TRACE_CAP_MSG("created", &caps[0]);
1027
1028     return SYS_ERR_OK;
1029 }
1030
1031
1032 /// Retype caps
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)
1036 {
1037     size_t numobjs;
1038     uint8_t bits = 0;
1039     genpaddr_t base = 0;
1040     errval_t err;
1041
1042     /* Parameter checking */
1043     assert(type != ObjType_Null);
1044     assert(type < ObjType_Num);
1045
1046     struct capability *src_cap = &src_cte->cap;
1047
1048     TRACE_CAP_MSG("retyping", src_cte);
1049
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");
1054         return err;
1055     }
1056
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;
1062         break;
1063
1064     case ObjType_RAM:
1065         bits = src_cap->u.ram.bits;
1066         base = src_cap->u.ram.base;
1067         break;
1068
1069     case ObjType_Dispatcher:
1070         bits = base = 0;
1071         break;
1072
1073     case ObjType_Frame:
1074         bits = src_cap->u.frame.bits;
1075         base = src_cap->u.frame.base;
1076         break;
1077
1078     case ObjType_DevFrame:
1079         bits = src_cap->u.devframe.bits;
1080         base = src_cap->u.devframe.base;
1081         break;
1082
1083     default:
1084         panic("Unreachable case");
1085     }
1086
1087     /* determine number of objects to be created */
1088     numobjs = caps_numobjs(type, bits, objbits);
1089
1090     if (numobjs == 0) {
1091         debug(SUBSYS_CAPS, "caps_retype: numobjs == 0\n");
1092         return SYS_ERR_INVALID_SIZE_BITS;
1093     }
1094    // debug(SUBSYS_CAPS, "caps_retype: numobjs == %d\n", (int)numobjs);
1095
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;
1100     }
1101
1102     /* check that destination slots are all empty */
1103     debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1104           " dest_slot %d\n",
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
1108             != ObjType_Null) {
1109             debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1110                   (int)(dest_slot + i));
1111             return SYS_ERR_SLOTS_IN_USE;
1112         }
1113     }
1114
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);
1122     }
1123
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;
1130     }
1131
1132     /* Handle mapping */
1133     for (size_t i = 0; i < numobjs; i++) {
1134         mdb_insert(&dest_cte[i]);
1135     }
1136
1137 #ifdef TRACE_PMEM_CAPS
1138     for (size_t i = 0; i < numobjs; i++) {
1139         TRACE_CAP_MSG("created", &dest_cte[i]);
1140     }
1141 #endif
1142
1143     return SYS_ERR_OK;
1144 }
1145
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)
1149 {
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
1161         return SYS_ERR_OK;
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;
1165     } else {
1166         return SYS_ERR_OK;
1167     }
1168 }
1169
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,
1173                             uintptr_t param2)
1174 {
1175     /* Parameter Checking */
1176     assert(dest_cnode_cte->cap.type == ObjType_CNode);
1177
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);
1181
1182 }
1183
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)
1187 {
1188     errval_t err;
1189     /* Parameter checking */
1190     // Null checking
1191     assert(dest_cte != NULL);
1192     assert(src_cte != NULL);
1193
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;
1199     }
1200     // Parameters should be 0 if not minting
1201     if (!mint) {
1202         assert(param1 == 0);
1203         assert(param2 == 0);
1204     }
1205
1206     assert(!src_cte->mdbnode.in_delete);
1207
1208     /* Insert #source_cap into #dest_cap */
1209     err = set_cap(dest_cap, src_cap);
1210     if (err_is_fail(err)) {
1211         return err;
1212     }
1213
1214     /* Transfer MDB attributes that must be equal for all copies */
1215 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1216     CP_ATTR(owner);
1217     CP_ATTR(locked);
1218     CP_ATTR(remote_copies);
1219     CP_ATTR(remote_ancs);
1220     CP_ATTR(remote_descs);
1221 #undef CP_ATTR
1222
1223     /* Copy is done */
1224     if(!mint) {
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);
1230         return SYS_ERR_OK;
1231     }
1232     else {
1233         TRACE_CAP_MSG("minting to", dest_cte);
1234     }
1235
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) {
1240     case ObjType_CNode:
1241         if (param2 > CPTR_BITS) {
1242             return SYS_ERR_GUARD_SIZE_OVERFLOW;
1243         }
1244         dest_cap->u.cnode.guard      = param1;
1245         dest_cap->u.cnode.guard_size = param2;
1246         break;
1247
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
1251         // yet be setup
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;
1258         }*/
1259         if (param2 < LMP_RECV_HEADER_LENGTH) {
1260             return SYS_ERR_INVALID_EPLEN;
1261         }
1262         dest_cap->u.endpoint.epoffset = param1;
1263         dest_cap->u.endpoint.epbuflen = param2;
1264         break;
1265
1266     case ObjType_IO:
1267         if(src_cap->u.io.start  <= param1) {
1268             dest_cap->u.io.start = param1;
1269         }
1270         if(src_cap->u.io.end  >= param2) {
1271             dest_cap->u.io.end = param2;
1272         }
1273         break;
1274
1275     default:
1276         // Unhandled source type for mint
1277         return SYS_ERR_INVALID_SOURCE_TYPE;
1278     }
1279
1280     // Insert after doing minting operation
1281     mdb_insert(dest_cte);
1282
1283     return SYS_ERR_OK;
1284 }