d2f43772e463de3a39ff551ff61d612165b2d2d9
[barrelfish] / kernel / capabilities.c
1 /**
2  * \file
3  * \brief Kernel capability management implementation.
4  */
5
6 /*
7  * Copyright (c) 2007-2012,2015,2016 ETH Zurich.
8  * Copyright (c) 2015, 2016 Hewlett Packard Enterprise Development LP.
9  * All rights reserved.
10  *
11  * This file is distributed under the terms in the attached LICENSE file.
12  * If you do not find this file, copies can be found by writing to:
13  * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
14  */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <kernel.h>
19 #include <barrelfish_kpi/syscalls.h>
20 #include <barrelfish_kpi/paging_arch.h>
21 #include <barrelfish_kpi/lmp.h>
22 #include <offsets.h>
23 #include <capabilities.h>
24 #include <cap_predicates.h>
25 #include <distcaps.h>
26 #include <dispatch.h>
27 #include <kcb.h>
28 #include <paging_kernel_arch.h>
29 #include <mdb/mdb.h>
30 #include <mdb/mdb_tree.h>
31 #include <trace/trace.h>
32 #include <trace_definitions/trace_defs.h>
33 #include <wakeup.h>
34 #include <bitmacros.h>
35
36 // XXX: remove
37 #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
38
39 #ifdef TRACE_PMEM_CAPS
40 uint64_t   trace_types_enabled = TRACE_TYPES_ENABLED_INITIAL;
41 genpaddr_t TRACE_PMEM_BEGIN    = TRACE_PMEM_BEGIN_INITIAL;
42 gensize_t  TRACE_PMEM_SIZE     = TRACE_PMEM_SIZE_INITIAL;
43
44 void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
45 {
46     if (types) {
47         trace_types_enabled = types;
48         TRACE_PMEM_BEGIN = start;
49         TRACE_PMEM_SIZE = size;
50     } else {
51         trace_types_enabled = 0;
52     }
53 }
54 #endif
55
56 struct capability monitor_ep;
57
58 STATIC_ASSERT(49 == ObjType_Num, "Knowledge of all cap types");
59 int sprint_cap(char *buf, size_t len, struct capability *cap)
60 {
61     switch (cap->type) {
62     case ObjType_PhysAddr:
63         return snprintf(buf, len,
64                         "physical address range cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
65                         cap->u.physaddr.base, cap->u.physaddr.bytes);
66
67     case ObjType_RAM:
68         return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
69                         cap->u.ram.base, cap->u.ram.bytes);
70
71     case ObjType_L1CNode: {
72         int ret = snprintf(buf, len, "L1 CNode cap "
73                            "(base=%#"PRIxGENPADDR", allocated bytes %#"PRIxGENSIZE
74                            ", rights mask %#"PRIxCAPRIGHTS")",
75                            get_address(cap), get_size(cap),
76                            cap->u.l1cnode.rightsmask);
77         return ret;
78     }
79
80     case ObjType_L2CNode: {
81         int ret = snprintf(buf, len, "L2 CNode cap "
82                            "(base=%#"PRIxGENPADDR", rights mask %#"PRIxCAPRIGHTS")",
83                            get_address(cap), cap->u.l1cnode.rightsmask);
84         return ret;
85     }
86
87     case ObjType_Dispatcher:
88         return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
89
90     case ObjType_Frame:
91         return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
92                         cap->u.frame.base, cap->u.frame.bytes);
93
94     case ObjType_DevFrame:
95         return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":0x%" PRIxGENSIZE ")",
96                         cap->u.frame.base, cap->u.devframe.bytes);
97
98     case ObjType_VNode_ARM_l1:
99         return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
100                         cap->u.vnode_arm_l1.base);
101
102     case ObjType_VNode_ARM_l2:
103         return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
104                         cap->u.vnode_arm_l2.base);
105
106     case ObjType_VNode_AARCH64_l0:
107         return snprintf(buf, len, "AARCH64 L0 table at 0x%" PRIxGENPADDR,
108                         cap->u.vnode_aarch64_l0.base);
109
110     case ObjType_VNode_AARCH64_l1:
111         return snprintf(buf, len, "AARCH64 L1 table at 0x%" PRIxGENPADDR,
112                         cap->u.vnode_aarch64_l1.base);
113
114     case ObjType_VNode_AARCH64_l2:
115         return snprintf(buf, len, "AARCH64 L2 table at 0x%" PRIxGENPADDR,
116                         cap->u.vnode_aarch64_l2.base);
117
118     case ObjType_VNode_AARCH64_l3:
119         return snprintf(buf, len, "AARCH64 L3 table at 0x%" PRIxGENPADDR,
120                         cap->u.vnode_aarch64_l3.base);
121
122     case ObjType_VNode_x86_32_ptable:
123         return snprintf(buf, len, "x86_32 Page table at 0x%" PRIxGENPADDR,
124                         cap->u.vnode_x86_32_ptable.base);
125
126     case ObjType_VNode_x86_32_pdir:
127         return snprintf(buf, len, "x86_32 Page directory at 0x%" PRIxGENPADDR,
128                         cap->u.vnode_x86_32_pdir.base);
129
130     case ObjType_VNode_x86_32_pdpt:
131         return snprintf(buf, len, "x86_32 PDPT at 0x%" PRIxGENPADDR,
132                         cap->u.vnode_x86_32_pdpt.base);
133
134     case ObjType_VNode_x86_64_ptable:
135         return snprintf(buf, len, "x86_64 Page table at 0x%" PRIxGENPADDR,
136                         cap->u.vnode_x86_64_ptable.base);
137
138     case ObjType_VNode_x86_64_pdir:
139         return snprintf(buf, len, "x86_64 Page directory at 0x%" PRIxGENPADDR,
140                         cap->u.vnode_x86_64_pdir.base);
141
142     case ObjType_VNode_x86_64_pdpt:
143         return snprintf(buf, len, "x86_64 PDPT at 0x%" PRIxGENPADDR,
144                         cap->u.vnode_x86_64_pdpt.base);
145
146     case ObjType_VNode_x86_64_pml4:
147         return snprintf(buf, len, "x86_64 PML4 at 0x%" PRIxGENPADDR,
148                         cap->u.vnode_x86_64_pml4.base);
149
150     case ObjType_Frame_Mapping:
151         return snprintf(buf, len, "Frame Mapping (Frame cap @%p, "
152                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
153                                   cap->u.frame_mapping.frame,
154                                   cap->u.frame_mapping.pte,
155                                   cap->u.frame_mapping.pte_count);
156
157     case ObjType_DevFrame_Mapping:
158         return snprintf(buf, len, "DevFrame Mapping (DevFrame cap @%p, "
159                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
160                                   cap->u.devframe_mapping.frame,
161                                   cap->u.devframe_mapping.pte,
162                                   cap->u.devframe_mapping.pte_count);
163
164     case ObjType_VNode_x86_64_pml4_Mapping:
165         return snprintf(buf, len, "x86_64 PML4 Mapping (x86_64 PML4 cap @%p, "
166                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
167                                   cap->u.vnode_x86_64_pml4_mapping.frame,
168                                   cap->u.vnode_x86_64_pml4_mapping.pte,
169                                   cap->u.vnode_x86_64_pml4_mapping.pte_count);
170
171     case ObjType_VNode_x86_64_pdpt_Mapping:
172         return snprintf(buf, len, "x86_64 PDPT Mapping (x86_64 PDPT cap @%p, "
173                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
174                                   cap->u.vnode_x86_64_pdpt_mapping.frame,
175                                   cap->u.vnode_x86_64_pdpt_mapping.pte,
176                                   cap->u.vnode_x86_64_pdpt_mapping.pte_count);
177
178     case ObjType_VNode_x86_64_pdir_Mapping:
179         return snprintf(buf, len, "x86_64 PDIR Mapping (x86_64 PDIR cap @%p, "
180                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
181                                   cap->u.vnode_x86_64_pdir_mapping.frame,
182                                   cap->u.vnode_x86_64_pdir_mapping.pte,
183                                   cap->u.vnode_x86_64_pdir_mapping.pte_count);
184
185     case ObjType_VNode_x86_64_ptable_Mapping:
186         return snprintf(buf, len, "x86_64 PTABLE Mapping (x86_64 PTABLE cap @%p, "
187                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
188                                   cap->u.vnode_x86_64_ptable_mapping.frame,
189                                   cap->u.vnode_x86_64_ptable_mapping.pte,
190                                   cap->u.vnode_x86_64_ptable_mapping.pte_count);
191
192     case ObjType_VNode_x86_32_pdpt_Mapping:
193         return snprintf(buf, len, "x86_32 PDPT Mapping (x86_32 PDPT cap @%p, "
194                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
195                                   cap->u.vnode_x86_32_pdpt_mapping.frame,
196                                   cap->u.vnode_x86_32_pdpt_mapping.pte,
197                                   cap->u.vnode_x86_32_pdpt_mapping.pte_count);
198
199     case ObjType_VNode_x86_32_pdir_Mapping:
200         return snprintf(buf, len, "x86_32 PDIR Mapping (x86_32 PDIR cap @%p, "
201                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
202                                   cap->u.vnode_x86_32_pdir_mapping.frame,
203                                   cap->u.vnode_x86_32_pdir_mapping.pte,
204                                   cap->u.vnode_x86_32_pdir_mapping.pte_count);
205
206     case ObjType_VNode_x86_32_ptable_Mapping:
207         return snprintf(buf, len, "x86_32 PTABLE Mapping (x86_32 PTABLE cap @%p, "
208                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
209                                   cap->u.vnode_x86_32_ptable_mapping.frame,
210                                   cap->u.vnode_x86_32_ptable_mapping.pte,
211                                   cap->u.vnode_x86_32_ptable_mapping.pte_count);
212
213     case ObjType_VNode_ARM_l1_Mapping:
214         return snprintf(buf, len, "ARM l1 Mapping (ARM l1 cap @%p, "
215                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
216                                   cap->u.vnode_arm_l1_mapping.frame,
217                                   cap->u.vnode_arm_l1_mapping.pte,
218                                   cap->u.vnode_arm_l1_mapping.pte_count);
219
220     case ObjType_VNode_ARM_l2_Mapping:
221         return snprintf(buf, len, "ARM l2 Mapping (ARM l2 cap @%p, "
222                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
223                                   cap->u.vnode_arm_l2_mapping.frame,
224                                   cap->u.vnode_arm_l2_mapping.pte,
225                                   cap->u.vnode_arm_l2_mapping.pte_count);
226
227     case ObjType_VNode_AARCH64_l0_Mapping:
228         return snprintf(buf, len, "AARCH64 l0 Mapping (AARCH64 l0 cap @%p, "
229                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
230                                   cap->u.vnode_aarch64_l0_mapping.frame,
231                                   cap->u.vnode_aarch64_l0_mapping.pte,
232                                   cap->u.vnode_aarch64_l0_mapping.pte_count);
233
234     case ObjType_VNode_AARCH64_l1_Mapping:
235         return snprintf(buf, len, "AARCH64 l1 Mapping (AARCH64 l1 cap @%p, "
236                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
237                                   cap->u.vnode_aarch64_l1_mapping.frame,
238                                   cap->u.vnode_aarch64_l1_mapping.pte,
239                                   cap->u.vnode_aarch64_l1_mapping.pte_count);
240
241     case ObjType_VNode_AARCH64_l2_Mapping:
242         return snprintf(buf, len, "AARCH64 l2 Mapping (AARCH64 l2 cap @%p, "
243                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
244                                   cap->u.vnode_aarch64_l2_mapping.frame,
245                                   cap->u.vnode_aarch64_l2_mapping.pte,
246                                   cap->u.vnode_aarch64_l2_mapping.pte_count);
247
248     case ObjType_VNode_AARCH64_l3_Mapping:
249         return snprintf(buf, len, "AARCH64 l3 Mapping (AARCH64 l3 cap @%p, "
250                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
251                                   cap->u.vnode_aarch64_l3_mapping.frame,
252                                   cap->u.vnode_aarch64_l3_mapping.pte,
253                                   cap->u.vnode_aarch64_l3_mapping.pte_count);
254
255     case ObjType_IRQTable:
256         return snprintf(buf, len, "IRQTable cap");
257
258     case ObjType_IRQDest:
259         return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", cpu: %"PRIu64")",
260                 cap->u.irqdest.vector, cap->u.irqdest.cpu);
261
262     case ObjType_EndPoint:
263         return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
264                         cap->u.endpoint.listener, cap->u.endpoint.epoffset);
265
266     case ObjType_IO:
267         return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
268                         cap->u.io.start, cap->u.io.end);
269
270     case ObjType_Kernel:
271         return snprintf(buf, len, "Kernel cap");
272
273     case ObjType_KernelControlBlock:
274         return snprintf(buf, len, "Kernel control block");
275
276     case ObjType_ID:
277         return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
278                         " core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
279                         cap->u.id.core_local_id);
280
281     case ObjType_PerfMon:
282         return snprintf(buf, len, "PerfMon cap");
283
284     case ObjType_Null:
285         return snprintf(buf, len, "Null capability (empty slot)");
286
287     case ObjType_IPI:
288         return snprintf(buf, len, "IPI cap");
289
290     default:
291         return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
292     }
293 }
294
295 void caps_trace(const char *func, int line, struct cte *cte, const char *msg)
296 {
297     char cap_buf[512];
298     sprint_cap(cap_buf, 512, &cte->cap);
299
300     char disp_buf[64];
301     if (dcb_current) {
302         dispatcher_handle_t handle = dcb_current->disp;
303         struct dispatcher_shared_generic *disp =
304             get_dispatcher_shared_generic(handle);
305         snprintf(disp_buf, 64, "from %.*s", DISP_NAME_LEN, disp->name);
306     }
307     else {
308         strcpy(disp_buf, "no disp");
309     }
310
311     printk(LOG_WARN, "%s: %s:%d: %s %p %s"
312            " (owner:%" PRIuCOREID ", rc:%d/ra:%d/rd:%d)\n",
313            disp_buf, func, line, (msg ? : ""), cte, cap_buf, cte->mdbnode.owner,
314            cte->mdbnode.remote_copies, cte->mdbnode.remote_ancs,
315            cte->mdbnode.remote_descs);
316 }
317
318 /**
319  * ID capability core_local_id counter.
320  */
321 static uint32_t id_cap_counter = 1;
322
323 /**
324  *  Sets #dest equal to #src
325  *
326  * #dest cannot be in use.
327  */
328 static errval_t set_cap(struct capability *dest, struct capability *src)
329 {
330     /* Parameter checking */
331     assert(src  != NULL);
332     assert(dest != NULL);
333
334     debug(SUBSYS_CAPS, "Copying cap from %#"PRIxLPADDR" to %#"PRIxLPADDR"\n",
335             mem_to_local_phys((lvaddr_t)cte_for_cap(src)),
336             mem_to_local_phys((lvaddr_t)cte_for_cap(dest)));
337
338     // Reserved object bits must always be greater/equal to actual object size
339     assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
340
341     // Cannot overwrite an already existing cap
342     if (dest->type != ObjType_Null) {
343         return SYS_ERR_SLOT_IN_USE;
344     }
345
346     memcpy(dest, src, sizeof(struct capability));
347     return SYS_ERR_OK;
348 }
349
350 /**
351  * \brief Determine how many objects can be created in a specified region.
352  *
353  * This function computes the number of objects that can be created by a call
354  * to caps_create().
355  *
356  * \param type          Type of objects to create.
357  * \param srcsize       Size of memory area in bytes
358  * \param objsize       For variable-sized objects, size multiplier
359  *
360  * \return Number of objects to be created, or zero on error
361  */
362
363 // If you create more capability types you need to deal with them
364 // in the table below.
365 STATIC_ASSERT(49 == ObjType_Num, "Knowledge of all cap types");
366 static size_t caps_max_numobjs(enum objtype type, gensize_t srcsize, gensize_t objsize)
367 {
368     switch(type) {
369     case ObjType_PhysAddr:
370     case ObjType_RAM:
371     case ObjType_Frame:
372     case ObjType_DevFrame:
373         if (objsize > srcsize) {
374             return 0;
375         } else {
376             return srcsize / objsize;
377         }
378
379     case ObjType_L1CNode:
380         if (srcsize < OBJSIZE_L2CNODE || objsize < OBJSIZE_L2CNODE) {
381             // disallow L1 CNode to be smaller than 16kB.
382             return 0;
383         } else {
384             return srcsize / objsize;
385         }
386
387     case ObjType_L2CNode:
388         if (srcsize < OBJSIZE_L2CNODE || objsize != OBJSIZE_L2CNODE) {
389             // disallow L2 CNode creation if source too small or objsize wrong
390             return 0;
391         } else {
392             return srcsize / objsize;
393         }
394
395
396     case ObjType_VNode_x86_64_pml4:
397     case ObjType_VNode_x86_64_pdpt:
398     case ObjType_VNode_x86_64_pdir:
399     case ObjType_VNode_x86_64_ptable:
400     case ObjType_VNode_x86_32_pdpt:
401     case ObjType_VNode_x86_32_pdir:
402     case ObjType_VNode_x86_32_ptable:
403     case ObjType_VNode_ARM_l1:
404     case ObjType_VNode_ARM_l2:
405     case ObjType_VNode_AARCH64_l0:
406     case ObjType_VNode_AARCH64_l1:
407     case ObjType_VNode_AARCH64_l2:
408     case ObjType_VNode_AARCH64_l3:
409     {
410         if (srcsize < vnode_objsize(type)) {
411             return 0;
412         } else {
413             return srcsize / vnode_objsize(type);
414         }
415     }
416
417     case ObjType_Dispatcher:
418         if (srcsize < 1UL << OBJBITS_DISPATCHER) {
419             return 0;
420         } else {
421             return srcsize / (1UL << OBJBITS_DISPATCHER);
422         }
423
424     case ObjType_KernelControlBlock:
425         if (srcsize < 1UL << OBJBITS_KCB) {
426             return 0;
427         } else {
428             return srcsize / (1UL << OBJBITS_KCB);
429         }
430
431     case ObjType_Kernel:
432     case ObjType_IRQTable:
433     case ObjType_IRQDest:
434     case ObjType_IRQSrc:
435     case ObjType_IO:
436     case ObjType_EndPoint:
437     case ObjType_ID:
438     case ObjType_Notify_RCK:
439     case ObjType_Notify_IPI:
440     case ObjType_PerfMon:
441     case ObjType_IPI:
442     case ObjType_VNode_ARM_l1_Mapping:
443     case ObjType_VNode_ARM_l2_Mapping:
444     case ObjType_VNode_AARCH64_l0_Mapping:
445     case ObjType_VNode_AARCH64_l1_Mapping:
446     case ObjType_VNode_AARCH64_l2_Mapping:
447     case ObjType_VNode_AARCH64_l3_Mapping:
448     case ObjType_VNode_x86_64_pml4_Mapping:
449     case ObjType_VNode_x86_64_pdpt_Mapping:
450     case ObjType_VNode_x86_64_pdir_Mapping:
451     case ObjType_VNode_x86_64_ptable_Mapping:
452     case ObjType_VNode_x86_32_pdpt_Mapping:
453     case ObjType_VNode_x86_32_pdir_Mapping:
454     case ObjType_VNode_x86_32_ptable_Mapping:
455     case ObjType_DevFrame_Mapping:
456     case ObjType_Frame_Mapping:
457         return 1;
458
459     default:
460         panic("invalid type");
461         return 0;
462     }
463 }
464
465 /**
466  * \brief Initialize the objects for which local caps are about to be created.
467  *
468  * For the meaning of the parameters, see the 'caps_create' function.
469  */
470 STATIC_ASSERT(49 == ObjType_Num, "Knowledge of all cap types");
471
472 static errval_t caps_zero_objects(enum objtype type, lpaddr_t lpaddr,
473                                   gensize_t objsize, size_t count)
474 {
475     assert(type < ObjType_Num);
476
477     // Virtual address of the memory the kernel object resides in
478     // XXX: A better of doing this,
479     // this is creating caps that the kernel cannot address.
480     // It assumes that the cap is not of the type which will have to zeroed out.
481     lvaddr_t lvaddr;
482     if(lpaddr < PADDR_SPACE_LIMIT) {
483         lvaddr = local_phys_to_mem(lpaddr);
484     } else {
485         lvaddr = 0;
486     }
487
488     switch (type) {
489
490     case ObjType_Frame:
491         debug(SUBSYS_CAPS, "Frame: zeroing %zu bytes @%#"PRIxLPADDR"\n",
492                 (size_t)objsize * count, lpaddr);
493         TRACE(KERNEL, BZERO, 1);
494         memset((void*)lvaddr, 0, objsize * count);
495         TRACE(KERNEL, BZERO, 0);
496         break;
497
498     case ObjType_L1CNode:
499     case ObjType_L2CNode:
500         debug(SUBSYS_CAPS, "L%dCNode: zeroing %zu bytes @%#"PRIxLPADDR"\n",
501                 type == ObjType_L1CNode ? 1 : 2, (size_t)objsize * count,
502                 lpaddr);
503         TRACE(KERNEL, BZERO, 1);
504         memset((void*)lvaddr, 0, objsize * count);
505         TRACE(KERNEL, BZERO, 0);
506         break;
507
508     case ObjType_VNode_ARM_l1:
509     case ObjType_VNode_ARM_l2:
510     case ObjType_VNode_AARCH64_l0:
511     case ObjType_VNode_AARCH64_l1:
512     case ObjType_VNode_AARCH64_l2:
513     case ObjType_VNode_AARCH64_l3:
514     case ObjType_VNode_x86_32_ptable:
515     case ObjType_VNode_x86_32_pdir:
516     case ObjType_VNode_x86_32_pdpt:
517     case ObjType_VNode_x86_64_ptable:
518     case ObjType_VNode_x86_64_pdir:
519     case ObjType_VNode_x86_64_pdpt:
520     case ObjType_VNode_x86_64_pml4:
521         // objsize is size of VNode; but not given as such
522         objsize = vnode_objsize(type);
523         debug(SUBSYS_CAPS, "VNode: zeroing %zu bytes @%#"PRIxLPADDR"\n",
524                 (size_t)objsize * count, lpaddr);
525         TRACE(KERNEL, BZERO, 1);
526         memset((void*)lvaddr, 0, objsize * count);
527         TRACE(KERNEL, BZERO, 0);
528         break;
529
530     case ObjType_Dispatcher:
531         debug(SUBSYS_CAPS, "Dispatcher: zeroing %zu bytes @%#"PRIxLPADDR"\n",
532                 ((size_t)1 << OBJBITS_DISPATCHER) * count, lpaddr);
533         TRACE(KERNEL, BZERO, 1);
534         memset((void*)lvaddr, 0, (1UL << OBJBITS_DISPATCHER) * count);
535         TRACE(KERNEL, BZERO, 0);
536         break;
537
538     case ObjType_KernelControlBlock:
539         debug(SUBSYS_CAPS, "KCB: zeroing %zu bytes @%#"PRIxLPADDR"\n",
540                 ((size_t)1 << OBJBITS_KCB) * count, lpaddr);
541         TRACE(KERNEL, BZERO, 1);
542         memset((void*)lvaddr, 0, (1UL << OBJBITS_KCB) * count);
543         TRACE(KERNEL, BZERO, 0);
544         break;
545
546     default:
547         debug(SUBSYS_CAPS, "Not zeroing %zu bytes @%#"PRIxLPADDR" for type %d\n",
548                 (size_t)objsize * count, lpaddr, (int)type);
549         break;
550
551     }
552
553     return SYS_ERR_OK;
554 }
555
556 /**
557  * \brief Create capabilities to kernel objects.
558  *
559  * This function creates 'count' kernel objects of 'type' into the memory
560  * area, based at 'addr' and of size 'objsize'. For each created kernel
561  * object, a capability is created to it and put consecutively into the array
562  * of CTEs pointed to by 'caps'. The array needs to have the appropriate size
563  * to hold all created caps. Some kernel objects can have a variable size. In
564  * that case, 'objsize' should be non-zero. and give the size multiplier. *
565  *
566  * \param type          Type of objects to create.
567  * \param lpaddr        Base address in the local address space.
568  * \param size          Size of memory area as bytes.
569  * \param objsize       For variable-sized objects, size in bytes.
570  * \param count         Number of objects to be created
571  *                      (count <= caps_max_numobjs(type, size, objsize))
572  * \param dest_caps     Pointer to array of CTEs to hold created caps.
573  *
574  * \return Error code
575  */
576 // If you create more capability types you need to deal with them
577 // in the table below.
578 STATIC_ASSERT(49 == ObjType_Num, "Knowledge of all cap types");
579
580 static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, gensize_t size,
581                             gensize_t objsize, size_t count, coreid_t owner,
582                             struct cte *dest_caps)
583 {
584     errval_t err;
585
586     /* Parameter checking */
587     assert(dest_caps != NULL);
588     assert(type != ObjType_Null);
589     assert(type < ObjType_Num);
590     assert(count > 0);
591     // objsize is 0 for non-sized types (e.g. VNodes)
592     // TODO cleanup semantics for type == CNode
593     //assert(objsize % BASE_PAGE_SIZE == 0);
594     assert(!type_is_mapping(type));
595
596     genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
597
598     debug(SUBSYS_CAPS, "creating caps for %#"PRIxGENPADDR
599                        ", %" PRIuGENSIZE " bytes, objsize=%"PRIuGENSIZE
600                        ", count=%zu, owner=%d, type=%d\n",
601             genpaddr, size, objsize, count, (int)owner, (int)type);
602
603     // Virtual address of the memory the kernel object resides in
604     // XXX: A better of doing this,
605     // this is creating caps that the kernel cannot address.
606     // It assumes that the cap is not of the type which will have to zeroed out.
607     lvaddr_t lvaddr;
608     if(lpaddr < PADDR_SPACE_LIMIT) {
609         lvaddr = local_phys_to_mem(lpaddr);
610     } else {
611         lvaddr = 0;
612     }
613
614     /* Initialize the created capability */
615     struct capability temp_cap;
616     memset(&temp_cap, 0, sizeof(struct capability));
617     temp_cap.type = type;
618     // XXX: Handle rights!
619     temp_cap.rights = CAPRIGHTS_ALLRIGHTS;
620
621     debug(SUBSYS_CAPS, "owner = %d, my_core_id = %d\n", owner, my_core_id);
622     if (owner == my_core_id) {
623         // If we're creating new local objects, they need to be cleared
624         err = caps_zero_objects(type, lpaddr, objsize, count);
625         if (err_is_fail(err)) {
626             return err;
627         }
628     }
629
630     size_t dest_i = 0;
631     err = SYS_ERR_OK;
632
633     /* Set the type specific fields and insert into #dest_caps */
634     switch(type) {
635     case ObjType_Frame:
636         for(dest_i = 0; dest_i < count; dest_i++) {
637             // Initialize type specific fields
638             temp_cap.u.frame.base = genpaddr + dest_i * objsize;
639             temp_cap.u.frame.bytes = objsize;
640             assert((get_size(&temp_cap) & BASE_PAGE_MASK) == 0);
641             // Insert the capability
642             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
643             if (err_is_fail(err)) {
644                 break;
645             }
646         }
647         break;
648
649     case ObjType_PhysAddr:
650         for(dest_i = 0; dest_i < count; dest_i++) {
651             // Initialize type specific fields
652             temp_cap.u.physaddr.base = genpaddr + dest_i * objsize;
653             temp_cap.u.physaddr.bytes = objsize;
654             // Insert the capability
655             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
656             if (err_is_fail(err)) {
657                 break;
658             }
659         }
660         break;
661
662     case ObjType_RAM:
663         for(dest_i = 0; dest_i < count; dest_i++) {
664             // Initialize type specific fields
665             temp_cap.u.ram.base = genpaddr + dest_i * objsize;
666             temp_cap.u.ram.bytes = objsize;
667             // Insert the capabilities
668             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
669             if (err_is_fail(err)) {
670                 break;
671             }
672         }
673         break;
674
675     case ObjType_DevFrame:
676         for(dest_i = 0; dest_i < count; dest_i++) {
677             // Initialize type specific fields
678             temp_cap.u.devframe.base = genpaddr + dest_i * objsize;
679             temp_cap.u.devframe.bytes = objsize;
680             // Insert the capabilities
681             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
682             if (err_is_fail(err)) {
683                 break;
684             }
685         }
686         break;
687
688     case ObjType_L1CNode:
689         for (dest_i = 0; dest_i < count; dest_i++) {
690             assert(objsize >= OBJSIZE_L2CNODE);
691             assert(objsize % OBJSIZE_L2CNODE == 0);
692             temp_cap.u.l1cnode.cnode = lpaddr + dest_i * objsize;
693             temp_cap.u.l1cnode.allocated_bytes = objsize;
694             // XXX: implement CNode cap rights
695             temp_cap.u.l1cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
696             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
697             if (err_is_fail(err)) {
698                 break;
699             }
700         }
701         break;
702
703     case ObjType_L2CNode:
704         for (dest_i = 0; dest_i < count; dest_i++) {
705             temp_cap.u.l2cnode.cnode = lpaddr + dest_i * objsize;
706             // XXX: implement CNode cap rights
707             temp_cap.u.l2cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
708             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
709             if (err_is_fail(err)) {
710                 break;
711             }
712         }
713         break;
714
715     case ObjType_VNode_ARM_l1:
716     {
717         size_t objsize_vnode = vnode_objsize(type);
718
719         for(dest_i = 0; dest_i < count; dest_i++) {
720             // Initialize type specific fields
721             temp_cap.u.vnode_arm_l1.base =
722                 genpaddr + dest_i * objsize_vnode;
723
724
725             // Insert the capability
726             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
727             if (err_is_fail(err)) {
728                 break;
729             }
730         }
731
732         break;
733     }
734
735     case ObjType_VNode_ARM_l2:
736     {
737         size_t objsize_vnode = vnode_objsize(type);
738
739         for(dest_i = 0; dest_i < count; dest_i++) {
740             // Initialize type specific fields
741             temp_cap.u.vnode_arm_l2.base =
742                 genpaddr + dest_i * objsize_vnode;
743
744             // Insert the capability
745             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
746             if (err_is_fail(err)) {
747                 break;
748             }
749         }
750         break;
751     }
752
753     case ObjType_VNode_AARCH64_l0:
754     {
755         size_t objsize_vnode = vnode_objsize(type);
756
757         for(dest_i = 0; dest_i < count; dest_i++) {
758             // Initialize type specific fields
759             temp_cap.u.vnode_aarch64_l0.base =
760                 genpaddr + dest_i * objsize_vnode;
761
762             // Insert the capability
763             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
764             if (err_is_fail(err)) {
765                 break;
766             }
767         }
768
769         break;
770     }
771
772     case ObjType_VNode_AARCH64_l1:
773     {
774         size_t objsize_vnode = vnode_objsize(type);
775
776         for(dest_i = 0; dest_i < count; dest_i++) {
777             // Initialize type specific fields
778             temp_cap.u.vnode_aarch64_l1.base =
779                 genpaddr + dest_i * objsize_vnode;
780
781             // Insert the capability
782             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
783             if (err_is_fail(err)) {
784                 break;
785             }
786         }
787
788         break;
789     }
790
791     case ObjType_VNode_AARCH64_l2:
792     {
793         size_t objsize_vnode = vnode_objsize(type);
794
795         for(dest_i = 0; dest_i < count; dest_i++) {
796             // Initialize type specific fields
797             temp_cap.u.vnode_aarch64_l2.base =
798                 genpaddr + dest_i * objsize_vnode;
799
800             // Insert the capability
801             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
802
803             if (err_is_fail(err)) {
804                 break;
805             }
806         }
807         break;
808     }
809
810     case ObjType_VNode_AARCH64_l3:
811     {
812         size_t objsize_vnode = vnode_objsize(type);
813
814         for(dest_i = 0; dest_i < count; dest_i++) {
815             // Initialize type specific fields
816             temp_cap.u.vnode_aarch64_l3.base =
817                 genpaddr + dest_i * objsize_vnode;
818
819             // Insert the capability
820             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
821             if (err_is_fail(err)) {
822                 break;
823             }
824         }
825         break;
826     }
827
828     case ObjType_VNode_x86_32_ptable:
829     {
830         size_t objsize_vnode = vnode_objsize(type);
831
832         for(dest_i = 0; dest_i < count; dest_i++) {
833             // Initialize type specific fields
834             temp_cap.u.vnode_x86_32_ptable.base =
835                 genpaddr + dest_i * objsize_vnode;
836
837             // Insert the capability
838             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
839             if (err_is_fail(err)) {
840                 break;
841             }
842         }
843         break;
844     }
845
846     case ObjType_VNode_x86_32_pdir:
847     {
848         size_t objsize_vnode = vnode_objsize(type);
849
850         for(dest_i = 0; dest_i < count; dest_i++) {
851             // Initialize type specific fields
852             temp_cap.u.vnode_x86_32_pdir.base =
853                 genpaddr + dest_i * objsize_vnode;
854
855 #if defined(__i386__) && !defined(CONFIG_PAE)
856             // Make it a good PDE by inserting kernel/mem VSpaces
857             lpaddr = gen_phys_to_local_phys(temp_cap.u.vnode_x86_32_pdir.base);
858             paging_x86_32_make_good_pdir(lpaddr);
859 #endif
860
861             // Insert the capability
862             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
863             if (err_is_fail(err)) {
864                 break;
865             }
866         }
867         break;
868     }
869
870     case ObjType_VNode_x86_32_pdpt:
871     {
872         size_t objsize_vnode = vnode_objsize(type);
873
874         for(dest_i = 0; dest_i < count; dest_i++) {
875             // Initialize type specific fields
876             temp_cap.u.vnode_x86_32_pdir.base =
877                 genpaddr + dest_i * objsize_vnode;
878
879 #if defined(__i386__) && defined(CONFIG_PAE)
880             // Make it a good PDPTE by inserting kernel/mem VSpaces
881             lpaddr_t var =
882                 gen_phys_to_local_phys(temp_cap.u.vnode_x86_32_pdpt.base);
883             paging_x86_32_make_good_pdpte(var);
884 #endif
885
886             // Insert the capability
887             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
888             if (err_is_fail(err)) {
889                 break;
890             }
891         }
892         break;
893     }
894
895     case ObjType_VNode_x86_64_ptable:
896     {
897         size_t objsize_vnode = vnode_objsize(type);
898
899         for(dest_i = 0; dest_i < count; dest_i++) {
900             // Initialize type specific fields
901             temp_cap.u.vnode_x86_64_ptable.base =
902                 genpaddr + dest_i * objsize_vnode;
903
904             // Insert the capability
905             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
906             if (err_is_fail(err)) {
907                 break;
908             }
909         }
910         break;
911     }
912
913     case ObjType_VNode_x86_64_pdir:
914     {
915         size_t objsize_vnode = vnode_objsize(type);
916
917         for(dest_i = 0; dest_i < count; dest_i++) {
918             // Initialize type specific fields
919             temp_cap.u.vnode_x86_64_pdir.base =
920                 genpaddr + dest_i * objsize_vnode;
921
922             // Insert the capability
923             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
924             if (err_is_fail(err)) {
925                 break;
926             }
927         }
928         break;
929     }
930
931     case ObjType_VNode_x86_64_pdpt:
932     {
933         size_t objsize_vnode = vnode_objsize(type);
934
935         for(dest_i = 0; dest_i < count; dest_i++) {
936             // Initialize type specific fields
937             temp_cap.u.vnode_x86_64_pdpt.base =
938                 genpaddr + dest_i * objsize_vnode;
939
940             // Insert the capability
941             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
942             if (err_is_fail(err)) {
943                 break;
944             }
945         }
946         break;
947     }
948
949     case ObjType_VNode_x86_64_pml4:
950     {
951         size_t objsize_vnode = vnode_objsize(type);
952
953         for(dest_i = 0; dest_i < count; dest_i++) {
954             // Initialize type specific fields
955             temp_cap.u.vnode_x86_64_pml4.base =
956                 genpaddr + dest_i * objsize_vnode;
957
958 #if defined(__x86_64__) || defined(__k1om__)
959             // Make it a good PML4 by inserting kernel/mem VSpaces
960             lpaddr_t var = gen_phys_to_local_phys(get_address(&temp_cap));
961             paging_x86_64_make_good_pml4(var);
962 #endif
963
964             // Insert the capability
965             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
966             if (err_is_fail(err)) {
967                 break;
968             }
969         }
970
971         break;
972     }
973
974     case ObjType_Dispatcher:
975         assert((1UL << OBJBITS_DISPATCHER) >= sizeof(struct dcb));
976
977         for(dest_i = 0; dest_i < count; dest_i++) {
978             // Initialize type specific fields
979             temp_cap.u.dispatcher.dcb = (struct dcb *)
980                 (lvaddr + dest_i * (1UL << OBJBITS_DISPATCHER));
981             // Insert the capability
982             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
983             if (err_is_fail(err)) {
984                 break;
985             }
986         }
987         break;
988
989     case ObjType_ID:
990         // ID type does not refer to a kernel object
991         assert(lpaddr  == 0);
992         assert(size    == 0);
993         assert(objsize == 0);
994         assert(count   == 1);
995
996         // Prevent wrap around
997         if (id_cap_counter >= UINT32_MAX) {
998             return SYS_ERR_ID_SPACE_EXHAUSTED;
999         }
1000
1001         // Generate a new ID, core_local_id monotonically increases
1002         temp_cap.u.id.coreid = my_core_id;
1003         temp_cap.u.id.core_local_id = id_cap_counter++;
1004
1005         // Insert the capability
1006         err = set_cap(&dest_caps->cap, &temp_cap);
1007         break;
1008
1009     case ObjType_IO:
1010         temp_cap.u.io.start = 0;
1011         temp_cap.u.io.end   = 65535;
1012         /* fall through */
1013
1014     case ObjType_Kernel:
1015     case ObjType_IPI:
1016     case ObjType_IRQTable:
1017     case ObjType_IRQDest:
1018     case ObjType_IRQSrc:
1019     case ObjType_EndPoint:
1020     case ObjType_Notify_RCK:
1021     case ObjType_Notify_IPI:
1022     case ObjType_PerfMon:
1023         // These types do not refer to a kernel object
1024         assert(lpaddr  == 0);
1025         assert(size    == 0);
1026         assert(objsize == 0);
1027         assert(count   == 1);
1028
1029         // Insert the capability
1030         err = set_cap(&dest_caps->cap, &temp_cap);
1031         if (err_is_ok(err)) {
1032             dest_i = 1;
1033         }
1034         break;
1035
1036     case ObjType_KernelControlBlock:
1037         assert((1UL << OBJBITS_KCB) >= sizeof(struct kcb));
1038
1039         for(size_t i = 0; i < count; i++) {
1040             // Initialize type specific fields
1041             temp_cap.u.kernelcontrolblock.kcb = (struct kcb *)
1042                 (lvaddr + i * (1UL << OBJBITS_KCB));
1043             // Insert the capability
1044             err = set_cap(&dest_caps[i].cap, &temp_cap);
1045             if (err_is_fail(err)) {
1046                 return err;
1047             }
1048         }
1049         return SYS_ERR_OK;
1050
1051     default:
1052         panic("Unhandled capability type or capability of this type cannot"
1053               " be created");
1054     }
1055
1056     if (err_is_fail(err)) {
1057         // Revert the partially initialized caps to zero
1058         for (size_t i = 0; i < dest_i; i++) {
1059             memset(&dest_caps[i], 0, sizeof(dest_caps[i]));
1060         }
1061         return err;
1062     }
1063     else {
1064         // Set the owner for all the new caps
1065         for (size_t i = 0; i < dest_i; i++) {
1066             dest_caps[i].mdbnode.owner = owner;
1067         }
1068     }
1069
1070     return SYS_ERR_OK;
1071 }
1072
1073 /**
1074  * Look up a capability in two-level cspace rooted at `rootcn`.
1075  */
1076 errval_t caps_lookup_slot(struct capability *rootcn, capaddr_t cptr,
1077                           uint8_t level, struct cte **ret, CapRights rights)
1078 {
1079     TRACE(KERNEL, CAP_LOOKUP_SLOT, 0);
1080
1081     cslot_t l1index, l2index;
1082     l1index = (cptr >> L2_CNODE_BITS) & MASK(CPTR_BITS-L2_CNODE_BITS);
1083     l2index = cptr & MASK(L2_CNODE_BITS);
1084
1085     assert(ret != NULL);
1086     assert(rootcn != NULL);
1087
1088     if (level > 2) {
1089         debug(SUBSYS_CAPS, "%s called with level=%hhu, from %p\n",
1090                 __FUNCTION__, level,
1091                 (void*)kernel_virt_to_elf_addr(__builtin_return_address(0)));
1092         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1093         return SYS_ERR_CAP_LOOKUP_DEPTH;
1094     }
1095     assert(level <= 2);
1096
1097     // level 0 means that we do not do any resolution and just return the cte
1098     // for rootcn.
1099     if (level == 0) {
1100         *ret = cte_for_cap(rootcn);
1101         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1102         return SYS_ERR_OK;
1103     }
1104
1105     if (rootcn->type != ObjType_L1CNode) {
1106         debug(SUBSYS_CAPS, "%s: rootcn->type = %d, called from %p\n",
1107                 __FUNCTION__, rootcn->type,
1108                 (void*)kernel_virt_to_elf_addr(__builtin_return_address(0)));
1109         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1110         // XXX: think about errors
1111         return SYS_ERR_CNODE_TYPE;
1112     }
1113     assert(rootcn->type == ObjType_L1CNode);
1114
1115     if (l1index > cnode_get_slots(rootcn)) {
1116         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1117         return SYS_ERR_L1_CNODE_INDEX;
1118     }
1119
1120     /* Apply rights to L1 CNode */
1121     if ((rootcn->rights & rights) != rights) {
1122         debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
1123               "Passed rights = %u, cnode_cap->rights = %u\n",
1124               rights, rootcn->rights);
1125         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1126         return SYS_ERR_CNODE_RIGHTS;
1127     }
1128
1129     struct cte *l2cnode = caps_locate_slot(get_address(rootcn), l1index);
1130
1131     // level == 1 means that we terminate after looking up the slot in the L1
1132     // cnode.
1133     if (level == 1) {
1134         if (l2cnode->cap.type == ObjType_Null) {
1135             TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1136             return SYS_ERR_CAP_NOT_FOUND;
1137         }
1138         *ret = l2cnode;
1139         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1140         return SYS_ERR_OK;
1141     }
1142
1143     if (l2cnode->cap.type != ObjType_L2CNode) {
1144         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1145         debug(SUBSYS_CAPS, "%s: l2cnode->type = %d\n", __FUNCTION__,
1146                l2cnode->cap.type);
1147         return SYS_ERR_CNODE_TYPE;
1148     }
1149     assert(l2cnode->cap.type == ObjType_L2CNode);
1150
1151     assert(l2index < L2_CNODE_SLOTS);
1152
1153     /* Apply rights to L2 CNode */
1154     if ((l2cnode->cap.rights & rights) != rights) {
1155         debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
1156               "Passed rights = %u, cnode_cap->rights = %u\n",
1157               rights, l2cnode->cap.rights);
1158         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1159         return SYS_ERR_CNODE_RIGHTS;
1160     }
1161
1162     struct cte *cte = caps_locate_slot(get_address(&l2cnode->cap), l2index);
1163     if (cte->cap.type == ObjType_Null) {
1164         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1165         return SYS_ERR_CAP_NOT_FOUND;
1166     }
1167
1168     *ret = cte;
1169
1170     TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1171     return SYS_ERR_OK;
1172 }
1173
1174 /**
1175  * Wrapper for caps_lookup_slot returning capability instead of cte.
1176  */
1177 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
1178                          uint8_t level, struct capability **ret, CapRights rights)
1179 {
1180     TRACE(KERNEL, CAP_LOOKUP_CAP, 0);
1181
1182     struct cte *ret_cte;
1183     errval_t err = caps_lookup_slot(cnode_cap, cptr, level, &ret_cte, rights);
1184     if (err_is_fail(err)) {
1185         return err;
1186     }
1187     *ret = &ret_cte->cap;
1188     TRACE(KERNEL, CAP_LOOKUP_CAP, 1);
1189     return SYS_ERR_OK;
1190 }
1191
1192 /**
1193  * \brief Create a capability from an existing capability metadata.
1194  *
1195  * Used when sending capabilities across cores. The metadata is sent across
1196  * cores and the receiving monitor can create the new capability on its core.
1197  *
1198  * \bug Does not check that supplied owner matches existing copies of cap.
1199  */
1200 errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
1201                                    int cnode_level, cslot_t dest_slot, coreid_t owner,
1202                                    struct capability *src)
1203 {
1204     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 0);
1205     errval_t err;
1206     struct capability *cnode;
1207     err = caps_lookup_cap(root, cnode_cptr, cnode_level, &cnode,
1208                           CAPRIGHTS_READ_WRITE);
1209     if (err_is_fail(err)) {
1210         return err_push(err, SYS_ERR_SLOT_LOOKUP_FAIL);
1211     }
1212     if (cnode->type != ObjType_L1CNode &&
1213         cnode->type != ObjType_L2CNode)
1214     {
1215         return SYS_ERR_CNODE_TYPE;
1216     }
1217
1218     struct cte *dest = caps_locate_slot(get_address(cnode), dest_slot);
1219
1220     err = set_cap(&dest->cap, src);
1221     if (err_is_fail(err)) {
1222         return err;
1223     }
1224
1225     dest->mdbnode.owner = owner;
1226
1227     err = mdb_insert(dest);
1228     assert(err_is_ok(err));
1229
1230     struct cte *neighbour = NULL;
1231     if (!neighbour
1232         && (neighbour = mdb_predecessor(dest))
1233         && !is_copy(&dest->cap, &neighbour->cap))
1234     {
1235         neighbour = NULL;
1236     }
1237     if (!neighbour
1238         && (neighbour = mdb_successor(dest))
1239         && !is_copy(&dest->cap, &neighbour->cap))
1240     {
1241         neighbour = NULL;
1242     }
1243
1244     if (neighbour) {
1245         assert(!neighbour->mdbnode.in_delete);
1246         assert(neighbour->mdbnode.owner == owner);
1247 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
1248         CP_ATTR(locked);
1249         CP_ATTR(remote_copies);
1250         CP_ATTR(remote_ancs);
1251         CP_ATTR(remote_descs);
1252 #undef CP_ATTR
1253     }
1254     else {
1255         dest->mdbnode.locked = false;
1256         if (owner != my_core_id) {
1257             // For foreign caps it does not really matter if ancestors or
1258             // descendants exist
1259             dest->mdbnode.remote_copies = true;
1260             dest->mdbnode.remote_ancs = false;
1261             dest->mdbnode.remote_descs = false;
1262         }
1263         else {
1264             // We just created a new copy of a owned capability from nothing.
1265             // This is either caused by a retype, or by sharing a capability
1266             // that does not care about locality.
1267             // XXX: This should probably be done more explicitly -MN
1268             if (distcap_needs_locality(dest->cap.type)) {
1269                 // Retype, so have ancestors and no descendants
1270                 dest->mdbnode.remote_copies = false;
1271                 dest->mdbnode.remote_ancs = true;
1272                 dest->mdbnode.remote_descs = false;
1273             }
1274             else {
1275                 dest->mdbnode.remote_copies = false;
1276                 dest->mdbnode.remote_ancs = false;
1277                 dest->mdbnode.remote_descs = false;
1278             }
1279         }
1280     }
1281
1282     TRACE_CAP_MSG("created", dest);
1283
1284     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 1);
1285     return SYS_ERR_OK;
1286 }
1287
1288 //{{{1 Capability creation
1289
1290 /// check arguments, return true iff ok
1291 STATIC_ASSERT(49 == ObjType_Num, "Knowledge of all cap types");
1292 static bool check_caps_create_arguments(enum objtype type,
1293                                         size_t bytes, size_t objsize,
1294                                         bool exact)
1295 {
1296     /* mappable types need to be at least BASE_PAGE_SIZEd */
1297     if (type_is_mappable(type)) {
1298         /* source size not multiple of BASE_PAGE_SIZE */
1299         if (bytes & BASE_PAGE_MASK) {
1300             debug(SUBSYS_CAPS, "source size not multiple of BASE_PAGE_SIZE\n");
1301             return false;
1302         }
1303         /* objsize > 0 and not multiple of BASE_PAGE_SIZE */
1304         if (objsize > 0 && objsize & BASE_PAGE_MASK) {
1305             debug(SUBSYS_CAPS, "object size not multiple of BASE_PAGE_SIZE\n");
1306             return false;
1307         }
1308
1309         /* check that bytes can be evenly divided into objsize sized chunks */
1310         if (exact && bytes > 0 && objsize > 0) {
1311             if (bytes % objsize) {
1312                 debug(SUBSYS_CAPS, "source size cannot be evenly divided into object size-sized chunks\n");
1313             }
1314             return bytes % objsize == 0;
1315         }
1316
1317         return true;
1318     }
1319
1320     if (type == ObjType_L1CNode) {
1321         /* L1 CNode minimum size is OBJSIZE_L2CNODE */
1322         if (bytes < OBJSIZE_L2CNODE || objsize < OBJSIZE_L2CNODE) {
1323             debug(SUBSYS_CAPS, "source size or L1 CNode objsize < OBJSIZE_L2CNODE\n");
1324             return false;
1325         }
1326         /* check that bytes can be evenly divided into L1 CNodes of objsize */
1327         if (exact && (bytes % objsize != 0)) {
1328             debug(SUBSYS_CAPS, "source not evenly divisible into L1 CNodes of objsize\n");
1329             return false;
1330         }
1331         /* L1 CNode size must be multiple of 1UL << OBJBITS_CTE */
1332         return objsize % (1UL << OBJBITS_CTE) == 0;
1333     }
1334
1335     if (type == ObjType_L2CNode) {
1336         /* L2 CNode size must be OBJSIZE_L2CNODE */
1337         if (bytes < OBJSIZE_L2CNODE || objsize != OBJSIZE_L2CNODE) {
1338             debug(SUBSYS_CAPS, "source size < or L2 CNode objsize != OBJSIZE_L2CNODE\n");
1339             return false;
1340         }
1341         if (exact && (bytes % objsize != 0)) {
1342             debug(SUBSYS_CAPS, "source not evenly divisible into L2 CNodes of objsize\n");
1343             return false;
1344         }
1345         return true;
1346     }
1347
1348     /* special case Dispatcher which is 1kB right now */
1349     if (type == ObjType_Dispatcher) {
1350         if (bytes & ((1UL << OBJBITS_DISPATCHER) - 1)) {
1351             return false;
1352         }
1353         if (objsize > 0 && objsize != 1UL << OBJBITS_DISPATCHER) {
1354             return false;
1355         }
1356
1357         if (exact && bytes % (1UL << OBJBITS_DISPATCHER)) {
1358             return false;
1359         }
1360
1361         return true;
1362     }
1363
1364     // All other types do not need special alignments/offsets
1365     return true;
1366 }
1367
1368 /** Create caps to new kernel objects.
1369  * This takes the size of the memory region in bytes, and the size of
1370  * individual objects in bytes. The following needs to hold:
1371  *      bytes % objbytes == 0
1372  */
1373 errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bytes,
1374                          size_t objsize, coreid_t owner, struct cte *caps)
1375 {
1376     TRACE(KERNEL, CAP_CREATE_NEW, 0);
1377     /* Parameter checking */
1378     assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1379     debug(SUBSYS_CAPS, "caps_create_new: type = %d, addr = %#"PRIxLPADDR
1380             ", bytes=%zu, objsize=%zu\n", type, addr, bytes, objsize);
1381     assert(check_caps_create_arguments(type, bytes, objsize, false));
1382     assert(addr == 0 || check_caps_create_arguments(type, bytes, objsize, true));
1383
1384     size_t numobjs = caps_max_numobjs(type, bytes, objsize);
1385     assert(numobjs > 0);
1386     // XXX: Dispatcher creation is kind of hacky right now :(
1387     // Consider allowing non-mappable types to be < BASE_PAGE_SIZE
1388     //if (type == ObjType_Dispatcher) {
1389     //    numobjs = 1;
1390     //}
1391
1392     /* Create the new capabilities */
1393     errval_t err = caps_create(type, addr, bytes, objsize, numobjs, owner, caps);
1394     if (err_is_fail(err)) {
1395         return err;
1396     }
1397
1398     // Handle the mapping database
1399     set_init_mapping(caps, numobjs);
1400
1401     TRACE_CAP_MSG("created", &caps[0]);
1402
1403     TRACE(KERNEL, CAP_CREATE_NEW, 1);
1404     return SYS_ERR_OK;
1405 }
1406
1407 STATIC_ASSERT(49 == ObjType_Num, "Knowledge of all cap types");
1408 /// Retype caps
1409 /// Create `count` new caps of `type` from `offset` in src, and put them in
1410 /// `dest_cnode` starting at `dest_slot`.
1411 errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
1412                      struct capability *dest_cnode, cslot_t dest_slot,
1413                      struct cte *src_cte, gensize_t offset,
1414                      bool from_monitor)
1415 {
1416     TRACE(KERNEL, CAP_RETYPE, 0);
1417     size_t maxobjs;
1418     genpaddr_t base = 0;
1419     gensize_t size = 0;
1420     errval_t err;
1421     bool do_range_check = false;
1422
1423     /* Parameter checking */
1424     assert(type != ObjType_Null);
1425     assert(type < ObjType_Num);
1426     if (type == ObjType_Null || type >= ObjType_Num) {
1427         return SYS_ERR_INVALID_RETYPE;
1428     }
1429
1430     debug(SUBSYS_CAPS, "%s: Retyping to type=%d, from offset=%" PRIuGENSIZE
1431             ", objsize=%" PRIuGENSIZE ", count=%zu\n",
1432             __FUNCTION__, type, offset, objsize, count);
1433
1434     /* check that offset into source cap is multiple of BASE_PAGE_SIZE */
1435     if (offset % BASE_PAGE_SIZE != 0) {
1436         return SYS_ERR_RETYPE_INVALID_OFFSET;
1437     }
1438     assert(offset % BASE_PAGE_SIZE == 0);
1439
1440     // check that size is multiple of BASE_PAGE_SIZE for mappable types
1441     if (type_is_mappable(type) && objsize % BASE_PAGE_SIZE != 0) {
1442         debug(SUBSYS_CAPS, "%s: objsize = %"PRIuGENSIZE"\n", __FUNCTION__, objsize);
1443         return SYS_ERR_INVALID_SIZE;
1444     }
1445     else if (type == ObjType_L1CNode && objsize % OBJSIZE_L2CNODE != 0)
1446     {
1447         printk(LOG_WARN, "%s: CNode: objsize = %" PRIuGENSIZE "\n", __FUNCTION__, objsize);
1448         return SYS_ERR_INVALID_SIZE;
1449     }
1450     else if (type == ObjType_L2CNode && objsize != OBJSIZE_L2CNODE)
1451     {
1452         printk(LOG_WARN, "%s: L2CNode: objsize = %"PRIuGENSIZE"\n", __FUNCTION__, objsize);
1453         return SYS_ERR_INVALID_SIZE;
1454     }
1455     assert((type_is_mappable(type) && objsize % BASE_PAGE_SIZE == 0) ||
1456            (type == ObjType_L1CNode && objsize % OBJSIZE_L2CNODE == 0 &&
1457             objsize >= OBJSIZE_L2CNODE) ||
1458            (type == ObjType_L2CNode && objsize == OBJSIZE_L2CNODE) ||
1459            !type_is_mappable(type));
1460
1461     /* No explicit retypes to Mapping allowed */
1462     if (type_is_mapping(type)) {
1463         return SYS_ERR_RETYPE_MAPPING_EXPLICIT;
1464     }
1465
1466     struct capability *src_cap = &src_cte->cap;
1467
1468     TRACE_CAP_MSG("retyping", src_cte);
1469
1470     /* Check retypability */
1471     err = is_retypeable(src_cte, src_cap->type, type, from_monitor);
1472     if (err_is_fail(err)) {
1473         if (err_no(err) != SYS_ERR_REVOKE_FIRST) {
1474             printk(LOG_NOTE, "caps_retype: is_retypeable failed: %"PRIuERRV"\n", err);
1475             debug(SUBSYS_CAPS, "caps_retype: is_retypeable failed\n");
1476             return err;
1477         } else {
1478             debug(SUBSYS_CAPS,
1479                     "caps_retype: is_retypeable() returned SYS_ERR_REVOKE_FIRST, doing range check\n");
1480             // We handle err_revoke_first fine-grained checking below, as it
1481             // might happen for non-overlapping regions.
1482
1483             // TODO: move the range checking into is_retypeable() or even
1484             // is_revoked_first(), -SG 2016-04-18
1485             do_range_check = true;
1486         }
1487     }
1488     // from here: src cap type is one of these.
1489     assert(src_cap->type == ObjType_PhysAddr ||
1490            src_cap->type == ObjType_RAM ||
1491            src_cap->type == ObjType_Dispatcher ||
1492            src_cap->type == ObjType_Frame ||
1493            src_cap->type == ObjType_DevFrame);
1494
1495     if (src_cap->type != ObjType_Dispatcher) {
1496         base = get_address(src_cap);
1497         size = get_size(src_cap);
1498     }
1499
1500     maxobjs = caps_max_numobjs(type, get_size(src_cap), objsize);
1501     debug(SUBSYS_CAPS, "maximum possible new object count: %zu\n", maxobjs);
1502
1503     if (maxobjs == 0) {
1504         debug(SUBSYS_CAPS, "caps_retype: maxobjs == 0\n");
1505         return SYS_ERR_INVALID_SIZE;
1506     }
1507
1508     if (count > maxobjs) {
1509         debug(SUBSYS_CAPS, "caps_retype: maxobjs = %zu, count = %zu\n", maxobjs, count);
1510         return SYS_ERR_RETYPE_INVALID_COUNT;
1511     }
1512     // from here: count <= maxobjs
1513     assert(count <= maxobjs);
1514     // make sure nobody calls with the old behaviour
1515     if (count == 0) {
1516         return SYS_ERR_RETYPE_INVALID_COUNT;
1517     }
1518     assert(count > 0);
1519
1520     /* check that we can create `count` objs from `offset` in source, and
1521      * update base accordingly */
1522     if (src_cap->type != ObjType_Dispatcher) {
1523         // TODO: convince ourselves that this is the only condition on offset
1524         if (offset + count * objsize > get_size(src_cap)) {
1525             debug(SUBSYS_CAPS, "caps_retype: cannot create all %zu objects"
1526                     " of size 0x%" PRIxGENSIZE " from offset 0x%" PRIxGENSIZE "\n",
1527                     count, objsize, offset);
1528             return SYS_ERR_RETYPE_INVALID_OFFSET;
1529         }
1530         // adjust base address for new objects
1531         base += offset;
1532
1533         // Check whether we got SYS_ERR_REVOKE_FIRST because of
1534         // non-overlapping child
1535         if (do_range_check) {
1536             int find_range_result = 0;
1537             struct cte *found_cte = NULL;
1538             err = mdb_find_range(get_type_root(src_cap->type), base, objsize * count,
1539                     MDB_RANGE_FOUND_SURROUNDING, &found_cte, &find_range_result);
1540             // this should never return an error unless we mess up the
1541             // non-user supplied arguments
1542             if (err_is_fail(err)) {
1543                 printk(LOG_WARN, "mdb_find_range returned: %"PRIuERRV"\n", err);
1544             }
1545             assert(err_is_ok(err));
1546             // return REVOKE_FIRST, if we found a cap inside the region
1547             // (FOUND_INNER == 2) or overlapping the region (FOUND_PARTIAL == 3)
1548             if (find_range_result >= MDB_RANGE_FOUND_INNER) {
1549                 debug(SUBSYS_CAPS,
1550                     "%s: found existing region inside, or overlapping requested region:\n",
1551                     __FUNCTION__);
1552                 return SYS_ERR_REVOKE_FIRST;
1553             }
1554             // return REVOKE_FIRST, if we found a cap that isn't our source
1555             // (or a copy of our source) covering the whole requested region.
1556             else if (find_range_result == MDB_RANGE_FOUND_SURROUNDING &&
1557                      !is_copy(&found_cte->cap, src_cap))
1558             {
1559                 debug(SUBSYS_CAPS,
1560                        "%s: found non source region fully covering requested region\n",
1561                        __FUNCTION__);
1562                 return SYS_ERR_REVOKE_FIRST;
1563             }
1564         }
1565     }
1566
1567     /* check that destination slots all fit within target cnode */
1568     if (dest_slot + count > cnode_get_slots(dest_cnode)) {
1569         debug(SUBSYS_CAPS, "caps_retype: dest slots don't fit in cnode\n");
1570         return SYS_ERR_SLOTS_INVALID;
1571     }
1572
1573     /* check that destination slots are all empty */
1574     debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1575           " dest_slot %d\n",
1576           get_address(dest_cnode), (int)dest_slot);
1577     for (cslot_t i = 0; i < count; i++) {
1578         if (caps_locate_slot(get_address(dest_cnode), dest_slot + i)->cap.type
1579             != ObjType_Null) {
1580             debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1581                   (int)(dest_slot + i));
1582             return SYS_ERR_SLOTS_IN_USE;
1583         }
1584     }
1585
1586     /* Check that L1 CNode is destination when creating L2 CNode */
1587     if (type == ObjType_L2CNode) {
1588         debug(SUBSYS_CAPS, "caps_retype: check that dest cnode is L1"
1589                            " when creating L2 CNodes\n");
1590         if (dest_cnode->type != ObjType_L1CNode &&
1591             dest_cnode->type != ObjType_L2CNode)
1592         {
1593             panic("L2 CNode can only be created in L1 or L2 CNode\n");
1594         }
1595     }
1596
1597     /* create new caps */
1598     struct cte *dest_cte =
1599         caps_locate_slot(get_address(dest_cnode), dest_slot);
1600     err = caps_create(type, base, size, objsize, count, my_core_id, dest_cte);
1601     if (err_is_fail(err)) {
1602         debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
1603         return err_push(err, SYS_ERR_RETYPE_CREATE);
1604     }
1605
1606     /* special initialisation for endpoint caps */
1607     if (type == ObjType_EndPoint) {
1608         assert(src_cap->type == ObjType_Dispatcher);
1609         assert(count == 1);
1610         struct capability *dest_cap = &dest_cte->cap;
1611         dest_cap->u.endpoint.listener = src_cap->u.dispatcher.dcb;
1612     }
1613
1614     /* Handle mapping */
1615     for (size_t i = 0; i < count; i++) {
1616         mdb_insert(&dest_cte[i]);
1617     }
1618
1619 #ifdef TRACE_PMEM_CAPS
1620     for (size_t i = 0; i < count; i++) {
1621         TRACE_CAP_MSG("created", &dest_cte[i]);
1622     }
1623 #endif
1624
1625     TRACE(KERNEL, CAP_RETYPE, 1);
1626     return SYS_ERR_OK;
1627 }
1628
1629 /// Check the validity of a retype operation
1630 errval_t is_retypeable(struct cte *src_cte, enum objtype src_type,
1631                        enum objtype dest_type, bool from_monitor)
1632 {
1633     if (!is_well_founded(src_type, dest_type)) {
1634         return SYS_ERR_INVALID_RETYPE;
1635     } else if (!is_revoked_first(src_cte, src_type)){
1636         //printf("err_revoke_first: (%p, %d, %d)\n", src_cte, src_type, dest_type);
1637         return SYS_ERR_REVOKE_FIRST;
1638     } else if (dest_type == ObjType_EndPoint && src_cte->mdbnode.owner == my_core_id) {
1639         // XXX: because of the current "multi-retype" hack for endpoints, a
1640         // dispatcher->endpoint retype can happen irrespective of the existence
1641         // of descendants on any core.
1642         // However, we only do this for locally owned caps as the owner should
1643         // be notified that the cap has remote descendants
1644         return SYS_ERR_OK;
1645     } else if (!from_monitor && (src_cte->mdbnode.owner != my_core_id
1646                                  || src_cte->mdbnode.remote_descs)) {
1647         return SYS_ERR_RETRY_THROUGH_MONITOR;
1648     } else {
1649         return SYS_ERR_OK;
1650     }
1651 }
1652
1653 /// Create copies to a slot within a cnode
1654 errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
1655                             struct cte *src_cte, bool mint, uintptr_t param1,
1656                             uintptr_t param2)
1657 {
1658     /* Parameter Checking */
1659     assert(dest_cnode_cte->cap.type == ObjType_L1CNode ||
1660            dest_cnode_cte->cap.type == ObjType_L2CNode);
1661
1662     // only allow L2 CNodes and BSP KCB in L1 CNode
1663     // XXX: BSPKCB should not be in rootcn...
1664     if (dest_cnode_cte->cap.type == ObjType_L1CNode &&
1665         src_cte->cap.type != ObjType_L2CNode &&
1666         src_cte->cap.type != ObjType_KernelControlBlock)
1667     {
1668         printk(LOG_WARN, "trying to copy cap type %d into cap type %d\n",
1669                 src_cte->cap.type, dest_cnode_cte->cap.type);
1670         return SYS_ERR_DEST_TYPE_INVALID;
1671     }
1672
1673     struct cte *dest_cte;
1674     dest_cte = caps_locate_slot(get_address(&dest_cnode_cte->cap), dest_slot);
1675     return caps_copy_to_cte(dest_cte, src_cte, mint, param1, param2);
1676
1677 }
1678
1679 /// Create copies to a cte
1680 STATIC_ASSERT(49 == ObjType_Num, "Knowledge of all cap types");
1681 errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
1682                           uintptr_t param1, uintptr_t param2)
1683 {
1684     errval_t err;
1685     /* Parameter checking */
1686     // Null checking
1687     assert(dest_cte != NULL);
1688     assert(src_cte != NULL);
1689
1690     struct capability *src_cap  = &src_cte->cap;
1691     struct capability *dest_cap = &dest_cte->cap;
1692     // NULL caps cannot be copied/minted
1693     if (src_cap->type == ObjType_Null) {
1694         return SYS_ERR_CAP_NOT_FOUND;
1695     }
1696     // Parameters should be 0 if not minting
1697     if (!mint) {
1698         assert(param1 == 0);
1699         assert(param2 == 0);
1700     }
1701
1702     assert(!src_cte->mdbnode.in_delete);
1703
1704     /* Insert #source_cap into #dest_cap */
1705     err = set_cap(dest_cap, src_cap);
1706     if (err_is_fail(err)) {
1707         return err;
1708     }
1709
1710     /* Transfer MDB attributes that must be equal for all copies */
1711 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1712     CP_ATTR(owner);
1713     CP_ATTR(locked);
1714     CP_ATTR(remote_copies);
1715     CP_ATTR(remote_ancs);
1716     CP_ATTR(remote_descs);
1717 #undef CP_ATTR
1718
1719     /* Copy is done */
1720     if(!mint) {
1721         TRACE_CAP_MSG("copied to", dest_cte);
1722         // Handle mapping here only for non-mint operations
1723         // (mint can change eq fields which would make the early insertion
1724         // invalid in some cases)
1725         mdb_insert(dest_cte);
1726         return SYS_ERR_OK;
1727     }
1728     else {
1729         TRACE_CAP_MSG("minting to", dest_cte);
1730     }
1731
1732     /* For minting, set the specified parameters */
1733     // Process source-specific parameters for minting
1734     // XXX: If failure, revert the insertion
1735     switch(src_cap->type) {
1736     case ObjType_EndPoint:
1737         // XXX: FIXME: check that buffer offset lies wholly within the disp frame
1738         // can't easily enforce this here, because the dispatcher frame may not
1739         // yet be setup
1740 /*        if (param1 < sizeof(struct dispatcher) ||
1741             dest_cap->u.endpoint.listener->disp == NULL ||
1742             param2 < IDC_RECV_LENGTH ||
1743             param1 + sizeof(struct idc_endpoint) + param2 * sizeof(uintptr_t) >
1744             (1UL << dest_cap->u.endpoint.listener->disp_cte.cap.u.frame.bits)) {
1745             return SYS_ERR_INVALID_EPBUF;
1746         }*/
1747         if (param2 < LMP_RECV_HEADER_LENGTH) {
1748             return SYS_ERR_INVALID_EPLEN;
1749         }
1750         dest_cap->u.endpoint.epoffset = param1;
1751         dest_cap->u.endpoint.epbuflen = param2;
1752         break;
1753
1754     case ObjType_IO:
1755         if(src_cap->u.io.start  <= param1) {
1756             dest_cap->u.io.start = param1;
1757         }
1758         if(src_cap->u.io.end  >= param2) {
1759             dest_cap->u.io.end = param2;
1760         }
1761         break;
1762
1763     default:
1764         // Unhandled source type for mint
1765         return SYS_ERR_INVALID_SOURCE_TYPE;
1766     }
1767
1768     // Insert after doing minting operation
1769     mdb_insert(dest_cte);
1770
1771     return SYS_ERR_OK;
1772 }