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