3 * \brief Capability system user code
7 * Copyright (c) 2007-2010, 2012, 2016, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
17 #include <barrelfish/barrelfish.h>
18 #include <barrelfish/cspace.h>
19 #include <barrelfish/caddr.h>
20 #include <barrelfish/lmp_endpoints.h>
21 #include <if/monitor_defs.h>
22 #include <if/monitor_blocking_defs.h>
23 #include <barrelfish/monitor_client.h>
24 #include <trace/trace.h>
28 #define ROOT_CNODE_INIT { \
29 .croot = CPTR_ROOTCN, \
31 .level = CNODE_TYPE_ROOT, }
33 struct cnoderef cnode_root = ROOT_CNODE_INIT;
35 #define TASK_CNODE_INIT { \
36 .croot = CPTR_ROOTCN, \
37 .cnode = CPTR_TASKCN_BASE, \
38 .level = CNODE_TYPE_OTHER, }
40 #define PAGE_CNODE_INIT { \
41 .croot = CPTR_ROOTCN, \
42 .cnode = CPTR_PAGECN_BASE, \
43 .level = CNODE_TYPE_OTHER, }
46 struct cnoderef cnode_task = TASK_CNODE_INIT;
49 struct cnoderef cnode_base = {
50 .cnode = CPTR_BASE_PAGE_CN_BASE,
51 .level = CNODE_TYPE_OTHER,
56 struct cnoderef cnode_super = {
57 .cnode = CPTR_SUPERCN_BASE,
58 .level = CNODE_TYPE_OTHER,
63 struct cnoderef cnode_page = PAGE_CNODE_INIT;
66 struct cnoderef cnode_module = {
67 .cnode = CPTR_MODULECN_BASE,
68 .level = CNODE_TYPE_OTHER,
72 /// Capability to Root CNode
73 struct capref cap_root = {
74 .cnode = TASK_CNODE_INIT,
75 .slot = TASKCN_SLOT_ROOTCN
78 /// Capability for IRQ table
79 struct capref cap_irq = {
80 .cnode = TASK_CNODE_INIT,
81 .slot = TASKCN_SLOT_IRQ
84 /// Capability for legacy IO
85 struct capref cap_io = {
86 .cnode = TASK_CNODE_INIT,
87 .slot = TASKCN_SLOT_IO
90 /// Capability for endpoint to self
91 struct capref cap_selfep = {
92 .cnode = TASK_CNODE_INIT,
93 .slot = TASKCN_SLOT_SELFEP
96 /// Capability for dispatcher
97 struct capref cap_dispatcher = {
98 .cnode = TASK_CNODE_INIT,
99 .slot = TASKCN_SLOT_DISPATCHER
102 /// Capability for dispatcher
103 struct capref cap_dispframe = {
104 .cnode = TASK_CNODE_INIT,
105 .slot = TASKCN_SLOT_DISPFRAME
108 /// Capability for ArgSpace
109 struct capref cap_argcn = {
110 .cnode = ROOT_CNODE_INIT,
111 .slot = ROOTCN_SLOT_ARGCN
114 /// Capability for monitor endpoint
115 struct capref cap_monitorep = {
116 .cnode = TASK_CNODE_INIT,
117 .slot = TASKCN_SLOT_MONITOREP
120 /// Capability for kernel (only in monitor)
121 struct capref cap_kernel = {
122 .cnode = TASK_CNODE_INIT,
123 .slot = TASKCN_SLOT_KERNELCAP
126 /// Capability for IPI sending (only in monitor)
127 struct capref cap_ipi = {
128 .cnode = TASK_CNODE_INIT,
129 .slot = TASKCN_SLOT_IPI
133 struct capref cap_perfmon = {
134 .cnode = TASK_CNODE_INIT,
135 .slot = TASKCN_SLOT_PERF_MON
138 /// Capability for endpoint to init (only in monitor/mem_serv)
139 struct capref cap_initep = {
140 .cnode = TASK_CNODE_INIT,
141 .slot = TASKCN_SLOT_INITEP
145 struct capref cap_sessionid = {
146 .cnode = TASK_CNODE_INIT,
147 .slot = TASKCN_SLOT_SESSIONID
150 /// Process manager cap, allows creating domains.
151 struct capref cap_procmng = {
152 .cnode = TASK_CNODE_INIT,
153 .slot = TASKCN_SLOT_PROC_MNG
157 struct capref cap_vroot = {
158 .cnode = PAGE_CNODE_INIT,
159 .slot = PAGECN_SLOT_VROOT,
162 static inline bool backoff(int count)
164 // very crude exponential backoff based upon core id
165 int yieldcnt = 2^count * disp_get_core_id();
166 for (int i=0; i<yieldcnt; i++) {
173 * \brief Retype a capability into one or more new capabilities, going through
174 * the monitor to ensure consistancy with other cores. Only necessary for
175 * caps that have been sent remotely.
177 static errval_t cap_retype_remote(struct capref src_root, struct capref dest_root,
178 capaddr_t src, gensize_t offset, enum objtype new_type,
179 gensize_t objsize, size_t count, capaddr_t to,
180 capaddr_t slot, int to_level)
182 struct monitor_blocking_binding *mrc = get_monitor_blocking_binding();
184 return LIB_ERR_MONITOR_RPC_NULL;
187 errval_t err, remote_cap_err;
190 err = mrc->rpc_tx_vtbl.remote_cap_retype(mrc, src_root, dest_root, src,
191 offset, (uint64_t)new_type, objsize,
192 count, to, slot, to_level, &remote_cap_err);
193 if (err_is_fail(err)){
194 DEBUG_ERR(err, "remote cap retype\n");
196 } while (err_no(remote_cap_err) == MON_ERR_REMOTE_CAP_RETRY && backoff(++send_count));
198 return remote_cap_err;
204 * \brief Delete the given capability, going through the monitor to ensure
205 * consistancy with other cores. Only necessary for caps that have been sent
208 * \param cap Capability to be deleted
210 * Deletes (but does not revoke) the given capability, allowing the CNode slot
213 static errval_t cap_delete_remote(struct capref root, capaddr_t src, uint8_t level)
215 struct monitor_blocking_binding *mrc = get_monitor_blocking_binding();
217 return LIB_ERR_MONITOR_RPC_NULL;
220 errval_t err, remote_cap_err;
223 err = mrc->rpc_tx_vtbl.remote_cap_delete(mrc, root, src, level,
225 if (err_is_fail(err)){
226 DEBUG_ERR(err, "remote cap delete\n");
228 } while (err_no(remote_cap_err) == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
230 return remote_cap_err;
234 * \brief Revoke (delete all copies and descendants of) the given capability,
235 * going through the monitor to ensure consistancy with other cores. Only
236 * necessary for caps that have been sent remotely.
238 * \param cap Capability to be revoked
240 * Deletes all copies and descendants of the given capability, but not the
241 * capability itself. If this succeeds, the capability is guaranteed to be
242 * the only copy in the system.
244 static errval_t cap_revoke_remote(struct capref root, capaddr_t src, uint8_t level)
246 struct monitor_blocking_binding *mrc = get_monitor_blocking_binding();
248 return LIB_ERR_MONITOR_RPC_NULL;
251 errval_t err, remote_cap_err;
254 err = mrc->rpc_tx_vtbl.remote_cap_revoke(mrc, root, src, level,
256 if (err_is_fail(err)){
257 DEBUG_ERR(err, "remote cap delete\n");
259 } while (err_no(remote_cap_err) == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
261 return remote_cap_err;
265 * \brief Retype (part of) a capability into one or more new capabilities
267 * \param dest_start Location of first destination slot, which must be empty
268 * \param src Source capability to retype
269 * \param offset Offset into source capability
270 * \param new_type Kernel object type to retype to.
271 * \param objsize Size of created objects in bytes
272 * (ignored for fixed-size objects)
273 * \param count The number of new objects to create
275 * When retyping IRQSrc capabilities, offset and objsize represent the start
276 * and end of the to be created interrupt range. Count must be 1 for IRQSrc.
278 * Retypes (part of) the given source capability into a number of new
279 * capabilities, which may be of the same or of different type. The new
280 * capabilities are created in the slots starting from dest_start, which must
281 * all be empty and lie in the same CNode. The number of objects created is
282 * determined by the argument `count`.
284 errval_t cap_retype(struct capref dest_start, struct capref src, gensize_t offset,
285 enum objtype new_type, gensize_t objsize, size_t count)
289 // Address of destination cspace
290 capaddr_t dcs_addr = get_croot_addr(dest_start);
291 // Address of the cap to the destination CNode
292 capaddr_t dcn_addr = get_cnode_addr(dest_start);
293 // Depth/Level of destination cnode
294 enum cnode_type dcn_level = get_cnode_level(dest_start);
295 // Address of source cspace
296 capaddr_t scp_root = get_croot_addr(src);
297 // Address of source capability
298 capaddr_t scp_addr = get_cap_addr(src);
300 err = invoke_cnode_retype(cap_root, scp_root, scp_addr, offset, new_type,
301 objsize, count, dcs_addr, dcn_addr, dcn_level,
304 if (err_no(err) == SYS_ERR_RETRY_THROUGH_MONITOR) {
305 struct capref src_root = get_croot_capref(src);
306 struct capref dest_root = get_croot_capref(dest_start);
307 return cap_retype_remote(src_root, dest_root, scp_addr, offset, new_type,
308 objsize, count, dcn_addr, dest_start.slot,
317 * \brief Create a capability
319 * \param dest Location where to create the cap, which must be empty.
320 * \param type Kernel object type to create.
321 * \param size Size of the created capability in bytes.
322 * (ignored for fixed-size objects)
324 * Only certain types of capabilities can be created this way. If invoked on
325 * a capability type, that is not creatable at runtime the error
326 * SYS_ERR_TYPE_NOT_CREATABLE is returned. Most capabilities have to be retyped
327 * from other capabilities with cap_retype().
329 errval_t cap_create(struct capref dest, enum objtype type, size_t size)
333 // Address of the cap to the destination CNode
334 capaddr_t dest_cnode_cptr = get_cnode_addr(dest);
335 enum cnode_type dest_cnode_level = get_cnode_level(dest);
337 err = invoke_cnode_create(cap_root, type, size, dest_cnode_cptr,
338 dest_cnode_level, dest.slot);
344 * \brief Delete the given capability
346 * \param cap Capability to be deleted
348 * Deletes (but does not revoke) the given capability, allowing the CNode slot
351 errval_t cap_delete(struct capref cap)
354 struct capref croot = get_croot_capref(cap);
355 capaddr_t caddr = get_cap_addr(cap);
356 enum cnode_type level = get_cap_level(cap);
358 err = invoke_cnode_delete(croot, caddr, level);
360 if (err_no(err) == SYS_ERR_RETRY_THROUGH_MONITOR) {
361 return cap_delete_remote(croot, caddr, level);
368 * \brief Revoke (delete all copies and descendants of) the given capability
370 * \param cap Capability to be revoked
372 * Deletes all copies and descendants of the given capability, but not the
373 * capability itself. If this succeeds, the capability is guaranteed to be
374 * the only copy in the system.
376 errval_t cap_revoke(struct capref cap)
379 struct capref croot = get_croot_capref(cap);
380 capaddr_t caddr = get_cap_addr(cap);
381 enum cnode_type level = get_cap_level(cap);
383 err = invoke_cnode_revoke(croot, caddr, level);
385 if (err_no(err) == SYS_ERR_RETRY_THROUGH_MONITOR) {
386 return cap_revoke_remote(croot, caddr, level);
393 * \brief Destroy a capability, i.e. delete it and free the slot.
395 * \param cap Capability to be destroyed
397 errval_t cap_destroy(struct capref cap)
400 err = cap_delete(cap);
401 if (err_is_fail(err)) {
405 err = slot_free(cap);
406 if (err_is_fail(err)) {
407 return err_push(err, LIB_ERR_WHILE_FREEING_SLOT);
414 * \brief Replace own L1 CNode
416 * \param new the replacement L1 CNode
417 * \param ret the slot to put the old L1 CNode
419 errval_t root_cnode_resize(struct capref new, struct capref ret)
421 assert(get_croot_addr(new) == CPTR_ROOTCN);
422 assert(get_cap_level(new) == CNODE_TYPE_COUNT);
423 capaddr_t new_cptr = get_cap_addr(new);
425 assert(get_croot_addr(ret) == CPTR_ROOTCN);
426 assert(get_cap_level(ret) == CNODE_TYPE_COUNT);
427 capaddr_t retcn_ptr= get_cnode_addr(ret);
429 return invoke_cnode_resize(cap_root, new_cptr, retcn_ptr, ret.slot);
433 * \brief Create a CNode from a given RAM capability in a specific slot
435 * \param dest location in which to place newly-created CNode cap
436 * \param src location of RAM capability to be retyped to new CNode
437 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
438 * \param slots number of slots in created CNode
439 * must match size of RAM capability.
441 * This function requires that dest refer to an existing but empty slot. It
442 * retypes the given memory to a new CNode.
444 errval_t cnode_create_from_mem(struct capref dest, struct capref src,
445 enum objtype cntype, struct cnoderef *cnoderef,
450 if (cntype != ObjType_L1CNode &&
451 cntype != ObjType_L2CNode)
453 return LIB_ERR_CNODE_TYPE;
457 // Retype it to the destination
458 err = cap_retype(dest, src, 0, cntype, slots * (1UL << OBJBITS_CTE), 1);
459 if (err_is_fail(err)) {
460 return err_push(err, LIB_ERR_CAP_RETYPE);
463 // Construct the cnoderef to return
464 if (cnoderef != NULL) {
465 enum cnode_type ref_cntype = cntype == ObjType_L1CNode ? CNODE_TYPE_ROOT : CNODE_TYPE_OTHER;
466 *cnoderef = build_cnoderef(dest, ref_cntype);
473 * \brief Create a CNode from newly-allocated RAM in a newly-allocated slot
475 * \param ret_dest capref struct to be filled-in with location of CNode
476 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
477 * \param slots Minimum number of slots in created CNode
478 * \param retslots If non-NULL, filled in with the number of slots in created CNode
480 errval_t cnode_create(struct capref *ret_dest, struct cnoderef *cnoderef,
481 cslot_t slots, cslot_t *retslots)
483 USER_PANIC("cnode_create deprecated; use cnode_create_l1, cnode_create_l2, or cnode_create_foreign_l2: %p %p %p %p\n",
484 __builtin_return_address(0),
486 __builtin_return_address(1),
487 __builtin_return_address(2),
488 __builtin_return_address(3)
493 return LIB_ERR_NOT_IMPLEMENTED;
497 * \brief Create a L2 CNode from newly-allocated RAM in a newly-allocated slot
499 * \param ret_dest capref struct to be filled-in with location of CNode
500 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
502 * This function always creates a L2 CNode which contains 256 capabilities
504 errval_t cnode_create_l2(struct capref *ret_dest, struct cnoderef *cnoderef)
508 // Allocate a slot in root cn for destination
509 assert(ret_dest != NULL);
510 err = slot_alloc_root(ret_dest);
511 if (err_is_fail(err)) {
512 return err_push(err, LIB_ERR_SLOT_ALLOC);
516 err = cnode_create_raw(*ret_dest, cnoderef, ObjType_L2CNode,
517 L2_CNODE_SLOTS, &retslots);
518 if (retslots != L2_CNODE_SLOTS) {
519 debug_printf("Unable to create properly sized L2 CNode: got %"PRIuCSLOT" slots instead of %"PRIuCSLOT"\n",
520 retslots, (cslot_t)L2_CNODE_SLOTS);
525 errval_t cnode_create_l1(struct capref *ret_dest, struct cnoderef *cnoderef)
529 // Allocate a slot in root cn for destination
530 assert(ret_dest != NULL);
531 err = slot_alloc(ret_dest);
532 if (err_is_fail(err)) {
533 return err_push(err, LIB_ERR_SLOT_ALLOC);
537 err = cnode_create_raw(*ret_dest, cnoderef, ObjType_L1CNode,
538 L2_CNODE_SLOTS, &retslots);
539 if (retslots != L2_CNODE_SLOTS) {
540 debug_printf("Unable to create initial L1 CNode: got %"PRIuCSLOT" slots instead of %"PRIuCSLOT"\n",
541 retslots, (cslot_t)L2_CNODE_SLOTS);
547 * \brief Create a CNode for another cspace from newly-allocated RAM in a
548 * newly-allocated slot
550 * \param dest_l1 capref to L1 (root) cnode of destination cspace
551 * \param dest_slot slot to fill with new cnode in destination L1 cnode
552 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
554 * This function creates a CNode which contains 256 capabilities initially
555 * and puts it in a slot in our cspace.
557 errval_t cnode_create_foreign_l2(struct capref dest_l1, cslot_t dest_slot,
558 struct cnoderef *cnoderef)
562 if (capref_is_null(dest_l1)) {
563 return LIB_ERR_CROOT_NULL;
565 assert(!capref_is_null(dest_l1));
568 dest.cnode = build_cnoderef(dest_l1, CNODE_TYPE_ROOT);
569 dest.slot = dest_slot;
572 err = cnode_create_raw(dest, NULL, ObjType_L2CNode, L2_CNODE_SLOTS, &retslots);
573 if (retslots != L2_CNODE_SLOTS) {
574 debug_printf("Unable to create properly sized foreign CNode: "
575 "got %"PRIuCSLOT" slots instead of %"PRIuCSLOT"\n",
576 retslots, (cslot_t)L2_CNODE_SLOTS);
579 // Create proper cnoderef for foreign L2
581 cnoderef->croot = get_cap_addr(dest_l1);
582 cnoderef->cnode = ROOTCN_SLOT_ADDR(dest_slot);
583 cnoderef->level = CNODE_TYPE_OTHER;
589 * \brief Create a CNode from newly-allocated RAM in the given slot
591 * \param dest location in which to place CNode cap
592 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
593 * \param cntype, type of new cnode
594 * \param slots Minimum number of slots in created CNode
595 * \param retslots If non-NULL, filled in with the number of slots in created CNode
597 * This function requires that dest refer to an existing but empty slot. It
598 * allocates memory (using #ram_alloc), and retypes that memory to a new CNode.
599 * The intermediate ram cap is destroyed.
601 errval_t cnode_create_raw(struct capref dest, struct cnoderef *cnoderef,
602 enum objtype cntype, cslot_t slots, cslot_t *retslots)
609 if (cntype != ObjType_L1CNode &&
610 cntype != ObjType_L2CNode)
612 return LIB_ERR_CNODE_TYPE;
615 if (slots < L2_CNODE_SLOTS ||
616 (cntype == ObjType_L2CNode && slots != L2_CNODE_SLOTS))
618 return LIB_ERR_CNODE_SLOTS;
621 if (retslots != NULL) {
625 // XXX: mem_serv should serve non-power-of-two requests
626 uint8_t bits = log2ceil(slots);
627 assert(slots >= (1UL << bits));
629 // Allocate some memory
630 err = ram_alloc(&ram, bits + OBJBITS_CTE);
631 if (err_is_fail(err)) {
632 return err_push(err, LIB_ERR_RAM_ALLOC);
635 err = cnode_create_from_mem(dest, ram, cntype, cnoderef, slots);
636 if (err_is_fail(err)) {
637 return err_push(err, LIB_ERR_CNODE_CREATE_FROM_MEM);
640 err = cap_destroy(ram);
641 if (err_is_fail(err)) {
642 return err_push(err, LIB_ERR_CAP_DESTROY);
649 * \brief Create CNode with a given guard
651 * \param dest Location where to place the cnode
652 * \param cnoderef Filled in cnoderef struct if non-NULL
653 * \param slots Minimum number of slots in created CNode
654 * \param retslots If non-NULL, filled in with the number of slots in created CNode
655 * \param guard The guard value to set
656 * \param guard_size The length of the guard in bits
658 * This function requires that dest refer to an existing but empty slot. It
659 * allocates memory (using #ram_alloc), and retypes that memory to a new CNode
660 * with the given guard value and size. An intermediate slot is used in order to
661 * set the guard value.
663 errval_t cnode_create_with_guard(struct capref dest, struct cnoderef *cnoderef,
664 cslot_t slots, cslot_t *retslots,
665 uint64_t guard, uint8_t guard_size)
667 USER_PANIC("%s: GPT CNodes are deprecated\n", __FUNCTION__);
671 * \brief Create a VNode in newly-allocated memory
673 * \param dest location to place new VNode cap
674 * \param type VNode type to create
676 * This function requires that dest refer to an existing but empty slot.
677 * The intermidiate ram cap is destroyed.
679 errval_t vnode_create(struct capref dest, enum objtype type)
685 size_t objbits_vnode = vnode_objbits(type);
686 err = ram_alloc(&ram, objbits_vnode);
687 if (err_no(err) == LIB_ERR_RAM_ALLOC_WRONG_SIZE && type != ObjType_VNode_ARM_l1) {
688 // can only get 4kB pages, cannot create ARM_l1, and waste 3kB for
690 err = ram_alloc(&ram, BASE_PAGE_BITS);
692 if (err_is_fail(err)) {
693 return err_push(err, LIB_ERR_RAM_ALLOC);
696 assert(type_is_vnode(type));
697 err = cap_retype(dest, ram, 0, type, vnode_objsize(type), 1);
698 if (err_is_fail(err)) {
699 return err_push(err, LIB_ERR_CAP_RETYPE);
702 err = cap_destroy(ram);
703 if (err_is_fail(err)) {
704 return err_push(err, LIB_ERR_CAP_DESTROY);
711 * \brief Create a Frame cap referring to newly-allocated RAM in a given slot
713 * \param dest Location to place new frame cap
714 * \param bytes Minimum size of frame to create
715 * \param retbytes If non-NULL, filled in with size of created frame
717 * This function requires that dest refer to an existing but empty slot.
718 * #ram_alloc is used to allocate memory. After retyping the intermediate
719 * ram cap is destroyed.
721 * This function will returns a special error code if ram_alloc fails
722 * due to the constrains on the memory server (size of cap or region
723 * of memory). This is to facilitate retrying with different
726 errval_t frame_create(struct capref dest, size_t bytes, size_t *retbytes)
729 uint8_t bits = log2ceil(bytes);
730 assert((1UL << bits) >= bytes);
733 if (bits < BASE_PAGE_BITS) {
734 bits = BASE_PAGE_BITS;
738 err = ram_alloc(&ram, bits);
739 if (err_is_fail(err)) {
740 if (err_no(err) == MM_ERR_NOT_FOUND ||
741 err_no(err) == LIB_ERR_RAM_ALLOC_WRONG_SIZE) {
742 return err_push(err, LIB_ERR_RAM_ALLOC_MS_CONSTRAINTS);
744 return err_push(err, LIB_ERR_RAM_ALLOC);
747 err = cap_retype(dest, ram, 0, ObjType_Frame, (1UL << bits), 1);
748 if (err_is_fail(err)) {
749 return err_push(err, LIB_ERR_CAP_RETYPE);
752 err = cap_destroy(ram);
753 if (err_is_fail(err)) {
754 return err_push(err, LIB_ERR_CAP_DESTROY);
757 if (retbytes != NULL) {
758 *retbytes = 1UL << bits;
765 * \brief Create a Dispatcher in newly-allocated memory
767 * \param dest location to place new dispatcher cap
769 * This function requires that dest refer to an existing but empty slot. It does
770 * not map in nor initialise the Dispatcher.
771 * The intermediate ram cap is destroyed.
773 errval_t dispatcher_create(struct capref dest)
778 assert(1 << log2ceil(OBJSIZE_DISPATCHER) == OBJSIZE_DISPATCHER);
779 err = ram_alloc(&ram, log2ceil(OBJSIZE_DISPATCHER));
780 if (err_is_fail(err)) {
781 return err_push(err, LIB_ERR_RAM_ALLOC);
784 err = cap_retype(dest, ram, 0, ObjType_Dispatcher, 0, 1);
785 if (err_is_fail(err)) {
786 return err_push(err, LIB_ERR_CAP_RETYPE);
789 err = cap_destroy(ram);
790 if (err_is_fail(err)) {
791 return err_push(err, LIB_ERR_CAP_DESTROY);
797 * \brief Create endpoint to caller on current dispatcher.
799 * \param buflen Length of incoming LMP buffer, in words
800 * \param retcap Pointer to capref struct, filled-in with location of cap
801 * \param retep Double pointer to LMP endpoint, filled-in with allocated EP
803 errval_t endpoint_create(size_t buflen, struct capref *retcap,
804 struct lmp_endpoint **retep)
806 errval_t err = slot_alloc(retcap);
807 if (err_is_fail(err)) {
808 return err_push(err, LIB_ERR_SLOT_ALLOC);
811 return lmp_endpoint_create_in_slot(buflen, *retcap, retep);
815 * \brief Create a Frame cap referring to newly-allocated RAM in an allocated slot
817 * \param dest Pointer to capref struct, filled-in with location of new cap
818 * \param bytes Minimum size of frame to create
819 * \param retbytes If non-NULL, filled in with size of created frame
821 errval_t frame_alloc(struct capref *dest, size_t bytes, size_t *retbytes)
823 errval_t err = slot_alloc(dest);
824 if (err_is_fail(err)) {
825 return err_push(err, LIB_ERR_SLOT_ALLOC);
828 return frame_create(*dest, bytes, retbytes);
832 * \brief Create a DevFrame cap by retyping out of given source PhysAddr cap
834 * \param dest Pointer to capref struct, filled-in with location of new cap
835 * \param src Cap_info struct for the source PhysAddr cap
836 * \param size_bits Size of created objects as a power of two
837 * (ignored for fixed-size objects)
839 errval_t devframe_type(struct capref *dest, struct capref src, uint8_t bits)
841 errval_t err = slot_alloc(dest);
842 if (err_is_fail(err)) {
843 return err_push(err, LIB_ERR_SLOT_ALLOC);
846 return cap_retype(*dest, src, 0, ObjType_DevFrame, 1UL << bits, 1);
850 * \brief Create an ID cap in a newly allocated slot.
852 * \param dest Pointer to capref struct, filld-in with location of new cap.
854 * The caller is responsible for revoking the cap after using it.
856 errval_t idcap_alloc(struct capref *dest)
858 errval_t err = slot_alloc(dest);
860 if (err_is_fail(err)) {
861 return err_push(err, LIB_ERR_SLOT_ALLOC);
864 return idcap_create(*dest);
868 * \brief Create an ID cap in the specified slot.
870 * \param dest Capref, where ID cap should be created.
872 * The caller is responsible for revoking the cap after using it.
874 errval_t idcap_create(struct capref dest)
876 return cap_create(dest, ObjType_ID, 0);
880 * \brief Builds a #cnoderef struct from a #capref struct using cap
883 * \param cnoder Pointer to a cnoderef struct, fill-in by function.
884 * \param capr Capref to a CNode capability.
886 errval_t cnode_build_cnoderef(struct cnoderef *cnoder, struct capref capr)
888 struct capability cap;
889 errval_t err = debug_cap_identify(capr, &cap);
890 if (err_is_fail(err)) {
894 if (cap.type != ObjType_L1CNode &&
895 cap.type != ObjType_L2CNode) {
896 return LIB_ERR_NOT_CNODE;
899 if (!cnodecmp(capr.cnode, cnode_root)) {
900 USER_PANIC("cnode_build_cnoderef NYI for non rootcn caprefs");
903 cnoder->croot = get_croot_addr(capr);
904 cnoder->cnode = capr.slot << L2_CNODE_BITS;
905 cnoder->level = CNODE_TYPE_OTHER;