aefbaf682e0405f4448f7d16378b821acff97eaf
[barrelfish] / kernel / capabilities.c
1 /**
2  * \file
3  * \brief Kernel capability management implementation.
4  */
5
6 /*
7  * Copyright (c) 2007-2012,2015, ETH Zurich.
8  * Copyright (c) 2015, 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 #ifdef TRACE_PMEM_CAPS
37 uint64_t   trace_types_enabled = TRACE_TYPES_ENABLED_INITIAL;
38 genpaddr_t TRACE_PMEM_BEGIN    = TRACE_PMEM_BEGIN_INITIAL;
39 gensize_t  TRACE_PMEM_SIZE     = TRACE_PMEM_SIZE_INITIAL;
40
41 void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
42 {
43     if (types) {
44         trace_types_enabled = types;
45         TRACE_PMEM_BEGIN = start;
46         TRACE_PMEM_SIZE = size;
47     } else {
48         trace_types_enabled = 0;
49     }
50 }
51 #endif
52
53 struct capability monitor_ep;
54
55 STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
56 int sprint_cap(char *buf, size_t len, struct capability *cap)
57 {
58     switch (cap->type) {
59     case ObjType_PhysAddr:
60         return snprintf(buf, len,
61                         "physical address range cap (0x%" PRIxGENPADDR ":0x%zx)",
62                         cap->u.physaddr.base, cap->u.physaddr.bytes);
63
64     case ObjType_RAM:
65         return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":0x%zx)",
66                         cap->u.ram.base, cap->u.ram.bytes);
67
68     case ObjType_CNode: {
69         int ret = snprintf(buf, len, "CNode cap "
70                            "(bits %u, rights mask 0x%" PRIxCAPRIGHTS ")",
71                            cap->u.cnode.bits, cap->u.cnode.rightsmask);
72         if (cap->u.cnode.guard_size != 0 && ret < len) {
73             ret += snprintf(&buf[ret], len - ret, " (guard 0x%" PRIxCADDR ":%u)",
74                             cap->u.cnode.guard, cap->u.cnode.guard_size);
75         }
76         return ret;
77     }
78
79     case ObjType_Dispatcher:
80         return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
81
82     case ObjType_Frame:
83         return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":0x%zx)",
84                         cap->u.frame.base, cap->u.frame.bytes);
85
86     case ObjType_DevFrame:
87         return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":0x%zx)",
88                         cap->u.frame.base, cap->u.devframe.bytes);
89
90     case ObjType_VNode_ARM_l1:
91         return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
92                         cap->u.vnode_arm_l1.base);
93
94     case ObjType_VNode_ARM_l2:
95         return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
96                         cap->u.vnode_arm_l2.base);
97
98     case ObjType_VNode_AARCH64_l1:
99         return snprintf(buf, len, "AARCH64 L1 table at 0x%" PRIxGENPADDR,
100                         cap->u.vnode_aarch64_l1.base);
101
102     case ObjType_VNode_AARCH64_l2:
103         return snprintf(buf, len, "AARCH64 L2 table at 0x%" PRIxGENPADDR,
104                         cap->u.vnode_aarch64_l2.base);
105
106     case ObjType_VNode_AARCH64_l3:
107         return snprintf(buf, len, "AARCH64 L3 table at 0x%" PRIxGENPADDR,
108                         cap->u.vnode_aarch64_l3.base);
109
110     case ObjType_VNode_x86_32_ptable:
111         return snprintf(buf, len, "x86_32 Page table at 0x%" PRIxGENPADDR,
112                         cap->u.vnode_x86_32_ptable.base);
113
114     case ObjType_VNode_x86_32_pdir:
115         return snprintf(buf, len, "x86_32 Page directory at 0x%" PRIxGENPADDR,
116                         cap->u.vnode_x86_32_pdir.base);
117
118     case ObjType_VNode_x86_32_pdpt:
119         return snprintf(buf, len, "x86_32 PDPT at 0x%" PRIxGENPADDR,
120                         cap->u.vnode_x86_32_pdpt.base);
121
122     case ObjType_VNode_x86_64_ptable:
123         return snprintf(buf, len, "x86_64 Page table at 0x%" PRIxGENPADDR,
124                         cap->u.vnode_x86_64_ptable.base);
125
126     case ObjType_VNode_x86_64_pdir:
127         return snprintf(buf, len, "x86_64 Page directory at 0x%" PRIxGENPADDR,
128                         cap->u.vnode_x86_64_pdir.base);
129
130     case ObjType_VNode_x86_64_pdpt:
131         return snprintf(buf, len, "x86_64 PDPT at 0x%" PRIxGENPADDR,
132                         cap->u.vnode_x86_64_pdpt.base);
133
134     case ObjType_VNode_x86_64_pml4:
135         return snprintf(buf, len, "x86_64 PML4 at 0x%" PRIxGENPADDR,
136                         cap->u.vnode_x86_64_pml4.base);
137
138     case ObjType_Frame_Mapping:
139         return snprintf(buf, len, "Frame Mapping (Frame cap @%p, "
140                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
141                                   cap->u.frame_mapping.frame,
142                                   cap->u.frame_mapping.pte,
143                                   cap->u.frame_mapping.pte_count);
144
145     case ObjType_DevFrame_Mapping:
146         return snprintf(buf, len, "DevFrame Mapping (DevFrame cap @%p, "
147                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
148                                   cap->u.devframe_mapping.frame,
149                                   cap->u.devframe_mapping.pte,
150                                   cap->u.devframe_mapping.pte_count);
151
152     case ObjType_VNode_x86_64_pml4_Mapping:
153         return snprintf(buf, len, "x86_64 PML4 Mapping (x86_64 PML4 cap @%p, "
154                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
155                                   cap->u.vnode_x86_64_pml4_mapping.frame,
156                                   cap->u.vnode_x86_64_pml4_mapping.pte,
157                                   cap->u.vnode_x86_64_pml4_mapping.pte_count);
158
159     case ObjType_VNode_x86_64_pdpt_Mapping:
160         return snprintf(buf, len, "x86_64 PDPT Mapping (x86_64 PDPT cap @%p, "
161                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
162                                   cap->u.vnode_x86_64_pdpt_mapping.frame,
163                                   cap->u.vnode_x86_64_pdpt_mapping.pte,
164                                   cap->u.vnode_x86_64_pdpt_mapping.pte_count);
165
166     case ObjType_VNode_x86_64_pdir_Mapping:
167         return snprintf(buf, len, "x86_64 PDIR Mapping (x86_64 PDIR cap @%p, "
168                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
169                                   cap->u.vnode_x86_64_pdir_mapping.frame,
170                                   cap->u.vnode_x86_64_pdir_mapping.pte,
171                                   cap->u.vnode_x86_64_pdir_mapping.pte_count);
172
173     case ObjType_VNode_x86_64_ptable_Mapping:
174         return snprintf(buf, len, "x86_64 PTABLE Mapping (x86_64 PTABLE cap @%p, "
175                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
176                                   cap->u.vnode_x86_64_ptable_mapping.frame,
177                                   cap->u.vnode_x86_64_ptable_mapping.pte,
178                                   cap->u.vnode_x86_64_ptable_mapping.pte_count);
179
180     case ObjType_VNode_x86_32_pdpt_Mapping:
181         return snprintf(buf, len, "x86_32 PDPT Mapping (x86_32 PDPT cap @%p, "
182                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
183                                   cap->u.vnode_x86_32_pdpt_mapping.frame,
184                                   cap->u.vnode_x86_32_pdpt_mapping.pte,
185                                   cap->u.vnode_x86_32_pdpt_mapping.pte_count);
186
187     case ObjType_VNode_x86_32_pdir_Mapping:
188         return snprintf(buf, len, "x86_32 PDIR Mapping (x86_32 PDIR cap @%p, "
189                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
190                                   cap->u.vnode_x86_32_pdir_mapping.frame,
191                                   cap->u.vnode_x86_32_pdir_mapping.pte,
192                                   cap->u.vnode_x86_32_pdir_mapping.pte_count);
193
194     case ObjType_VNode_x86_32_ptable_Mapping:
195         return snprintf(buf, len, "x86_32 PTABLE Mapping (x86_32 PTABLE cap @%p, "
196                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
197                                   cap->u.vnode_x86_32_ptable_mapping.frame,
198                                   cap->u.vnode_x86_32_ptable_mapping.pte,
199                                   cap->u.vnode_x86_32_ptable_mapping.pte_count);
200
201     case ObjType_VNode_ARM_l1_Mapping:
202         return snprintf(buf, len, "ARM l1 Mapping (ARM l1 cap @%p, "
203                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
204                                   cap->u.vnode_arm_l1_mapping.frame,
205                                   cap->u.vnode_arm_l1_mapping.pte,
206                                   cap->u.vnode_arm_l1_mapping.pte_count);
207
208     case ObjType_VNode_ARM_l2_Mapping:
209         return snprintf(buf, len, "ARM l2 Mapping (ARM l2 cap @%p, "
210                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
211                                   cap->u.vnode_arm_l2_mapping.frame,
212                                   cap->u.vnode_arm_l2_mapping.pte,
213                                   cap->u.vnode_arm_l2_mapping.pte_count);
214
215     case ObjType_VNode_AARCH64_l1_Mapping:
216         return snprintf(buf, len, "AARCH64 l1 Mapping (AARCH64 l1 cap @%p, "
217                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
218                                   cap->u.vnode_aarch64_l1_mapping.frame,
219                                   cap->u.vnode_aarch64_l1_mapping.pte,
220                                   cap->u.vnode_aarch64_l1_mapping.pte_count);
221
222     case ObjType_VNode_AARCH64_l2_Mapping:
223         return snprintf(buf, len, "AARCH64 l2 Mapping (AARCH64 l2 cap @%p, "
224                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
225                                   cap->u.vnode_aarch64_l2_mapping.frame,
226                                   cap->u.vnode_aarch64_l2_mapping.pte,
227                                   cap->u.vnode_aarch64_l2_mapping.pte_count);
228
229     case ObjType_VNode_AARCH64_l3_Mapping:
230         return snprintf(buf, len, "AARCH64 l3 Mapping (AARCH64 l3 cap @%p, "
231                                   "pte @0x%"PRIxLVADDR", pte_count=%hu)",
232                                   cap->u.vnode_aarch64_l3_mapping.frame,
233                                   cap->u.vnode_aarch64_l3_mapping.pte,
234                                   cap->u.vnode_aarch64_l3_mapping.pte_count);
235
236     case ObjType_IRQTable:
237         return snprintf(buf, len, "IRQTable cap");
238
239     case ObjType_IRQDest:
240         return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", ctrl: %"PRIu64")",
241                 cap->u.irqdest.vector, cap->u.irqdest.controller);
242
243     case ObjType_EndPoint:
244         return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
245                         cap->u.endpoint.listener, cap->u.endpoint.epoffset);
246
247     case ObjType_IO:
248         return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
249                         cap->u.io.start, cap->u.io.end);
250
251     case ObjType_Kernel:
252         return snprintf(buf, len, "Kernel cap");
253
254     case ObjType_ID:
255         return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
256                         " core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
257                         cap->u.id.core_local_id);
258
259     case ObjType_PerfMon:
260         return snprintf(buf, len, "PerfMon cap");
261
262     case ObjType_Null:
263         return snprintf(buf, len, "Null capability (empty slot)");
264
265     case ObjType_IPI:
266         return snprintf(buf, len, "IPI cap");
267
268     default:
269         return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
270     }
271 }
272
273 void caps_trace(const char *func, int line, struct cte *cte, const char *msg)
274 {
275     char cap_buf[512];
276     sprint_cap(cap_buf, 512, &cte->cap);
277
278     char disp_buf[64];
279     if (dcb_current) {
280         dispatcher_handle_t handle = dcb_current->disp;
281         struct dispatcher_shared_generic *disp =
282             get_dispatcher_shared_generic(handle);
283         snprintf(disp_buf, 64, "from %.*s", DISP_NAME_LEN, disp->name);
284     }
285     else {
286         strcpy(disp_buf, "no disp");
287     }
288
289     printk(LOG_WARN, "%s: %s:%d: %s %p %s"
290            " (owner:%" PRIuCOREID ", rc:%d/ra:%d/rd:%d)\n",
291            disp_buf, func, line, (msg ? : ""), cte, cap_buf, cte->mdbnode.owner,
292            cte->mdbnode.remote_copies, cte->mdbnode.remote_ancs,
293            cte->mdbnode.remote_descs);
294 }
295
296 /**
297  * ID capability core_local_id counter.
298  */
299 static uint32_t id_cap_counter = 1;
300
301 /**
302  *  Sets #dest equal to #src
303  *
304  * #dest cannot be in use.
305  */
306 static errval_t set_cap(struct capability *dest, struct capability *src)
307 {
308     /* Parameter checking */
309     assert(src  != NULL);
310     assert(dest != NULL);
311
312     // Reserved object bits must always be greater/equal to actual object size
313     assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
314
315     // Cannot overwrite an already existing cap
316     if (dest->type != ObjType_Null) {
317         return SYS_ERR_SLOT_IN_USE;
318     }
319
320     memcpy(dest, src, sizeof(struct capability));
321     return SYS_ERR_OK;
322 }
323
324 /**
325  * \brief Determine how many objects can be created in a specified region.
326  *
327  * This function computes the number of objects that can be created by a call
328  * to caps_create().
329  *
330  * \param type          Type of objects to create.
331  * \param bits          Size of memory area as 2^bits.
332  * \param objbits       For variable-sized objects, size multiplier as 2^bits.
333  *
334  * \return Number of objects to be created, or zero on error
335  */
336
337 // If you create more capability types you need to deal with them
338 // in the table below.
339 STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
340
341 static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
342 {
343     switch(type) {
344     case ObjType_PhysAddr:
345     case ObjType_RAM:
346     case ObjType_Frame:
347     case ObjType_DevFrame:
348         if (objbits > bits) {
349             return 0;
350         } else {
351             return 1UL << (bits - objbits);
352         }
353
354     case ObjType_CNode:
355         if (bits < OBJBITS_CTE || objbits > bits - OBJBITS_CTE) {
356             return 0;
357         } else {
358             return 1UL << (bits - OBJBITS_CTE - objbits);
359         }
360
361     case ObjType_VNode_x86_64_pml4:
362     case ObjType_VNode_x86_64_pdpt:
363     case ObjType_VNode_x86_64_pdir:
364     case ObjType_VNode_x86_64_ptable:
365     case ObjType_VNode_x86_32_pdpt:
366     case ObjType_VNode_x86_32_pdir:
367     case ObjType_VNode_x86_32_ptable:
368     case ObjType_VNode_ARM_l1:
369     case ObjType_VNode_ARM_l2:
370     case ObjType_VNode_AARCH64_l1:
371     case ObjType_VNode_AARCH64_l2:
372     case ObjType_VNode_AARCH64_l3:
373     {
374         size_t objbits_vnode = vnode_objbits(type);
375         if (bits < objbits_vnode) {
376             return 0;
377         } else {
378             return 1UL << (bits - objbits_vnode);
379         }
380     }
381
382     case ObjType_Dispatcher:
383         if (bits < OBJBITS_DISPATCHER) {
384             return 0;
385         } else {
386             return 1UL << (bits - OBJBITS_DISPATCHER);
387         }
388
389     case ObjType_KernelControlBlock:
390         if (bits < OBJBITS_KCB) {
391             return 0;
392         } else {
393             return 1UL << (bits - OBJBITS_KCB);
394         }
395
396     case ObjType_Kernel:
397     case ObjType_IRQTable:
398     case ObjType_IRQDest:
399     case ObjType_IRQSrc:
400     case ObjType_IO:
401     case ObjType_EndPoint:
402     case ObjType_ID:
403     case ObjType_Notify_RCK:
404     case ObjType_Notify_IPI:
405     case ObjType_PerfMon:
406     case ObjType_IPI:
407     case ObjType_VNode_ARM_l1_Mapping:
408     case ObjType_VNode_ARM_l2_Mapping:
409     case ObjType_VNode_AARCH64_l1_Mapping:
410     case ObjType_VNode_AARCH64_l2_Mapping:
411     case ObjType_VNode_AARCH64_l3_Mapping:
412     case ObjType_VNode_x86_64_pml4_Mapping:
413     case ObjType_VNode_x86_64_pdpt_Mapping:
414     case ObjType_VNode_x86_64_pdir_Mapping:
415     case ObjType_VNode_x86_64_ptable_Mapping:
416     case ObjType_VNode_x86_32_pdpt_Mapping:
417     case ObjType_VNode_x86_32_pdir_Mapping:
418     case ObjType_VNode_x86_32_ptable_Mapping:
419     case ObjType_DevFrame_Mapping:
420     case ObjType_Frame_Mapping:
421         return 1;
422
423     default:
424         panic("invalid type");
425         return 0;
426     }
427 }
428
429 /**
430  * \brief Initialize the objects for which local caps are about to be created.
431  *
432  * For the meaning of the parameters, see the 'caps_create' function.
433  */
434 STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
435
436 static errval_t caps_init_objects(enum objtype type, lpaddr_t lpaddr, uint8_t
437                                   bits, uint8_t objbits, size_t numobjs)
438 {
439     // Virtual address of the memory the kernel object resides in
440     // XXX: A better of doing this,
441     // this is creating caps that the kernel cannot address.
442     // It assumes that the cap is not of the type which will have to zeroed out.
443     lvaddr_t lvaddr;
444     if(lpaddr < PADDR_SPACE_LIMIT) {
445         lvaddr = local_phys_to_mem(lpaddr);
446     } else {
447         lvaddr = 0;
448     }
449
450     switch (type) {
451
452     case ObjType_Frame:
453         trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
454         // XXX: SCC hack, while we don't have a devframe allocator
455         if(lpaddr + ((lpaddr_t)1 << bits) < PADDR_SPACE_LIMIT) {
456             memset((void*)lvaddr, 0, (lvaddr_t)1 << bits);
457         } else {
458             printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
459                    " uninitialized\n", lpaddr);
460         }
461         trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
462         break;
463
464     case ObjType_CNode:
465     case ObjType_VNode_ARM_l1:
466     case ObjType_VNode_ARM_l2:
467     case ObjType_VNode_AARCH64_l1:
468     case ObjType_VNode_AARCH64_l2:
469     case ObjType_VNode_AARCH64_l3:
470     case ObjType_VNode_x86_32_ptable:
471     case ObjType_VNode_x86_32_pdir:
472     case ObjType_VNode_x86_32_pdpt:
473     case ObjType_VNode_x86_64_ptable:
474     case ObjType_VNode_x86_64_pdir:
475     case ObjType_VNode_x86_64_pdpt:
476     case ObjType_VNode_x86_64_pml4:
477     case ObjType_Dispatcher:
478     case ObjType_KernelControlBlock:
479         TRACE(KERNEL, BZERO, 1);
480         memset((void*)lvaddr, 0, 1UL << bits);
481         TRACE(KERNEL, BZERO, 0);
482         break;
483
484     default:
485         break;
486
487     }
488
489     return SYS_ERR_OK;
490 }
491
492 /**
493  * \brief Create capabilities to kernel objects.
494  *
495  * This function creates kernel objects of 'type' into the memory
496  * area, based at 'addr' and of size 2^'bits', so they completely fill the
497  * area. For each created kernel object, a capability is created to it and
498  * put consecutively into the array of CTEs pointed to by 'caps'. The array
499  * needs to have the appropriate size to hold all created caps. Some kernel
500  * objects can have a variable size. In that case, 'objbits' should be non-zero
501  * and give the a size multiplier as 2^'objbits'.
502  *
503  * \param type          Type of objects to create.
504  * \param addr          Base address in the local address space.
505  * \param bits          Size of memory area as 2^bits.
506  * \param objbits       For variable-sized objects, size multiplier as 2^bits.
507  * \param numobjs       Number of objects to be created, from caps_numobjs()
508  * \param dest_caps     Pointer to array of CTEs to hold created caps.
509  *
510  * \return Error code
511  */
512 // If you create more capability types you need to deal with them
513 // in the table below.
514 STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
515
516 static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, uint8_t bits,
517                             uint8_t objbits, size_t numobjs, coreid_t owner,
518                             struct cte *dest_caps)
519 {
520     errval_t err;
521
522     /* Parameter checking */
523     assert(dest_caps != NULL);
524     assert(type != ObjType_Null);
525     assert(type < ObjType_Num);
526     assert(numobjs > 0);
527     assert(!type_is_mapping(type));
528
529     genpaddr_t genpaddr = local_phys_to_gen_phys(lpaddr);
530
531     // Virtual address of the memory the kernel object resides in
532     // XXX: A better of doing this,
533     // this is creating caps that the kernel cannot address.
534     // It assumes that the cap is not of the type which will have to zeroed out.
535     lvaddr_t lvaddr;
536     if(lpaddr < PADDR_SPACE_LIMIT) {
537         lvaddr = local_phys_to_mem(lpaddr);
538     } else {
539         lvaddr = 0;
540     }
541
542     /* Initialize the created capability */
543     struct capability src_cap;
544     memset(&src_cap, 0, sizeof(struct capability));
545     src_cap.type = type;
546     // XXX: Handle rights!
547     src_cap.rights = CAPRIGHTS_ALLRIGHTS;
548
549     if (owner == my_core_id) {
550         // If we're creating new local objects, they need to be initialized
551         err = caps_init_objects(type, lpaddr, bits, objbits, numobjs);
552         if (err_is_fail(err)) {
553             return err;
554         }
555     }
556
557     size_t dest_i = 0;
558     err = SYS_ERR_OK;
559
560     /* Set the type specific fields and insert into #dest_caps */
561     switch(type) {
562     case ObjType_Frame:
563         TRACE(KERNEL, BZERO, 1);
564         // XXX: SCC hack, while we don't have a devframe allocator
565         if(lpaddr + ((lpaddr_t)1 << bits) < PADDR_SPACE_LIMIT) {
566             memset((void*)lvaddr, 0, (lvaddr_t)1 << bits);
567         } else {
568             printk(LOG_WARN, "Allocating RAM at 0x%" PRIxLPADDR
569                    " uninitialized\n", lpaddr);
570         }
571         TRACE(KERNEL, BZERO, 0);
572         for(dest_i = 0; dest_i < numobjs; dest_i++) {
573             // Initialize type specific fields
574             src_cap.u.frame.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
575             src_cap.u.frame.bytes = 1UL << objbits;
576             assert((get_size(&src_cap) & BASE_PAGE_MASK) == 0);
577             // Insert the capabilities
578             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
579             if (err_is_fail(err)) {
580                 break;
581             }
582         }
583         break;
584
585     case ObjType_PhysAddr:
586         for(dest_i = 0; dest_i < numobjs; dest_i++) {
587             // Initialize type specific fields
588             src_cap.u.physaddr.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
589             src_cap.u.physaddr.bytes = 1UL << objbits;
590             // Insert the capabilities
591             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
592             if (err_is_fail(err)) {
593                 break;
594             }
595         }
596         break;
597
598     case ObjType_RAM:
599         for(dest_i = 0; dest_i < numobjs; dest_i++) {
600             // Initialize type specific fields
601             src_cap.u.ram.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
602             src_cap.u.ram.bytes = 1UL << objbits;
603             // Insert the capabilities
604             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
605             if (err_is_fail(err)) {
606                 break;
607             }
608         }
609         break;
610
611     case ObjType_DevFrame:
612         for(dest_i = 0; dest_i < numobjs; dest_i++) {
613             // Initialize type specific fields
614             src_cap.u.devframe.base = genpaddr + dest_i * ((genpaddr_t)1 << objbits);
615             src_cap.u.devframe.bytes = 1UL << objbits;
616             // Insert the capabilities
617             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
618             if (err_is_fail(err)) {
619                 break;
620             }
621         }
622         break;
623
624     case ObjType_CNode:
625         assert((1UL << OBJBITS_CTE) >= sizeof(struct cte));
626         TRACE(KERNEL, BZERO, 1);
627         memset((void*)lvaddr, 0, 1UL << bits);
628         TRACE(KERNEL, BZERO, 0);
629
630         for(dest_i = 0; dest_i < numobjs; dest_i++) {
631             // Initialize type specific fields
632             src_cap.u.cnode.cnode =
633                 lpaddr + dest_i * ((lpaddr_t)1 << (objbits + OBJBITS_CTE));
634             src_cap.u.cnode.bits = objbits;
635             src_cap.u.cnode.guard = 0;
636             src_cap.u.cnode.guard_size = 0;
637             // XXX: Handle rights!
638             src_cap.u.cnode.rightsmask = CAPRIGHTS_ALLRIGHTS;
639             // Insert the capability
640             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
641             if (err_is_fail(err)) {
642                 break;
643             }
644         }
645         break;
646
647     case ObjType_VNode_ARM_l1:
648     {
649         size_t objbits_vnode = vnode_objbits(type);
650
651         TRACE(KERNEL, BZERO, 1);
652         memset((void*)lvaddr, 0, 1UL << bits);
653         TRACE(KERNEL, BZERO, 0);
654
655         for(dest_i = 0; dest_i < numobjs; dest_i++) {
656             // Initialize type specific fields
657             src_cap.u.vnode_arm_l1.base =
658                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
659
660 #ifdef __arm__
661             // Insert kernel/mem mappings into new table.
662             paging_make_good(
663                 gen_phys_to_local_phys(
664                     local_phys_to_mem(src_cap.u.vnode_arm_l1.base)
665                 ),
666                 1u << objbits_vnode
667                 );
668 #endif
669
670             // Insert the capability
671             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
672             if (err_is_fail(err)) {
673                 break;
674             }
675         }
676
677         break;
678     }
679
680     case ObjType_VNode_ARM_l2:
681     {
682         size_t objbits_vnode = vnode_objbits(type);
683
684         TRACE(KERNEL, BZERO, 1);
685         memset((void*)lvaddr, 0, 1UL << bits);
686         TRACE(KERNEL, BZERO, 0);
687
688         for(dest_i = 0; dest_i < numobjs; dest_i++) {
689             // Initialize type specific fields
690             src_cap.u.vnode_arm_l2.base =
691                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
692
693             // Insert the capability
694             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
695             if (err_is_fail(err)) {
696                 break;
697             }
698         }
699         break;
700     }
701
702     case ObjType_VNode_AARCH64_l1:
703     {
704         size_t objbits_vnode = vnode_objbits(type);
705
706         TRACE(KERNEL, BZERO, 1);
707         memset((void*)lvaddr, 0, 1UL << bits);
708         TRACE(KERNEL, BZERO, 0);
709
710         for(dest_i = 0; dest_i < numobjs; dest_i++) {
711             // Initialize type specific fields
712             src_cap.u.vnode_aarch64_l1.base =
713                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
714
715 #ifdef __aarch64__
716             // Insert kernel/mem mappings into new table.
717             lpaddr_t var = gen_phys_to_local_phys(src_cap.u.vnode_aarch64_l1.base);
718             paging_make_good(var);
719 #endif
720
721             // Insert the capability
722             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
723             if (err_is_fail(err)) {
724                 break;
725             }
726         }
727
728         break;
729     }
730
731     case ObjType_VNode_AARCH64_l2:
732     {
733         size_t objbits_vnode = vnode_objbits(type);
734
735         TRACE(KERNEL, BZERO, 1);
736         memset((void*)lvaddr, 0, 1UL << bits);
737         TRACE(KERNEL, BZERO, 0);
738
739         for(dest_i = 0; dest_i < numobjs; dest_i++) {
740             // Initialize type specific fields
741             src_cap.u.vnode_aarch64_l2.base =
742                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
743
744             // Insert the capability
745             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
746
747             if (err_is_fail(err)) {
748                 break;
749             }
750         }
751         break;
752     }
753
754     case ObjType_VNode_AARCH64_l3:
755     {
756         size_t objbits_vnode = vnode_objbits(type);
757
758         TRACE(KERNEL, BZERO, 1);
759         memset((void*)lvaddr, 0, 1UL << bits);
760         TRACE(KERNEL, BZERO, 0);
761
762         for(dest_i = 0; dest_i < numobjs; dest_i++) {
763             // Initialize type specific fields
764             src_cap.u.vnode_aarch64_l3.base =
765                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
766
767             // Insert the capability
768             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
769             if (err_is_fail(err)) {
770                 break;
771             }
772         }
773         break;
774     }
775
776     case ObjType_VNode_x86_32_ptable:
777     {
778         size_t objbits_vnode = vnode_objbits(type);
779
780         TRACE(KERNEL, BZERO, 1);
781         memset((void*)lvaddr, 0, 1UL << bits);
782         TRACE(KERNEL, BZERO, 0);
783
784         for(dest_i = 0; dest_i < numobjs; dest_i++) {
785             // Initialize type specific fields
786             src_cap.u.vnode_x86_32_ptable.base =
787                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
788
789             // Insert the capability
790             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
791             if (err_is_fail(err)) {
792                 break;
793             }
794         }
795         break;
796     }
797
798     case ObjType_VNode_x86_32_pdir:
799     {
800         size_t objbits_vnode = vnode_objbits(type);
801
802         TRACE(KERNEL, BZERO, 1);
803         memset((void*)lvaddr, 0, 1UL << bits);
804         TRACE(KERNEL, BZERO, 0);
805
806         for(dest_i = 0; dest_i < numobjs; dest_i++) {
807             // Initialize type specific fields
808             src_cap.u.vnode_x86_32_pdir.base =
809                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
810
811 #if defined(__i386__) && !defined(CONFIG_PAE)
812             // Make it a good PDE by inserting kernel/mem VSpaces
813             lpaddr = gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdir.base);
814             paging_x86_32_make_good_pdir(lpaddr);
815 #endif
816
817             // Insert the capability
818             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
819             if (err_is_fail(err)) {
820                 break;
821             }
822         }
823         break;
824     }
825
826     case ObjType_VNode_x86_32_pdpt:
827     {
828         size_t objbits_vnode = vnode_objbits(type);
829
830         TRACE(KERNEL, BZERO, 1);
831         memset((void*)lvaddr, 0, 1UL << bits);
832         TRACE(KERNEL, BZERO, 0);
833
834         for(dest_i = 0; dest_i < numobjs; dest_i++) {
835             // Initialize type specific fields
836             src_cap.u.vnode_x86_32_pdir.base =
837                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
838
839 #if defined(__i386__) && defined(CONFIG_PAE)
840             // Make it a good PDPTE by inserting kernel/mem VSpaces
841             lpaddr_t var =
842                 gen_phys_to_local_phys(src_cap.u.vnode_x86_32_pdpt.base);
843             paging_x86_32_make_good_pdpte(var);
844 #endif
845
846             // Insert the capability
847             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
848             if (err_is_fail(err)) {
849                 break;
850             }
851         }
852         break;
853     }
854
855     case ObjType_VNode_x86_64_ptable:
856     {
857         size_t objbits_vnode = vnode_objbits(type);
858
859         TRACE(KERNEL, BZERO, 1);
860         memset((void*)lvaddr, 0, 1UL << bits);
861         TRACE(KERNEL, BZERO, 0);
862
863         for(dest_i = 0; dest_i < numobjs; dest_i++) {
864             // Initialize type specific fields
865             src_cap.u.vnode_x86_64_ptable.base =
866                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
867
868             // Insert the capability
869             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
870             if (err_is_fail(err)) {
871                 break;
872             }
873         }
874         break;
875     }
876
877     case ObjType_VNode_x86_64_pdir:
878     {
879         size_t objbits_vnode = vnode_objbits(type);
880
881         TRACE(KERNEL, BZERO, 1);
882         memset((void*)lvaddr, 0, 1UL << bits);
883         TRACE(KERNEL, BZERO, 0);
884
885         for(dest_i = 0; dest_i < numobjs; dest_i++) {
886             // Initialize type specific fields
887             src_cap.u.vnode_x86_64_pdir.base =
888                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
889
890             // Insert the capability
891             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
892             if (err_is_fail(err)) {
893                 break;
894             }
895         }
896         break;
897     }
898
899     case ObjType_VNode_x86_64_pdpt:
900     {
901         size_t objbits_vnode = vnode_objbits(type);
902
903         TRACE(KERNEL, BZERO, 1);
904         memset((void*)lvaddr, 0, 1UL << bits);
905         TRACE(KERNEL, BZERO, 0);
906
907         for(dest_i = 0; dest_i < numobjs; dest_i++) {
908             // Initialize type specific fields
909             src_cap.u.vnode_x86_64_pdpt.base =
910                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
911
912             // Insert the capability
913             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
914             if (err_is_fail(err)) {
915                 break;
916             }
917         }
918         break;
919     }
920
921     case ObjType_VNode_x86_64_pml4:
922     {
923         size_t objbits_vnode = vnode_objbits(type);
924
925         TRACE(KERNEL, BZERO, 1);
926         memset((void*)lvaddr, 0, 1UL << bits);
927         TRACE(KERNEL, BZERO, 0);
928
929         for(dest_i = 0; dest_i < numobjs; dest_i++) {
930             // Initialize type specific fields
931             src_cap.u.vnode_x86_64_pml4.base =
932                 genpaddr + dest_i * ((genpaddr_t)1 << objbits_vnode);
933
934 #if defined(__x86_64__) || defined(__k1om__)
935             // Make it a good PML4 by inserting kernel/mem VSpaces
936             lpaddr_t var = gen_phys_to_local_phys(src_cap.u.vnode_x86_64_pml4.base);
937             paging_x86_64_make_good_pml4(var);
938 #endif
939
940             // Insert the capability
941             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
942             if (err_is_fail(err)) {
943                 break;
944             }
945         }
946
947         break;
948     }
949
950     case ObjType_Dispatcher:
951         assert((1UL << OBJBITS_DISPATCHER) >= sizeof(struct dcb));
952         TRACE(KERNEL, BZERO, 1);
953         memset((void*)lvaddr, 0, 1UL << bits);
954         TRACE(KERNEL, BZERO, 0);
955
956         for(dest_i = 0; dest_i < numobjs; dest_i++) {
957             // Initialize type specific fields
958             src_cap.u.dispatcher.dcb = (struct dcb *)
959                 (lvaddr + dest_i * (1UL << OBJBITS_DISPATCHER));
960             // Insert the capability
961             err = set_cap(&dest_caps[dest_i].cap, &src_cap);
962             if (err_is_fail(err)) {
963                 break;
964             }
965         }
966         break;
967
968     case ObjType_ID:
969         // ID type does not refer to a kernel object
970         assert(lpaddr  == 0);
971         assert(bits    == 0);
972         assert(objbits == 0);
973         assert(numobjs == 1);
974
975         // Prevent wrap around
976         if (id_cap_counter >= UINT32_MAX) {
977             return SYS_ERR_ID_SPACE_EXHAUSTED;
978         }
979
980         // Generate a new ID, core_local_id monotonically increases
981         src_cap.u.id.coreid = my_core_id;
982         src_cap.u.id.core_local_id = id_cap_counter++;
983
984         // Insert the capability
985         err = set_cap(&dest_caps->cap, &src_cap);
986         break;
987
988     case ObjType_IO:
989         src_cap.u.io.start = 0;
990         src_cap.u.io.end   = 65535;
991         /* fall through */
992
993     case ObjType_Kernel:
994     case ObjType_IPI:
995     case ObjType_IRQTable:
996     case ObjType_IRQDest:
997     case ObjType_IRQSrc:
998     case ObjType_EndPoint:
999     case ObjType_Notify_RCK:
1000     case ObjType_Notify_IPI:
1001     case ObjType_PerfMon:
1002         // These types do not refer to a kernel object
1003         assert(lpaddr  == 0);
1004         assert(bits    == 0);
1005         assert(objbits == 0);
1006         assert(numobjs == 1);
1007
1008         // Insert the capability
1009         err = set_cap(&dest_caps->cap, &src_cap);
1010         if (err_is_ok(err)) {
1011             dest_i = 1;
1012         }
1013         break;
1014
1015     case ObjType_KernelControlBlock:
1016         assert((1UL << OBJBITS_KCB) >= sizeof(struct dcb));
1017
1018         for(size_t i = 0; i < numobjs; i++) {
1019             // Initialize type specific fields
1020             src_cap.u.kernelcontrolblock.kcb = (struct kcb *)
1021                 (lvaddr + i * (1UL << OBJBITS_KCB));
1022             // Insert the capability
1023             err = set_cap(&dest_caps[i].cap, &src_cap);
1024             if (err_is_fail(err)) {
1025                 return err;
1026             }
1027         }
1028         return SYS_ERR_OK;
1029
1030     default:
1031         panic("Unhandled capability type or capability of this type cannot"
1032               " be created");
1033     }
1034
1035     if (err_is_fail(err)) {
1036         // Revert the partially initialized caps to zero
1037         for (size_t i = 0; i < dest_i; i++) {
1038             memset(&dest_caps[i], 0, sizeof(dest_caps[i]));
1039         }
1040         return err;
1041     }
1042     else {
1043         // Set the owner for all the new caps
1044         for (size_t i = 0; i < dest_i; i++) {
1045             dest_caps[i].mdbnode.owner = owner;
1046         }
1047     }
1048
1049     return SYS_ERR_OK;
1050 }
1051
1052 /**
1053  * Look up a capability.
1054  *
1055  * Starting from #cnode_cap, recursively lookup the capability at #cptr
1056  * with #vbits.
1057  *
1058  * \bug Handle rights
1059  */
1060 errval_t caps_lookup_slot(struct capability *cnode_cap, capaddr_t cptr,
1061                           uint8_t vbits, struct cte **ret, CapRights rights)
1062 {
1063     TRACE(KERNEL, CAP_LOOKUP_SLOT, 0);
1064     /* parameter checking */
1065     assert(cnode_cap != NULL);
1066
1067     /* Can only resolve CNode type */
1068     if (cnode_cap->type != ObjType_CNode) {
1069         debug(SUBSYS_CAPS, "caps_lookup_slot: Cap to lookup not of type CNode\n"
1070               "cnode_cap->type = %u\n", cnode_cap->type);
1071         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1072         return SYS_ERR_CNODE_TYPE;
1073     }
1074
1075     /* Apply rights to this CNode */
1076     if ((cnode_cap->rights & rights) != rights) {
1077         debug(SUBSYS_CAPS, "caps_lookup_slot: Rights mismatch\n"
1078               "Passed rights = %u, cnode_cap->rights = %u\n",
1079               rights, cnode_cap->rights);
1080         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1081         return SYS_ERR_CNODE_RIGHTS;
1082     }
1083
1084     /* Number of bits resolved by this cnode (guard and bits) */
1085     uint8_t bits_resolved = cnode_cap->u.cnode.bits +
1086         cnode_cap->u.cnode.guard_size;
1087     // All CNodes must resolve at least one bit
1088     assert(bits_resolved > 0);
1089     // If lookup exceeded expected depth then table is malformed
1090     if (bits_resolved > vbits) {
1091         debug(SUBSYS_CAPS, "caps_lookup_slot: Lookup exceeded valid bits\n"
1092               "Cnode bits = %u, guard size = %u, valid bits = %u, bits_resolved = %u\n",
1093               cnode_cap->u.cnode.bits, cnode_cap->u.cnode.guard_size,
1094               vbits, bits_resolved);
1095         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1096         return SYS_ERR_DEPTH_EXCEEDED;
1097     }
1098
1099     /* Guard-check (bit-mask of guard in cptr must match guard in cnode cap) */
1100     capaddr_t cptr_guard = (cptr >> (vbits - cnode_cap->u.cnode.guard_size))
1101         & MASK(cnode_cap->u.cnode.guard_size);
1102     if (cptr_guard != cnode_cap->u.cnode.guard) {
1103         debug(SUBSYS_CAPS, "caps_lookup_slot: guard check failed\n"
1104               "Computed guard = %"PRIuCADDR", "
1105               "Cnode guard = %"PRIxCADDR", bits = %u\n",
1106               cptr_guard, cnode_cap->u.cnode.guard,
1107               cnode_cap->u.cnode.guard_size);
1108         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1109         return SYS_ERR_GUARD_MISMATCH;
1110     }
1111
1112     /* Locate capability in this cnode */
1113     // Offset into the cnode
1114     size_t offset = (cptr >> (vbits - bits_resolved)) &
1115         MASK(cnode_cap->u.cnode.bits);
1116     // The capability at the offset
1117     struct cte *next_slot = caps_locate_slot(cnode_cap->u.cnode.cnode, offset);
1118     // Do not return NULL type capability
1119     if (next_slot->cap.type == ObjType_Null) {
1120         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1121         return SYS_ERR_CAP_NOT_FOUND;
1122     }
1123
1124     /* Number of bits left to resolve */
1125     int bitsleft = vbits - bits_resolved;
1126     // If all bits have been resolved, return the capability
1127     if(bitsleft == 0) {
1128         *ret = next_slot;
1129         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1130         return SYS_ERR_OK;
1131     }
1132
1133     /* If next capability is not of type cnode, return it */
1134     // XXX: Is this consistent?
1135     if (next_slot->cap.type != ObjType_CNode) {
1136         *ret = next_slot;
1137         TRACE(KERNEL, CAP_LOOKUP_SLOT, 1);
1138         return SYS_ERR_OK;
1139     }
1140
1141     /* Descend to next level */
1142     return caps_lookup_slot(&next_slot->cap, cptr, bitsleft, ret, rights);
1143 }
1144
1145 /**
1146  * Wrapper for caps_lookup_slot returning capability instead of cte.
1147  */
1148 errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
1149                          uint8_t vbits, struct capability **ret, CapRights rights)
1150 {
1151     TRACE(KERNEL, CAP_LOOKUP_CAP, 0);
1152     struct cte *ret_cte;
1153     errval_t err = caps_lookup_slot(cnode_cap, cptr, vbits, &ret_cte, rights);
1154     if (err_is_fail(err)) {
1155         return err;
1156     }
1157     *ret = &ret_cte->cap;
1158     TRACE(KERNEL, CAP_LOOKUP_CAP, 1);
1159     return SYS_ERR_OK;
1160 }
1161
1162 /**
1163  * \brief Create a capability from an existing capability metadata.
1164  *
1165  * Used when sending capabilities across cores. The metadata is sent across
1166  * cores and the receiving monitor can create the new capability on its core.
1167  *
1168  * \bug Does not check that supplied owner matches existing copies of cap.
1169  */
1170 errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
1171                                    int cnode_vbits, cslot_t dest_slot, coreid_t owner,
1172                                    struct capability *src)
1173 {
1174     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 0);
1175     errval_t err;
1176     struct capability *cnode;
1177     err = caps_lookup_cap(root, cnode_cptr, cnode_vbits, &cnode,
1178                           CAPRIGHTS_READ_WRITE);
1179     if (err_is_fail(err)) {
1180         return err_push(err, SYS_ERR_SLOT_LOOKUP_FAIL);
1181     }
1182     if (cnode->type != ObjType_CNode) {
1183         return SYS_ERR_CNODE_TYPE;
1184     }
1185
1186     struct cte *dest = caps_locate_slot(cnode->u.cnode.cnode, dest_slot);
1187
1188     err = set_cap(&dest->cap, src);
1189     if (err_is_fail(err)) {
1190         return err;
1191     }
1192
1193     dest->mdbnode.owner = owner;
1194
1195     err = mdb_insert(dest);
1196     assert(err_is_ok(err));
1197
1198     struct cte *neighbour = NULL;
1199     if (!neighbour
1200         && (neighbour = mdb_predecessor(dest))
1201         && !is_copy(&dest->cap, &neighbour->cap))
1202     {
1203         neighbour = NULL;
1204     }
1205     if (!neighbour
1206         && (neighbour = mdb_successor(dest))
1207         && !is_copy(&dest->cap, &neighbour->cap))
1208     {
1209         neighbour = NULL;
1210     }
1211
1212     if (neighbour) {
1213         assert(!neighbour->mdbnode.in_delete);
1214         assert(neighbour->mdbnode.owner == owner);
1215 #define CP_ATTR(a) dest->mdbnode.a = neighbour->mdbnode.a
1216         CP_ATTR(locked);
1217         CP_ATTR(remote_copies);
1218         CP_ATTR(remote_ancs);
1219         CP_ATTR(remote_descs);
1220 #undef CP_ATTR
1221     }
1222     else {
1223         dest->mdbnode.locked = false;
1224         if (owner != my_core_id) {
1225             // For foreign caps it does not really matter if ancestors or
1226             // descendants exist
1227             dest->mdbnode.remote_copies = true;
1228             dest->mdbnode.remote_ancs = false;
1229             dest->mdbnode.remote_descs = false;
1230         }
1231         else {
1232             // We just created a new copy of a owned capability from nothing.
1233             // This is either caused by a retype, or by sharing a capability
1234             // that does not care about locality.
1235             // XXX: This should probably be done more explicitly -MN
1236             if (distcap_needs_locality(dest->cap.type)) {
1237                 // Retype, so have ancestors and no descendants
1238                 dest->mdbnode.remote_copies = false;
1239                 dest->mdbnode.remote_ancs = true;
1240                 dest->mdbnode.remote_descs = false;
1241             }
1242             else {
1243                 dest->mdbnode.remote_copies = false;
1244                 dest->mdbnode.remote_ancs = false;
1245                 dest->mdbnode.remote_descs = false;
1246             }
1247         }
1248     }
1249
1250     TRACE_CAP_MSG("created", dest);
1251
1252     TRACE(KERNEL, CAP_CREATE_FROM_EXISTING, 1);
1253     return SYS_ERR_OK;
1254 }
1255
1256 /// Create caps to new kernel objects.
1257 errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bits,
1258                          size_t objbits, coreid_t owner, struct cte *caps)
1259 {
1260     TRACE(KERNEL, CAP_CREATE_NEW, 0);
1261     /* Parameter checking */
1262     assert(type != ObjType_EndPoint); // Cap of this type cannot be created
1263
1264     size_t numobjs = caps_numobjs(type, bits, objbits);
1265     assert(numobjs > 0);
1266
1267     /* Create the new capabilities */
1268     errval_t err = caps_create(type, addr, bits, objbits, numobjs, owner, caps);
1269     if (err_is_fail(err)) {
1270         return err;
1271     }
1272
1273     // Handle the mapping database
1274     set_init_mapping(caps, numobjs);
1275
1276     TRACE_CAP_MSG("created", &caps[0]);
1277
1278     TRACE(KERNEL, CAP_CREATE_NEW, 1);
1279     return SYS_ERR_OK;
1280 }
1281
1282
1283 STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
1284 /// Retype caps
1285 errval_t caps_retype(enum objtype type, size_t objbits,
1286                      struct capability *dest_cnode, cslot_t dest_slot,
1287                      struct cte *src_cte, bool from_monitor)
1288 {
1289     TRACE(KERNEL, CAP_RETYPE, 0);
1290     size_t numobjs;
1291     uint8_t bits = 0;
1292     genpaddr_t base = 0;
1293     errval_t err;
1294
1295     /* Parameter checking */
1296     assert(type != ObjType_Null);
1297     assert(type < ObjType_Num);
1298
1299     struct capability *src_cap = &src_cte->cap;
1300
1301     TRACE_CAP_MSG("retyping", src_cte);
1302
1303     /* No explicit retypes to Mapping allowed */
1304     if (type_is_mapping(type)) {
1305         return SYS_ERR_RETYPE_MAPPING_EXPLICIT;
1306     }
1307
1308     /* Check retypability */
1309     err = is_retypeable(src_cte, src_cap->type, type, from_monitor);
1310     if (err_is_fail(err)) {
1311         debug(SUBSYS_CAPS, "caps_retype: is_retypeable failed\n");
1312         return err;
1313     }
1314
1315     /* Create Destination caps as per source and destination type */
1316     switch(src_cap->type) {
1317     case ObjType_PhysAddr:
1318         bits = log2cl(src_cap->u.physaddr.bytes);
1319         base = src_cap->u.physaddr.base;
1320         break;
1321
1322     case ObjType_RAM:
1323         bits = log2cl(src_cap->u.ram.bytes);
1324         base = src_cap->u.ram.base;
1325         break;
1326
1327     case ObjType_Dispatcher:
1328         bits = base = 0;
1329         break;
1330
1331     case ObjType_Frame:
1332         bits = log2cl(src_cap->u.frame.bytes);
1333         base = src_cap->u.frame.base;
1334         break;
1335
1336     case ObjType_DevFrame:
1337         bits = log2cl(src_cap->u.devframe.bytes);
1338         base = src_cap->u.devframe.base;
1339         break;
1340
1341     default:
1342         panic("Unreachable case");
1343     }
1344
1345     /* determine number of objects to be created */
1346     numobjs = caps_numobjs(type, bits, objbits);
1347
1348     if (numobjs == 0) {
1349         debug(SUBSYS_CAPS, "caps_retype: numobjs == 0\n");
1350         return SYS_ERR_INVALID_SIZE_BITS;
1351     }
1352    // debug(SUBSYS_CAPS, "caps_retype: numobjs == %d\n", (int)numobjs);
1353
1354     /* check that destination slots all fit within target cnode */
1355     if (dest_slot + numobjs > (1UL << dest_cnode->u.cnode.bits)) {
1356         debug(SUBSYS_CAPS, "caps_retype: dest slots don't fit in cnode\n");
1357         return SYS_ERR_SLOTS_INVALID;
1358     }
1359
1360     /* check that destination slots are all empty */
1361     debug(SUBSYS_CAPS, "caps_retype: dest cnode is %#" PRIxLPADDR
1362           " dest_slot %d\n",
1363           dest_cnode->u.cnode.cnode, (int)dest_slot);
1364     for (cslot_t i = 0; i < numobjs; i++) {
1365         if (caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot + i)->cap.type
1366             != ObjType_Null) {
1367             debug(SUBSYS_CAPS, "caps_retype: dest slot %d in use\n",
1368                   (int)(dest_slot + i));
1369             return SYS_ERR_SLOTS_IN_USE;
1370         }
1371     }
1372
1373     /* create new caps */
1374     struct cte *dest_cte =
1375         caps_locate_slot(dest_cnode->u.cnode.cnode, dest_slot);
1376     err = caps_create(type, base, bits, objbits, numobjs, my_core_id, dest_cte);
1377     if (err_is_fail(err)) {
1378         debug(SUBSYS_CAPS, "caps_retype: failed to create a dest cap\n");
1379         return err_push(err, SYS_ERR_RETYPE_CREATE);
1380     }
1381
1382     /* special initialisation for endpoint caps */
1383     if (type == ObjType_EndPoint) {
1384         assert(src_cap->type == ObjType_Dispatcher);
1385         assert(numobjs == 1);
1386         struct capability *dest_cap = &dest_cte->cap;
1387         dest_cap->u.endpoint.listener = src_cap->u.dispatcher.dcb;
1388     }
1389
1390     /* Handle mapping */
1391     for (size_t i = 0; i < numobjs; i++) {
1392         mdb_insert(&dest_cte[i]);
1393     }
1394
1395 #ifdef TRACE_PMEM_CAPS
1396     for (size_t i = 0; i < numobjs; i++) {
1397         TRACE_CAP_MSG("created", &dest_cte[i]);
1398     }
1399 #endif
1400
1401     TRACE(KERNEL, CAP_RETYPE, 1);
1402     return SYS_ERR_OK;
1403 }
1404
1405 /// Check the validity of a retype operation
1406 errval_t is_retypeable(struct cte *src_cte, enum objtype src_type,
1407                        enum objtype dest_type, bool from_monitor)
1408 {
1409     if (!is_well_founded(src_type, dest_type)) {
1410         return SYS_ERR_INVALID_RETYPE;
1411     } else if (!is_revoked_first(src_cte, src_type)){
1412         printf("err_revoke_first: (%p, %d, %d)\n", src_cte, src_type, dest_type);
1413         return SYS_ERR_REVOKE_FIRST;
1414     } else if (dest_type == ObjType_EndPoint && src_cte->mdbnode.owner == my_core_id) {
1415         // XXX: because of the current "multi-retype" hack for endpoints, a
1416         // dispatcher->endpoint retype can happen irrespective of the existence
1417         // of descendents on any core.
1418         // Howevery, we only do this for locally owned caps as the owner should
1419         // be notified that the cap has remote descendants
1420         return SYS_ERR_OK;
1421     } else if (!from_monitor && (src_cte->mdbnode.owner != my_core_id
1422                                  || src_cte->mdbnode.remote_descs)) {
1423         return SYS_ERR_RETRY_THROUGH_MONITOR;
1424     } else {
1425         return SYS_ERR_OK;
1426     }
1427 }
1428
1429 /// Create copies to a slot within a cnode
1430 errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
1431                             struct cte *src_cte, bool mint, uintptr_t param1,
1432                             uintptr_t param2)
1433 {
1434     /* Parameter Checking */
1435     assert(dest_cnode_cte->cap.type == ObjType_CNode);
1436
1437     struct cte *dest_cte;
1438     dest_cte = caps_locate_slot(dest_cnode_cte->cap.u.cnode.cnode, dest_slot);
1439     return caps_copy_to_cte(dest_cte, src_cte, mint, param1, param2);
1440
1441 }
1442
1443 /// Create copies to a cte
1444 errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
1445                           uintptr_t param1, uintptr_t param2)
1446 {
1447     errval_t err;
1448     /* Parameter checking */
1449     // Null checking
1450     assert(dest_cte != NULL);
1451     assert(src_cte != NULL);
1452
1453     struct capability *src_cap  = &src_cte->cap;
1454     struct capability *dest_cap = &dest_cte->cap;
1455     // NULL caps cannot be copied/minted
1456     if (src_cap->type == ObjType_Null) {
1457         return SYS_ERR_CAP_NOT_FOUND;
1458     }
1459     // Parameters should be 0 if not minting
1460     if (!mint) {
1461         assert(param1 == 0);
1462         assert(param2 == 0);
1463     }
1464
1465     assert(!src_cte->mdbnode.in_delete);
1466
1467     /* Insert #source_cap into #dest_cap */
1468     err = set_cap(dest_cap, src_cap);
1469     if (err_is_fail(err)) {
1470         return err;
1471     }
1472
1473     /* Transfer MDB attributes that must be equal for all copies */
1474 #define CP_ATTR(at) dest_cte->mdbnode.at = src_cte->mdbnode.at
1475     CP_ATTR(owner);
1476     CP_ATTR(locked);
1477     CP_ATTR(remote_copies);
1478     CP_ATTR(remote_ancs);
1479     CP_ATTR(remote_descs);
1480 #undef CP_ATTR
1481
1482     /* Copy is done */
1483     if(!mint) {
1484         TRACE_CAP_MSG("copied to", dest_cte);
1485         // Handle mapping here only for non-mint operations
1486         // (mint can change eq fields which would make the early insertion
1487         // invalid in some cases)
1488         mdb_insert(dest_cte);
1489         return SYS_ERR_OK;
1490     }
1491     else {
1492         TRACE_CAP_MSG("minting to", dest_cte);
1493     }
1494
1495     /* For minting, set the specified parameters */
1496     // Process source-specific parameters for minting
1497     // XXX: If failure, revert the insertion
1498     switch(src_cap->type) {
1499     case ObjType_CNode:
1500         if (param2 > CPTR_BITS) {
1501             return SYS_ERR_GUARD_SIZE_OVERFLOW;
1502         }
1503         dest_cap->u.cnode.guard      = param1;
1504         dest_cap->u.cnode.guard_size = param2;
1505         break;
1506
1507     case ObjType_EndPoint:
1508         // XXX: FIXME: check that buffer offset lies wholly within the disp frame
1509         // can't easily enforce this here, because the dispatcher frame may not
1510         // yet be setup
1511 /*        if (param1 < sizeof(struct dispatcher) ||
1512             dest_cap->u.endpoint.listener->disp == NULL ||
1513             param2 < IDC_RECV_LENGTH ||
1514             param1 + sizeof(struct idc_endpoint) + param2 * sizeof(uintptr_t) >
1515             (1UL << dest_cap->u.endpoint.listener->disp_cte.cap.u.frame.bits)) {
1516             return SYS_ERR_INVALID_EPBUF;
1517         }*/
1518         if (param2 < LMP_RECV_HEADER_LENGTH) {
1519             return SYS_ERR_INVALID_EPLEN;
1520         }
1521         dest_cap->u.endpoint.epoffset = param1;
1522         dest_cap->u.endpoint.epbuflen = param2;
1523         break;
1524
1525     case ObjType_IO:
1526         if(src_cap->u.io.start  <= param1) {
1527             dest_cap->u.io.start = param1;
1528         }
1529         if(src_cap->u.io.end  >= param2) {
1530             dest_cap->u.io.end = param2;
1531         }
1532         break;
1533
1534     default:
1535         // Unhandled source type for mint
1536         return SYS_ERR_INVALID_SOURCE_TYPE;
1537     }
1538
1539     // Insert after doing minting operation
1540     mdb_insert(dest_cte);
1541
1542     return SYS_ERR_OK;
1543 }