kernel: capabilities: wrap check_caps_create_arguments() in #ifndef NDEBUG because...
[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(48 == 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.devframe.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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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.cap,
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(48 == 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 < OBJSIZE_DISPATCHER) {
419             return 0;
420         } else {
421             return srcsize / OBJSIZE_DISPATCHER;
422         }
423
424     case ObjType_KernelControlBlock:
425         if (srcsize < OBJSIZE_KCB) {
426             return 0;
427         } else {
428             return srcsize / OBJSIZE_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_IPI:
439     case ObjType_PerfMon:
440     case ObjType_IPI:
441     case ObjType_VNode_ARM_l1_Mapping:
442     case ObjType_VNode_ARM_l2_Mapping:
443     case ObjType_VNode_AARCH64_l0_Mapping:
444     case ObjType_VNode_AARCH64_l1_Mapping:
445     case ObjType_VNode_AARCH64_l2_Mapping:
446     case ObjType_VNode_AARCH64_l3_Mapping:
447     case ObjType_VNode_x86_64_pml4_Mapping:
448     case ObjType_VNode_x86_64_pdpt_Mapping:
449     case ObjType_VNode_x86_64_pdir_Mapping:
450     case ObjType_VNode_x86_64_ptable_Mapping:
451     case ObjType_VNode_x86_32_pdpt_Mapping:
452     case ObjType_VNode_x86_32_pdir_Mapping:
453     case ObjType_VNode_x86_32_ptable_Mapping:
454     case ObjType_DevFrame_Mapping:
455     case ObjType_Frame_Mapping:
456         return 1;
457
458     default:
459         panic("invalid type");
460         return 0;
461     }
462 }
463
464 /**
465  * \brief Initialize the objects for which local caps are about to be created.
466  *
467  * For the meaning of the parameters, see the 'caps_create' function.
468  */
469 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
470
471 static errval_t caps_zero_objects(enum objtype type, lpaddr_t lpaddr,
472                                   gensize_t objsize, size_t count)
473 {
474     assert(type < ObjType_Num);
475
476     // Virtual address of the memory the kernel object resides in
477     // XXX: A better of doing this,
478     // this is creating caps that the kernel cannot address.
479     // It assumes that the cap is not of the type which will have to zeroed out.
480     lvaddr_t lvaddr;
481     if(lpaddr < PADDR_SPACE_LIMIT) {
482         lvaddr = local_phys_to_mem(lpaddr);
483     } else {
484         lvaddr = 0;
485     }
486
487     switch (type) {
488
489     case ObjType_Frame:
490         debug(SUBSYS_CAPS, "Frame: zeroing %zu bytes @%#"PRIxLPADDR"\n",
491                 (size_t)objsize * count, lpaddr);
492         TRACE(KERNEL, BZERO, 1);
493         memset((void*)lvaddr, 0, objsize * count);
494         TRACE(KERNEL, BZERO, 0);
495         break;
496
497     case ObjType_L1CNode:
498     case ObjType_L2CNode:
499         debug(SUBSYS_CAPS, "L%dCNode: zeroing %zu bytes @%#"PRIxLPADDR"\n",
500                 type == ObjType_L1CNode ? 1 : 2, (size_t)objsize * count,
501                 lpaddr);
502         TRACE(KERNEL, BZERO, 1);
503         memset((void*)lvaddr, 0, objsize * count);
504         TRACE(KERNEL, BZERO, 0);
505         break;
506
507     case ObjType_VNode_ARM_l1:
508     case ObjType_VNode_ARM_l2:
509     case ObjType_VNode_AARCH64_l0:
510     case ObjType_VNode_AARCH64_l1:
511     case ObjType_VNode_AARCH64_l2:
512     case ObjType_VNode_AARCH64_l3:
513     case ObjType_VNode_x86_32_ptable:
514     case ObjType_VNode_x86_32_pdir:
515     case ObjType_VNode_x86_32_pdpt:
516     case ObjType_VNode_x86_64_ptable:
517     case ObjType_VNode_x86_64_pdir:
518     case ObjType_VNode_x86_64_pdpt:
519     case ObjType_VNode_x86_64_pml4:
520         // objsize is size of VNode; but not given as such
521         objsize = vnode_objsize(type);
522         debug(SUBSYS_CAPS, "VNode: zeroing %zu bytes @%#"PRIxLPADDR"\n",
523                 (size_t)objsize * count, lpaddr);
524         TRACE(KERNEL, BZERO, 1);
525         memset((void*)lvaddr, 0, objsize * count);
526         TRACE(KERNEL, BZERO, 0);
527         break;
528
529     case ObjType_Dispatcher:
530         debug(SUBSYS_CAPS, "Dispatcher: zeroing %zu bytes @%#"PRIxLPADDR"\n",
531                 ((size_t) OBJSIZE_DISPATCHER) * count, lpaddr);
532         TRACE(KERNEL, BZERO, 1);
533         memset((void*)lvaddr, 0, OBJSIZE_DISPATCHER * count);
534         TRACE(KERNEL, BZERO, 0);
535         break;
536
537     case ObjType_KernelControlBlock:
538         debug(SUBSYS_CAPS, "KCB: zeroing %zu bytes @%#"PRIxLPADDR"\n",
539                 ((size_t) OBJSIZE_KCB) * count, lpaddr);
540         TRACE(KERNEL, BZERO, 1);
541         memset((void*)lvaddr, 0, OBJSIZE_KCB * count);
542         TRACE(KERNEL, BZERO, 0);
543         break;
544
545     default:
546         debug(SUBSYS_CAPS, "Not zeroing %zu bytes @%#"PRIxLPADDR" for type %d\n",
547                 (size_t)objsize * count, lpaddr, (int)type);
548         break;
549
550     }
551
552     return SYS_ERR_OK;
553 }
554
555 /**
556  * \brief Create capabilities to kernel objects.
557  *
558  * This function creates 'count' kernel objects of 'type' into the memory
559  * area, based at 'addr' and of size 'objsize'. For each created kernel
560  * object, a capability is created to it and put consecutively into the array
561  * of CTEs pointed to by 'caps'. The array needs to have the appropriate size
562  * to hold all created caps. Some kernel objects can have a variable size. In
563  * that case, 'objsize' should be non-zero. and give the size multiplier. *
564  *
565  * \param type          Type of objects to create.
566  * \param lpaddr        Base address in the local address space.
567  * \param size          Size of memory area as bytes.
568  * \param objsize       For variable-sized objects, size in bytes.
569  * \param count         Number of objects to be created
570  *                      (count <= caps_max_numobjs(type, size, objsize))
571  * \param dest_caps     Pointer to array of CTEs to hold created caps.
572  *
573  * \return Error code
574  */
575 // If you create more capability types you need to deal with them
576 // in the table below.
577 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
578
579 static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, gensize_t size,
580                             gensize_t objsize, size_t count, coreid_t owner,
581                             struct cte *dest_caps)
582 {
583     errval_t err;
584
585     /* Parameter checking */
586     assert(dest_caps != NULL);
587     assert(type != ObjType_Null);
588     assert(type < ObjType_Num);
589     assert(count > 0);
590     // objsize is 0 for non-sized types (e.g. VNodes)
591     // TODO cleanup semantics for type == CNode
592     //assert(objsize % BASE_PAGE_SIZE == 0);
593     assert(!type_is_mapping(type));
594
595     genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
596
597     debug(SUBSYS_CAPS, "creating caps for %#"PRIxGENPADDR
598                        ", %" PRIuGENSIZE " bytes, objsize=%"PRIuGENSIZE
599                        ", count=%zu, owner=%d, type=%d\n",
600             genpaddr, size, objsize, count, (int)owner, (int)type);
601
602     // Virtual address of the memory the kernel object resides in
603     // XXX: A better of doing this,
604     // this is creating caps that the kernel cannot address.
605     // It assumes that the cap is not of the type which will have to zeroed out.
606     lvaddr_t lvaddr;
607     if(lpaddr < PADDR_SPACE_LIMIT) {
608         lvaddr = local_phys_to_mem(lpaddr);
609     } else {
610         lvaddr = 0;
611     }
612
613     /* Initialize the created capability */
614     struct capability temp_cap;
615     memset(&temp_cap, 0, sizeof(struct capability));
616     temp_cap.type = type;
617     // XXX: Handle rights!
618     temp_cap.rights = CAPRIGHTS_ALLRIGHTS;
619
620     debug(SUBSYS_CAPS, "owner = %d, my_core_id = %d\n", owner, my_core_id);
621     if (owner == my_core_id) {
622         // If we're creating new local objects, they need to be cleared
623         err = caps_zero_objects(type, lpaddr, objsize, count);
624         if (err_is_fail(err)) {
625             return err;
626         }
627     }
628
629     size_t dest_i = 0;
630     err = SYS_ERR_OK;
631
632     /* Set the type specific fields and insert into #dest_caps */
633     switch(type) {
634     case ObjType_Frame:
635         for(dest_i = 0; dest_i < count; dest_i++) {
636             // Initialize type specific fields
637             temp_cap.u.frame.base = genpaddr + dest_i * objsize;
638             temp_cap.u.frame.bytes = objsize;
639             assert((get_size(&temp_cap) & BASE_PAGE_MASK) == 0);
640             // Insert the capability
641             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
642             if (err_is_fail(err)) {
643                 break;
644             }
645         }
646         break;
647
648     case ObjType_PhysAddr:
649         for(dest_i = 0; dest_i < count; dest_i++) {
650             // Initialize type specific fields
651             temp_cap.u.physaddr.base = genpaddr + dest_i * objsize;
652             temp_cap.u.physaddr.bytes = objsize;
653             // Insert the capability
654             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
655             if (err_is_fail(err)) {
656                 break;
657             }
658         }
659         break;
660
661     case ObjType_RAM:
662         for(dest_i = 0; dest_i < count; dest_i++) {
663             // Initialize type specific fields
664             temp_cap.u.ram.base = genpaddr + dest_i * objsize;
665             temp_cap.u.ram.bytes = objsize;
666             // Insert the capabilities
667             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
668             if (err_is_fail(err)) {
669                 break;
670             }
671         }
672         break;
673
674     case ObjType_DevFrame:
675         for(dest_i = 0; dest_i < count; dest_i++) {
676             // Initialize type specific fields
677             temp_cap.u.devframe.base = genpaddr + dest_i * objsize;
678             temp_cap.u.devframe.bytes = objsize;
679             // Insert the capabilities
680             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
681             if (err_is_fail(err)) {
682                 break;
683             }
684         }
685         break;
686
687     case ObjType_L1CNode:
688         for (dest_i = 0; dest_i < count; dest_i++) {
689             assert(objsize >= OBJSIZE_L2CNODE);
690             assert(objsize % OBJSIZE_L2CNODE == 0);
691             temp_cap.u.l1cnode.cnode = lpaddr + dest_i * objsize;
692             temp_cap.u.l1cnode.allocated_bytes = objsize;
693             // XXX: implement CNode cap rights
694             temp_cap.u.l1cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
695             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
696             if (err_is_fail(err)) {
697                 break;
698             }
699         }
700         break;
701
702     case ObjType_L2CNode:
703         for (dest_i = 0; dest_i < count; dest_i++) {
704             temp_cap.u.l2cnode.cnode = lpaddr + dest_i * objsize;
705             // XXX: implement CNode cap rights
706             temp_cap.u.l2cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
707             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
708             if (err_is_fail(err)) {
709                 break;
710             }
711         }
712         break;
713
714     case ObjType_VNode_ARM_l1:
715     {
716         size_t objsize_vnode = vnode_objsize(type);
717
718         for(dest_i = 0; dest_i < count; dest_i++) {
719             // Initialize type specific fields
720             temp_cap.u.vnode_arm_l1.base =
721                 genpaddr + dest_i * objsize_vnode;
722
723
724             // Insert the capability
725             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
726             if (err_is_fail(err)) {
727                 break;
728             }
729         }
730
731         break;
732     }
733
734     case ObjType_VNode_ARM_l2:
735     {
736         size_t objsize_vnode = vnode_objsize(type);
737
738         for(dest_i = 0; dest_i < count; dest_i++) {
739             // Initialize type specific fields
740             temp_cap.u.vnode_arm_l2.base =
741                 genpaddr + dest_i * objsize_vnode;
742
743             // Insert the capability
744             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
745             if (err_is_fail(err)) {
746                 break;
747             }
748         }
749         break;
750     }
751
752     case ObjType_VNode_AARCH64_l0:
753     {
754         size_t objsize_vnode = vnode_objsize(type);
755
756         for(dest_i = 0; dest_i < count; dest_i++) {
757             // Initialize type specific fields
758             temp_cap.u.vnode_aarch64_l0.base =
759                 genpaddr + dest_i * objsize_vnode;
760
761             // Insert the capability
762             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
763             if (err_is_fail(err)) {
764                 break;
765             }
766         }
767
768         break;
769     }
770
771     case ObjType_VNode_AARCH64_l1:
772     {
773         size_t objsize_vnode = vnode_objsize(type);
774
775         for(dest_i = 0; dest_i < count; dest_i++) {
776             // Initialize type specific fields
777             temp_cap.u.vnode_aarch64_l1.base =
778                 genpaddr + dest_i * objsize_vnode;
779
780             // Insert the capability
781             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
782             if (err_is_fail(err)) {
783                 break;
784             }
785         }
786
787         break;
788     }
789
790     case ObjType_VNode_AARCH64_l2:
791     {
792         size_t objsize_vnode = vnode_objsize(type);
793
794         for(dest_i = 0; dest_i < count; dest_i++) {
795             // Initialize type specific fields
796             temp_cap.u.vnode_aarch64_l2.base =
797                 genpaddr + dest_i * objsize_vnode;
798
799             // Insert the capability
800             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
801
802             if (err_is_fail(err)) {
803                 break;
804             }
805         }
806         break;
807     }
808
809     case ObjType_VNode_AARCH64_l3:
810     {
811         size_t objsize_vnode = vnode_objsize(type);
812
813         for(dest_i = 0; dest_i < count; dest_i++) {
814             // Initialize type specific fields
815             temp_cap.u.vnode_aarch64_l3.base =
816                 genpaddr + dest_i * objsize_vnode;
817
818             // Insert the capability
819             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
820             if (err_is_fail(err)) {
821                 break;
822             }
823         }
824         break;
825     }
826
827     case ObjType_VNode_x86_32_ptable:
828     {
829         size_t objsize_vnode = vnode_objsize(type);
830
831         for(dest_i = 0; dest_i < count; dest_i++) {
832             // Initialize type specific fields
833             temp_cap.u.vnode_x86_32_ptable.base =
834                 genpaddr + dest_i * objsize_vnode;
835
836             // Insert the capability
837             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
838             if (err_is_fail(err)) {
839                 break;
840             }
841         }
842         break;
843     }
844
845     case ObjType_VNode_x86_32_pdir:
846     {
847         size_t objsize_vnode = vnode_objsize(type);
848
849         for(dest_i = 0; dest_i < count; dest_i++) {
850             // Initialize type specific fields
851             temp_cap.u.vnode_x86_32_pdir.base =
852                 genpaddr + dest_i * objsize_vnode;
853
854 #if defined(__i386__) && !defined(CONFIG_PAE)
855             // Make it a good PDE by inserting kernel/mem VSpaces
856             lpaddr = gen_phys_to_local_phys(temp_cap.u.vnode_x86_32_pdir.base);
857             paging_x86_32_make_good_pdir(lpaddr);
858 #endif
859
860             // Insert the capability
861             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
862             if (err_is_fail(err)) {
863                 break;
864             }
865         }
866         break;
867     }
868
869     case ObjType_VNode_x86_32_pdpt:
870     {
871         size_t objsize_vnode = vnode_objsize(type);
872
873         for(dest_i = 0; dest_i < count; dest_i++) {
874             // Initialize type specific fields
875             temp_cap.u.vnode_x86_32_pdir.base =
876                 genpaddr + dest_i * objsize_vnode;
877
878 #if defined(__i386__) && defined(CONFIG_PAE)
879             // Make it a good PDPTE by inserting kernel/mem VSpaces
880             lpaddr_t var =
881                 gen_phys_to_local_phys(temp_cap.u.vnode_x86_32_pdpt.base);
882             paging_x86_32_make_good_pdpte(var);
883 #endif
884
885             // Insert the capability
886             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
887             if (err_is_fail(err)) {
888                 break;
889             }
890         }
891         break;
892     }
893
894     case ObjType_VNode_x86_64_ptable:
895     {
896         size_t objsize_vnode = vnode_objsize(type);
897
898         for(dest_i = 0; dest_i < count; dest_i++) {
899             // Initialize type specific fields
900             temp_cap.u.vnode_x86_64_ptable.base =
901                 genpaddr + dest_i * objsize_vnode;
902
903             // Insert the capability
904             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
905             if (err_is_fail(err)) {
906                 break;
907             }
908         }
909         break;
910     }
911
912     case ObjType_VNode_x86_64_pdir:
913     {
914         size_t objsize_vnode = vnode_objsize(type);
915
916         for(dest_i = 0; dest_i < count; dest_i++) {
917             // Initialize type specific fields
918             temp_cap.u.vnode_x86_64_pdir.base =
919                 genpaddr + dest_i * objsize_vnode;
920
921             // Insert the capability
922             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
923             if (err_is_fail(err)) {
924                 break;
925             }
926         }
927         break;
928     }
929
930     case ObjType_VNode_x86_64_pdpt:
931     {
932         size_t objsize_vnode = vnode_objsize(type);
933
934         for(dest_i = 0; dest_i < count; dest_i++) {
935             // Initialize type specific fields
936             temp_cap.u.vnode_x86_64_pdpt.base =
937                 genpaddr + dest_i * objsize_vnode;
938
939             // Insert the capability
940             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
941             if (err_is_fail(err)) {
942                 break;
943             }
944         }
945         break;
946     }
947
948     case ObjType_VNode_x86_64_pml4:
949     {
950         size_t objsize_vnode = vnode_objsize(type);
951
952         for(dest_i = 0; dest_i < count; dest_i++) {
953             // Initialize type specific fields
954             temp_cap.u.vnode_x86_64_pml4.base =
955                 genpaddr + dest_i * objsize_vnode;
956
957 #if defined(__x86_64__) || defined(__k1om__)
958             // Make it a good PML4 by inserting kernel/mem VSpaces
959             lpaddr_t var = gen_phys_to_local_phys(get_address(&temp_cap));
960             paging_x86_64_make_good_pml4(var);
961 #endif
962
963             // Insert the capability
964             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
965             if (err_is_fail(err)) {
966                 break;
967             }
968         }
969
970         break;
971     }
972
973     case ObjType_Dispatcher:
974         assert(OBJSIZE_DISPATCHER >= sizeof(struct dcb));
975
976         for(dest_i = 0; dest_i < count; dest_i++) {
977             // Initialize type specific fields
978             temp_cap.u.dispatcher.dcb = (struct dcb *)
979                 (lvaddr + dest_i * OBJSIZE_DISPATCHER);
980             // Insert the capability
981             err = set_cap(&dest_caps[dest_i].cap, &temp_cap);
982             if (err_is_fail(err)) {
983                 break;
984             }
985         }
986         break;
987
988     case ObjType_ID:
989         // ID type does not refer to a kernel object
990         assert(lpaddr  == 0);
991         assert(size    == 0);
992         assert(objsize == 0);
993         assert(count   == 1);
994
995         // Prevent wrap around
996         if (id_cap_counter >= UINT32_MAX) {
997             return SYS_ERR_ID_SPACE_EXHAUSTED;
998         }
999
1000         // Generate a new ID, core_local_id monotonically increases
1001         temp_cap.u.id.coreid = my_core_id;
1002         temp_cap.u.id.core_local_id = id_cap_counter++;
1003
1004         // Insert the capability
1005         err = set_cap(&dest_caps->cap, &temp_cap);
1006         break;
1007
1008     case ObjType_IO:
1009         temp_cap.u.io.start = 0;
1010         temp_cap.u.io.end   = 65535;
1011         /* fall through */
1012
1013     case ObjType_IRQSrc:
1014         /* Caller has to set vec_start and vec_end */
1015     case ObjType_Kernel:
1016     case ObjType_IPI:
1017     case ObjType_IRQTable:
1018     case ObjType_IRQDest:
1019     case ObjType_EndPoint:
1020     case ObjType_Notify_IPI:
1021     case ObjType_PerfMon:
1022         // These types do not refer to a kernel object
1023         assert(lpaddr  == 0);
1024         assert(size    == 0);
1025         assert(objsize == 0);
1026         assert(count   == 1);
1027
1028         // Insert the capability
1029         err = set_cap(&dest_caps->cap, &temp_cap);
1030         if (err_is_ok(err)) {
1031             dest_i = 1;
1032         }
1033         break;
1034
1035     case ObjType_KernelControlBlock:
1036         assert(OBJSIZE_KCB >= sizeof(struct kcb));
1037
1038         for(size_t i = 0; i < count; i++) {
1039             // Initialize type specific fields
1040             temp_cap.u.kernelcontrolblock.kcb = (struct kcb *)
1041                 (lvaddr + i * OBJSIZE_KCB);
1042             // Insert the capability
1043             err = set_cap(&dest_caps[i].cap, &temp_cap);
1044             if (err_is_fail(err)) {
1045                 return err;
1046             }
1047         }
1048         return SYS_ERR_OK;
1049
1050     default:
1051         panic("Unhandled capability type or capability of this type cannot"
1052               " be created");
1053     }
1054
1055     if (err_is_fail(err)) {
1056         // Revert the partially initialized caps to zero
1057         for (size_t i = 0; i < dest_i; i++) {
1058             memset(&dest_caps[i], 0, sizeof(dest_caps[i]));
1059         }
1060         return err;
1061     }
1062     else {
1063         // Set the owner for all the new caps
1064         for (size_t i = 0; i < dest_i; i++) {
1065             dest_caps[i].mdbnode.owner = owner;
1066         }
1067     }
1068
1069     return SYS_ERR_OK;
1070 }
1071
1072 /**
1073  * Look up a capability in two-level cspace rooted at `rootcn`.
1074  */
1075 errval_t caps_lookup_slot(struct capability *rootcn, capaddr_t cptr,
1076                           uint8_t level, struct cte **ret, CapRights rights)
1077 {
1078     TRACE(KERNEL, CAP_LOOKUP_SLOT, 0);
1079
1080     cslot_t l1index, l2index;
1081     l1index = (cptr >> L2_CNODE_BITS) & MASK(CPTR_BITS-L2_CNODE_BITS);
1082     l2index = cptr & MASK(L2_CNODE_BITS);
1083
1084     assert(ret != NULL);
1085     assert(rootcn != NULL);
1086
1087     if (level > 2) {
1088         debug(SUBSYS_CAPS, "%s called with level=%hhu, from %p\n",
1089                 __FUNCTION__, level,
1090                 (void*)kernel_virt_to_elf_addr(__builtin_return_address(0)));
1091         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1092         return SYS_ERR_CAP_LOOKUP_DEPTH;
1093     }
1094     assert(level <= 2);
1095
1096     // level 0 means that we do not do any resolution and just return the cte
1097     // for rootcn.
1098     if (level == 0) {
1099         *ret = cte_for_cap(rootcn);
1100         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1101         return SYS_ERR_OK;
1102     }
1103
1104     if (rootcn->type != ObjType_L1CNode) {
1105         debug(SUBSYS_CAPS, "%s: rootcn->type = %d, called from %p\n",
1106                 __FUNCTION__, rootcn->type,
1107                 (void*)kernel_virt_to_elf_addr(__builtin_return_address(0)));
1108         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1109         // XXX: think about errors
1110         return SYS_ERR_CNODE_TYPE;
1111     }
1112     assert(rootcn->type == ObjType_L1CNode);
1113
1114     if (l1index >= cnode_get_slots(rootcn)) {
1115         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1116         debug(SUBSYS_CAPS, "%s: l1index = %"PRIuCSLOT", slots= %zu\n",
1117                 __FUNCTION__, l1index, cnode_get_slots(rootcn));
1118         return SYS_ERR_L1_CNODE_INDEX;
1119     }
1120
1121     /* Apply rights to L1 CNode */
1122     if ((rootcn->rights & rights) != rights) {
1123         debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
1124               "Passed rights = %u, cnode_cap->rights = %u\n",
1125               rights, rootcn->rights);
1126         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1127         return SYS_ERR_CNODE_RIGHTS;
1128     }
1129
1130     struct cte *l2cnode = caps_locate_slot(get_address(rootcn), l1index);
1131
1132     // level == 1 means that we terminate after looking up the slot in the L1
1133     // cnode.
1134     if (level == 1) {
1135         if (l2cnode->cap.type == ObjType_Null) {
1136             TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1137             return SYS_ERR_CAP_NOT_FOUND;
1138         }
1139         *ret = l2cnode;
1140         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1141         return SYS_ERR_OK;
1142     }
1143
1144     // L2 CNode in given L1 slot does not exist
1145     if (l2cnode->cap.type == ObjType_Null) {
1146         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1147         debug(SUBSYS_CAPS, "%s: l2cnode is NULL\n", __FUNCTION__);
1148         return SYS_ERR_CNODE_NOT_FOUND;
1149     }
1150     if (l2cnode->cap.type != ObjType_L2CNode) {
1151         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1152         debug(SUBSYS_CAPS, "%s: l2cnode->type = %d\n", __FUNCTION__,
1153                l2cnode->cap.type);
1154         return SYS_ERR_CNODE_TYPE;
1155     }
1156     assert(l2cnode->cap.type == ObjType_L2CNode);
1157
1158     assert(l2index < L2_CNODE_SLOTS);
1159
1160     /* Apply rights to L2 CNode */
1161     if ((l2cnode->cap.rights & rights) != rights) {
1162         debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
1163               "Passed rights = %u, cnode_cap->rights = %u\n",
1164               rights, l2cnode->cap.rights);
1165         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1166         return SYS_ERR_CNODE_RIGHTS;
1167     }
1168
1169     struct cte *cte = caps_locate_slot(get_address(&l2cnode->cap), l2index);
1170     if (cte->cap.type == ObjType_Null) {
1171         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1172         return SYS_ERR_CAP_NOT_FOUND;
1173     }
1174
1175     *ret = cte;
1176
1177     TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1178     return SYS_ERR_OK;
1179 }
1180
1181 /**
1182  * Wrapper for caps_lookup_slot returning capability instead of cte.
1183  */
1184 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
1185                          uint8_t level, struct capability **ret, CapRights rights)
1186 {
1187     TRACE(KERNEL, CAP_LOOKUP_CAP, 0);
1188
1189     struct cte *ret_cte;
1190     errval_t err = caps_lookup_slot(cnode_cap, cptr, level, &ret_cte, rights);
1191     if (err_is_fail(err)) {
1192         return err;
1193     }
1194     *ret = &ret_cte->cap;
1195     TRACE(KERNEL, CAP_LOOKUP_CAP, 1);
1196     return SYS_ERR_OK;
1197 }
1198
1199 /**
1200  * \brief Create a capability from an existing capability metadata.
1201  *
1202  * Used when sending capabilities across cores. The metadata is sent across
1203  * cores and the receiving monitor can create the new capability on its core.
1204  *
1205  * \bug Does not check that supplied owner matches existing copies of cap.
1206  */
1207 errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
1208                                    int cnode_level, cslot_t dest_slot, coreid_t owner,
1209                                    struct capability *src)
1210 {
1211     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 0);
1212     errval_t err;
1213     struct capability *cnode;
1214     err = caps_lookup_cap(root, cnode_cptr, cnode_level, &cnode,
1215                           CAPRIGHTS_READ_WRITE);
1216     if (err_is_fail(err)) {
1217         return err_push(err, SYS_ERR_SLOT_LOOKUP_FAIL);
1218     }
1219     if (cnode->type != ObjType_L1CNode &&
1220         cnode->type != ObjType_L2CNode)
1221     {
1222         return SYS_ERR_CNODE_TYPE;
1223     }
1224
1225     struct cte *dest = caps_locate_slot(get_address(cnode), dest_slot);
1226
1227     err = set_cap(&dest->cap, src);
1228     if (err_is_fail(err)) {
1229         return err;
1230     }
1231
1232     dest->mdbnode.owner = owner;
1233
1234     err = mdb_insert(dest);
1235     assert(err_is_ok(err));
1236
1237     struct cte *neighbour = NULL;
1238     if (!neighbour
1239         && (neighbour = mdb_predecessor(dest))
1240         && !is_copy(&dest->cap, &neighbour->cap))
1241     {
1242         neighbour = NULL;
1243     }
1244     if (!neighbour
1245         && (neighbour = mdb_successor(dest))
1246         && !is_copy(&dest->cap, &neighbour->cap))
1247     {
1248         neighbour = NULL;
1249     }
1250
1251     if (neighbour) {
1252         assert(!neighbour->mdbnode.in_delete);
1253         assert(neighbour->mdbnode.owner == owner);
1254 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
1255         CP_ATTR(locked);
1256         CP_ATTR(remote_copies);
1257         CP_ATTR(remote_ancs);
1258         CP_ATTR(remote_descs);
1259 #undef CP_ATTR
1260     }
1261     else {
1262         dest->mdbnode.locked = false;
1263         if (owner != my_core_id) {
1264             // For foreign caps it does not really matter if ancestors or
1265             // descendants exist
1266             dest->mdbnode.remote_copies = true;
1267             dest->mdbnode.remote_ancs = false;
1268             dest->mdbnode.remote_descs = false;
1269         }
1270         else {
1271             // We just created a new copy of a owned capability from nothing.
1272             // This is either caused by a retype, or by sharing a capability
1273             // that does not care about locality.
1274             // XXX: This should probably be done more explicitly -MN
1275             if (distcap_needs_locality(dest->cap.type)) {
1276                 // Retype, so have ancestors and no descendants
1277                 dest->mdbnode.remote_copies = false;
1278                 dest->mdbnode.remote_ancs = true;
1279                 dest->mdbnode.remote_descs = false;
1280             }
1281             else {
1282                 dest->mdbnode.remote_copies = false;
1283                 dest->mdbnode.remote_ancs = false;
1284                 dest->mdbnode.remote_descs = false;
1285             }
1286         }
1287     }
1288
1289     TRACE_CAP_MSG("created", dest);
1290
1291     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 1);
1292     return SYS_ERR_OK;
1293 }
1294
1295 //{{{1 Capability creation
1296
1297 /// check arguments, return true iff ok
1298 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
1299 #ifndef NDEBUG
1300 static bool check_caps_create_arguments(enum objtype type,
1301                                         size_t bytes, size_t objsize,
1302                                         bool exact)
1303 {
1304     gensize_t base_mask = BASE_PAGE_MASK;
1305     if (type_is_vnode(type)) {
1306         base_mask = vnode_objsize(type) - 1;
1307     }
1308     /* mappable types need to be at least BASE_PAGE_SIZEd */
1309     if (type_is_mappable(type)) {
1310         /* source size not multiple of or not aligned to BASE_PAGE_SIZE */
1311         if (bytes & base_mask) {
1312             debug(SUBSYS_CAPS, "source size not multiple of BASE_PAGE_SIZE\n");
1313             return false;
1314         }
1315         /* objsize > 0 and not multiple of BASE_PAGE_SIZE */
1316         if (objsize > 0 && objsize & base_mask) {
1317             debug(SUBSYS_CAPS, "object size not multiple of BASE_PAGE_SIZE\n");
1318             return false;
1319         }
1320
1321         /* check that bytes can be evenly divided into objsize sized chunks */
1322         if (exact && bytes > 0 && objsize > 0) {
1323             if (bytes % objsize) {
1324                 debug(SUBSYS_CAPS, "source size cannot be evenly divided into object size-sized chunks\n");
1325             }
1326             return bytes % objsize == 0;
1327         }
1328
1329         return true;
1330     }
1331
1332     if (type == ObjType_L1CNode) {
1333         /* L1 CNode minimum size is OBJSIZE_L2CNODE */
1334         if (bytes < OBJSIZE_L2CNODE || objsize < OBJSIZE_L2CNODE) {
1335             debug(SUBSYS_CAPS, "source size or L1 CNode objsize < OBJSIZE_L2CNODE\n");
1336             return false;
1337         }
1338         /* check that bytes can be evenly divided into L1 CNodes of objsize */
1339         if (exact && (bytes % objsize != 0)) {
1340             debug(SUBSYS_CAPS, "source not evenly divisible into L1 CNodes of objsize\n");
1341             return false;
1342         }
1343         /* L1 CNode size must be multiple of 1UL << OBJBITS_CTE */
1344         return objsize % (1UL << OBJBITS_CTE) == 0;
1345     }
1346
1347     if (type == ObjType_L2CNode) {
1348         /* L2 CNode size must be OBJSIZE_L2CNODE */
1349         if (bytes < OBJSIZE_L2CNODE || objsize != OBJSIZE_L2CNODE) {
1350             debug(SUBSYS_CAPS, "source size < or L2 CNode objsize != OBJSIZE_L2CNODE\n");
1351             return false;
1352         }
1353         if (exact && (bytes % objsize != 0)) {
1354             debug(SUBSYS_CAPS, "source not evenly divisible into L2 CNodes of objsize\n");
1355             return false;
1356         }
1357         return true;
1358     }
1359
1360     /* special case Dispatcher which is 1kB right now */
1361     if (type == ObjType_Dispatcher) {
1362         if (bytes & (OBJSIZE_DISPATCHER - 1)) {
1363             return false;
1364         }
1365         if (objsize > 0 && objsize != OBJSIZE_DISPATCHER) {
1366             return false;
1367         }
1368
1369         return true;
1370     }
1371
1372     // All other types do not need special alignments/offsets
1373     return true;
1374 }
1375 #endif
1376
1377 /** Create caps to new kernel objects.
1378  * This takes the size of the memory region in bytes, and the size of
1379  * individual objects in bytes. The following needs to hold:
1380  *      bytes % objbytes == 0
1381  */
1382 errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bytes,
1383                          size_t objsize, coreid_t owner, struct cte *caps)
1384 {
1385     TRACE(KERNEL, CAP_CREATE_NEW, 0);
1386     /* Parameter checking */
1387     assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1388     debug(SUBSYS_CAPS, "caps_create_new: type = %d, addr = %#"PRIxLPADDR
1389             ", bytes=%zu, objsize=%zu\n", type, addr, bytes, objsize);
1390     assert(check_caps_create_arguments(type, bytes, objsize, false));
1391     assert(addr == 0 || check_caps_create_arguments(type, bytes, objsize, true));
1392
1393     size_t numobjs = caps_max_numobjs(type, bytes, objsize);
1394     assert(numobjs > 0);
1395     // XXX: Dispatcher creation is kind of hacky right now :(
1396     // Consider allowing non-mappable types to be < BASE_PAGE_SIZE
1397     //if (type == ObjType_Dispatcher) {
1398     //    numobjs = 1;
1399     //}
1400
1401     /* Create the new capabilities */
1402     errval_t err = caps_create(type, addr, bytes, objsize, numobjs, owner, caps);
1403     if (err_is_fail(err)) {
1404         return err;
1405     }
1406
1407     // Handle the mapping database
1408     set_init_mapping(caps, numobjs);
1409
1410     TRACE_CAP_MSG("created", &caps[0]);
1411
1412     TRACE(KERNEL, CAP_CREATE_NEW, 1);
1413     return SYS_ERR_OK;
1414 }
1415
1416 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
1417 /// Retype caps
1418 /// Create `count` new caps of `type` from `offset` in src, and put them in
1419 /// `dest_cnode` starting at `dest_slot`.
1420 errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
1421                      struct capability *dest_cnode, cslot_t dest_slot,
1422                      struct cte *src_cte, gensize_t offset,
1423                      bool from_monitor)
1424 {
1425     TRACE(KERNEL, CAP_RETYPE, 0);
1426     size_t maxobjs;
1427     genpaddr_t base = 0;
1428     gensize_t size = 0;
1429     errval_t err;
1430     bool do_range_check = false;
1431     struct capability *src_cap = &src_cte->cap;
1432
1433     /* Parameter checking */
1434     assert(type != ObjType_Null);
1435     assert(type < ObjType_Num);
1436     if (type == ObjType_Null || type >= ObjType_Num) {
1437         return SYS_ERR_INVALID_RETYPE;
1438     }
1439
1440     debug(SUBSYS_CAPS, "%s: Retyping to type=%d, from offset=%" PRIuGENSIZE
1441             ", objsize=%" PRIuGENSIZE ", count=%zu\n",
1442             __FUNCTION__, type, offset, objsize, count);
1443
1444     /* check that offset into source cap is multiple of BASE_PAGE_SIZE */
1445     if (src_cap->type != ObjType_IRQSrc && offset % BASE_PAGE_SIZE != 0) {
1446         return SYS_ERR_RETYPE_INVALID_OFFSET;
1447     }
1448     assert(offset % BASE_PAGE_SIZE == 0 || src_cap->type == ObjType_IRQSrc);
1449
1450     // check that size is multiple of BASE_PAGE_SIZE for mappable types
1451     gensize_t base_size = BASE_PAGE_SIZE;
1452     if (type_is_vnode(type)) {
1453         base_size = vnode_objsize(type);
1454     }
1455     if (type_is_mappable(type) && objsize % base_size != 0) {
1456         debug(SUBSYS_CAPS, "%s: objsize = %"PRIuGENSIZE"\n", __FUNCTION__, objsize);
1457         return SYS_ERR_INVALID_SIZE;
1458     }
1459     else if (type == ObjType_L1CNode && objsize % OBJSIZE_L2CNODE != 0)
1460     {
1461         printk(LOG_WARN, "%s: CNode: objsize = %" PRIuGENSIZE "\n", __FUNCTION__, objsize);
1462         return SYS_ERR_INVALID_SIZE;
1463     }
1464     else if (type == ObjType_L2CNode && objsize != OBJSIZE_L2CNODE)
1465     {
1466         printk(LOG_WARN, "%s: L2CNode: objsize = %"PRIuGENSIZE"\n", __FUNCTION__, objsize);
1467         return SYS_ERR_INVALID_SIZE;
1468     }
1469     assert((type_is_mappable(type) && objsize % base_size == 0) ||
1470            (type == ObjType_L1CNode && objsize % OBJSIZE_L2CNODE == 0 &&
1471             objsize >= OBJSIZE_L2CNODE) ||
1472            (type == ObjType_L2CNode && objsize == OBJSIZE_L2CNODE) ||
1473            !type_is_mappable(type));
1474
1475     /* No explicit retypes to Mapping allowed */
1476     if (type_is_mapping(type)) {
1477         return SYS_ERR_RETYPE_MAPPING_EXPLICIT;
1478     }
1479
1480
1481     TRACE_CAP_MSG("retyping", src_cte);
1482
1483     /* Check retypability */
1484     err = is_retypeable(src_cte, src_cap->type, type, from_monitor);
1485     if (err_is_fail(err)) {
1486         if (err_no(err) != SYS_ERR_REVOKE_FIRST) {
1487             printk(LOG_NOTE, "caps_retype: is_retypeable failed: %"PRIuERRV"\n", err);
1488             debug(SUBSYS_CAPS, "caps_retype: is_retypeable failed\n");
1489             return err;
1490         } else {
1491             debug(SUBSYS_CAPS,
1492                     "caps_retype: is_retypeable() returned SYS_ERR_REVOKE_FIRST, doing range check\n");
1493             // We handle err_revoke_first fine-grained checking below, as it
1494             // might happen for non-overlapping regions.
1495
1496             // TODO: move the range checking into is_retypeable() or even
1497             // is_revoked_first(), -SG 2016-04-18
1498             do_range_check = true;
1499         }
1500     }
1501     // from here: src cap type is one of these.
1502     assert(src_cap->type == ObjType_PhysAddr ||
1503            src_cap->type == ObjType_RAM ||
1504            src_cap->type == ObjType_Dispatcher ||
1505            src_cap->type == ObjType_Frame ||
1506            src_cap->type == ObjType_DevFrame ||
1507            src_cap->type == ObjType_IRQSrc);
1508
1509     if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
1510         base = get_address(src_cap);
1511         size = get_size(src_cap);
1512     }
1513
1514     maxobjs = caps_max_numobjs(type, get_size(src_cap), objsize);
1515     debug(SUBSYS_CAPS, "maximum possible new object count: %zu\n", maxobjs);
1516
1517     if (maxobjs == 0) {
1518         debug(SUBSYS_CAPS, "caps_retype: maxobjs == 0\n");
1519         return SYS_ERR_INVALID_SIZE;
1520     }
1521
1522     if (count > maxobjs) {
1523         debug(SUBSYS_CAPS, "caps_retype: maxobjs = %zu, count = %zu\n", maxobjs, count);
1524         return SYS_ERR_RETYPE_INVALID_COUNT;
1525     }
1526     // from here: count <= maxobjs
1527     assert(count <= maxobjs);
1528     // make sure nobody calls with the old behaviour
1529     if (count == 0) {
1530         return SYS_ERR_RETYPE_INVALID_COUNT;
1531     }
1532     assert(count > 0);
1533
1534     /* check that we can create `count` objs from `offset` in source, and
1535      * update base accordingly */
1536     if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
1537         // TODO: convince ourselves that this is the only condition on offset
1538         if (offset + count * objsize > get_size(src_cap)) {
1539             debug(SUBSYS_CAPS, "caps_retype: cannot create all %zu objects"
1540                     " of size 0x%" PRIxGENSIZE " from offset 0x%" PRIxGENSIZE "\n",
1541                     count, objsize, offset);
1542             return SYS_ERR_RETYPE_INVALID_OFFSET;
1543         }
1544         // adjust base address for new objects
1545         base += offset;
1546
1547         // Check whether we got SYS_ERR_REVOKE_FIRST because of
1548         // non-overlapping child
1549         if (do_range_check) {
1550             int find_range_result = 0;
1551             struct cte *found_cte = NULL;
1552             err = mdb_find_range(get_type_root(src_cap->type), base, objsize * count,
1553                     MDB_RANGE_FOUND_SURROUNDING, &found_cte, &find_range_result);
1554             // this should never return an error unless we mess up the
1555             // non-user supplied arguments
1556             if (err_is_fail(err)) {
1557                 printk(LOG_WARN, "mdb_find_range returned: %"PRIuERRV"\n", err);
1558             }
1559             assert(err_is_ok(err));
1560             // return REVOKE_FIRST, if we found a cap inside the region
1561             // (FOUND_INNER == 2) or overlapping the region (FOUND_PARTIAL == 3)
1562             if (find_range_result >= MDB_RANGE_FOUND_INNER) {
1563                 debug(SUBSYS_CAPS,
1564                     "%s: found existing region inside, or overlapping requested region:\n",
1565                     __FUNCTION__);
1566                 debug(SUBSYS_CAPS, "%s: our region: %#"PRIxGENPADDR"--%#"PRIxGENPADDR"\n",
1567                         __FUNCTION__, base, base+objsize*count);
1568                 if (found_cte && kernel_loglevel >= LOG_DEBUG &&
1569                     kernel_log_subsystem_mask & SUBSYS_CAPS)
1570                 {
1571                     char capbuf[128];
1572                     sprint_cap(capbuf, 128, &found_cte->cap);
1573                     printk(LOG_NOTE, "%s: cap=%s\n", __FUNCTION__, capbuf);
1574                     if (type_is_mapping(found_cte->cap.type)) {
1575                         sprint_cap(capbuf, 128, found_cte->cap.u.frame_mapping.cap);
1576                         printk(LOG_NOTE, "%s: ... is mapping for cap=%s\n",
1577                                 __FUNCTION__, capbuf);
1578                     }
1579                     assert(get_address(&found_cte->cap) >= base &&
1580                            get_address(&found_cte->cap) < base+objsize*count);
1581                 }
1582                 return SYS_ERR_REVOKE_FIRST;
1583             }
1584             // return REVOKE_FIRST, if we found a cap that isn't our source
1585             // (or a copy of our source) covering the whole requested region.
1586             else if (find_range_result == MDB_RANGE_FOUND_SURROUNDING &&
1587                      !is_copy(&found_cte->cap, src_cap))
1588             {
1589                 debug(SUBSYS_CAPS,
1590                        "%s: found non source region fully covering requested region\n",
1591                        __FUNCTION__);
1592                 return SYS_ERR_REVOKE_FIRST;
1593             }
1594         }
1595     }
1596
1597     /* check that destination slots all fit within target cnode */
1598     if (dest_slot + count > cnode_get_slots(dest_cnode)) {
1599         debug(SUBSYS_CAPS, "caps_retype: dest slots don't fit in cnode\n");
1600         return SYS_ERR_SLOTS_INVALID;
1601     }
1602
1603     /* check that destination slots are all empty */
1604     debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1605           " dest_slot %d\n",
1606           get_address(dest_cnode), (int)dest_slot);
1607     for (cslot_t i = 0; i < count; i++) {
1608         if (caps_locate_slot(get_address(dest_cnode), dest_slot + i)->cap.type
1609             != ObjType_Null) {
1610             debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1611                   (int)(dest_slot + i));
1612             return SYS_ERR_SLOTS_IN_USE;
1613         }
1614     }
1615
1616     /* Check that L1 CNode is destination when creating L2 CNode */
1617     if (type == ObjType_L2CNode) {
1618         debug(SUBSYS_CAPS, "caps_retype: check that dest cnode is L1"
1619                            " when creating L2 CNodes\n");
1620         if (dest_cnode->type != ObjType_L1CNode &&
1621             dest_cnode->type != ObjType_L2CNode)
1622         {
1623             panic("L2 CNode can only be created in L1 or L2 CNode\n");
1624         }
1625     }
1626
1627     // IRQSrc specific checks
1628     uint64_t vec_start_new = offset;
1629     uint64_t vec_end_new = objsize;
1630     if(src_cap->type == ObjType_IRQSrc){
1631
1632         // Check new range is valid
1633         if(vec_start_new > vec_end_new){
1634             return SYS_ERR_RETYPE_INVALID_OFFSET;
1635         }
1636         
1637         // Check vec_start_new in range
1638         if(!(src_cap->u.irqsrc.vec_start <= vec_start_new &&
1639                 vec_start_new <= src_cap->u.irqsrc.vec_end)){
1640             return SYS_ERR_RETYPE_INVALID_OFFSET;
1641         }
1642
1643         // Check vec_end_new in range
1644         if(!(src_cap->u.irqsrc.vec_start <= vec_end_new &&
1645                 vec_end_new <= src_cap->u.irqsrc.vec_end)){
1646             return SYS_ERR_RETYPE_INVALID_OBJSIZE;
1647         }
1648     }
1649
1650
1651     /* create new caps */
1652     struct cte *dest_cte =
1653         caps_locate_slot(get_address(dest_cnode), dest_slot);
1654     if(type == ObjType_IRQSrc){
1655         // Pass special arguments
1656         err = caps_create(type, 0, 0, 0, 1, my_core_id, dest_cte);
1657         if(err_is_ok(err)){
1658             dest_cte->cap.u.irqsrc.vec_start = vec_start_new;
1659             dest_cte->cap.u.irqsrc.vec_end = vec_end_new;
1660         }
1661     } else {
1662         err = caps_create(type, base, size, objsize, count, my_core_id, dest_cte);
1663     }
1664     if (err_is_fail(err)) {
1665         debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
1666         return err_push(err, SYS_ERR_RETYPE_CREATE);
1667     }
1668
1669     /* special initialisation for endpoint caps */
1670     if (type == ObjType_EndPoint) {
1671         assert(src_cap->type == ObjType_Dispatcher);
1672         assert(count == 1);
1673         struct capability *dest_cap = &dest_cte->cap;
1674         dest_cap->u.endpoint.listener = src_cap->u.dispatcher.dcb;
1675     }
1676
1677     /* Handle mapping */
1678     for (size_t i = 0; i < count; i++) {
1679         mdb_insert(&dest_cte[i]);
1680     }
1681
1682 #ifdef TRACE_PMEM_CAPS
1683     for (size_t i = 0; i < count; i++) {
1684         TRACE_CAP_MSG("created", &dest_cte[i]);
1685     }
1686 #endif
1687
1688     TRACE(KERNEL, CAP_RETYPE, 1);
1689     return SYS_ERR_OK;
1690 }
1691
1692 /// Check the validity of a retype operation
1693 errval_t is_retypeable(struct cte *src_cte, enum objtype src_type,
1694                        enum objtype dest_type, bool from_monitor)
1695 {
1696     if (!is_well_founded(src_type, dest_type)) {
1697         return SYS_ERR_INVALID_RETYPE;
1698     } else if (!is_revoked_first(src_cte, src_type)){
1699         //printf("err_revoke_first: (%p, %d, %d)\n", src_cte, src_type, dest_type);
1700         return SYS_ERR_REVOKE_FIRST;
1701     } else if (dest_type == ObjType_EndPoint && src_cte->mdbnode.owner == my_core_id) {
1702         // XXX: because of the current "multi-retype" hack for endpoints, a
1703         // dispatcher->endpoint retype can happen irrespective of the existence
1704         // of descendants on any core.
1705         // However, we only do this for locally owned caps as the owner should
1706         // be notified that the cap has remote descendants
1707         return SYS_ERR_OK;
1708     } else if (!from_monitor && (src_cte->mdbnode.owner != my_core_id
1709                                  || src_cte->mdbnode.remote_descs)) {
1710         return SYS_ERR_RETRY_THROUGH_MONITOR;
1711     } else {
1712         return SYS_ERR_OK;
1713     }
1714 }
1715
1716 /// Create copies to a slot within a cnode
1717 errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
1718                             struct cte *src_cte, bool mint, uintptr_t param1,
1719                             uintptr_t param2)
1720 {
1721     /* Parameter Checking */
1722     assert(dest_cnode_cte->cap.type == ObjType_L1CNode ||
1723            dest_cnode_cte->cap.type == ObjType_L2CNode);
1724
1725     // only allow L2 CNodes and BSP KCB in L1 CNode
1726     // XXX: BSPKCB should not be in rootcn...
1727     if (dest_cnode_cte->cap.type == ObjType_L1CNode &&
1728         src_cte->cap.type != ObjType_L2CNode &&
1729         src_cte->cap.type != ObjType_KernelControlBlock)
1730     {
1731         printk(LOG_WARN, "trying to copy cap type %d into cap type %d\n",
1732                 src_cte->cap.type, dest_cnode_cte->cap.type);
1733         return SYS_ERR_DEST_TYPE_INVALID;
1734     }
1735
1736     struct cte *dest_cte;
1737     dest_cte = caps_locate_slot(get_address(&dest_cnode_cte->cap), dest_slot);
1738     return caps_copy_to_cte(dest_cte, src_cte, mint, param1, param2);
1739
1740 }
1741
1742 /// Create copies to a cte
1743 STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
1744 errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
1745                           uintptr_t param1, uintptr_t param2)
1746 {
1747     errval_t err;
1748     /* Parameter checking */
1749     // Null checking
1750     assert(dest_cte != NULL);
1751     assert(src_cte != NULL);
1752
1753     struct capability *src_cap  = &src_cte->cap;
1754     struct capability *dest_cap = &dest_cte->cap;
1755     // NULL caps cannot be copied/minted
1756     if (src_cap->type == ObjType_Null) {
1757         return SYS_ERR_CAP_NOT_FOUND;
1758     }
1759     // Parameters should be 0 if not minting
1760     if (!mint) {
1761         assert(param1 == 0);
1762         assert(param2 == 0);
1763     }
1764
1765     assert(!src_cte->mdbnode.in_delete);
1766
1767     /* Insert #source_cap into #dest_cap */
1768     err = set_cap(dest_cap, src_cap);
1769     if (err_is_fail(err)) {
1770         return err;
1771     }
1772
1773     /* Transfer MDB attributes that must be equal for all copies */
1774 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1775     CP_ATTR(owner);
1776     CP_ATTR(locked);
1777     CP_ATTR(remote_copies);
1778     CP_ATTR(remote_ancs);
1779     CP_ATTR(remote_descs);
1780 #undef CP_ATTR
1781
1782     /* Copy is done */
1783     if(!mint) {
1784         TRACE_CAP_MSG("copied to", dest_cte);
1785         // Handle mapping here only for non-mint operations
1786         // (mint can change eq fields which would make the early insertion
1787         // invalid in some cases)
1788         mdb_insert(dest_cte);
1789         return SYS_ERR_OK;
1790     }
1791     else {
1792         TRACE_CAP_MSG("minting to", dest_cte);
1793     }
1794
1795     /* For minting, set the specified parameters */
1796     // Process source-specific parameters for minting
1797     // XXX: If failure, revert the insertion
1798     switch(src_cap->type) {
1799     case ObjType_EndPoint:
1800         // XXX: FIXME: check that buffer offset lies wholly within the disp frame
1801         // can't easily enforce this here, because the dispatcher frame may not
1802         // yet be setup
1803 /*        if (param1 < sizeof(struct dispatcher) ||
1804             dest_cap->u.endpoint.listener->disp == NULL ||
1805             param2 < IDC_RECV_LENGTH ||
1806             param1 + sizeof(struct idc_endpoint) + param2 * sizeof(uintptr_t) >
1807             (1UL << dest_cap->u.endpoint.listener->disp_cte.cap.u.frame.bits)) {
1808             return SYS_ERR_INVALID_EPBUF;
1809         }*/
1810         if (param2 < LMP_RECV_HEADER_LENGTH) {
1811             return SYS_ERR_INVALID_EPLEN;
1812         }
1813         dest_cap->u.endpoint.epoffset = param1;
1814         dest_cap->u.endpoint.epbuflen = param2;
1815         break;
1816
1817     case ObjType_IO:
1818         if(src_cap->u.io.start  <= param1) {
1819             dest_cap->u.io.start = param1;
1820         }
1821         if(src_cap->u.io.end  >= param2) {
1822             dest_cap->u.io.end = param2;
1823         }
1824         break;
1825
1826     default:
1827         // Unhandled source type for mint
1828         return SYS_ERR_INVALID_SOURCE_TYPE;
1829     }
1830
1831     // Insert after doing minting operation
1832     mdb_insert(dest_cte);
1833
1834     return SYS_ERR_OK;
1835 }