3 * \brief Capability system user code
7 * Copyright (c) 2007, 2008, 2009, 2010, 2012, 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, Haldeneggsteig 4, 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_rpcclient_defs.h>
23 #include <barrelfish/monitor_client.h>
24 #include <trace/trace.h>
27 struct cnoderef cnode_root = {
28 .address = CPTR_ROOTCN,
29 .address_bits = CPTR_BITS,
30 .size_bits = DEFAULT_CNODE_BITS,
34 #define TASK_CNODE_INIT { \
36 .address_bits = DEFAULT_CNODE_BITS, \
37 .size_bits = DEFAULT_CNODE_BITS, \
38 .guard_size = GUARD_REMAINDER(2 * DEFAULT_CNODE_BITS) }
41 struct cnoderef cnode_task = TASK_CNODE_INIT;
44 struct cnoderef cnode_base = {
45 .address = CPTR_BASE_PAGE_CN_BASE,
46 .address_bits = DEFAULT_CNODE_BITS,
47 .size_bits = DEFAULT_CNODE_BITS,
52 struct cnoderef cnode_super0 = {
53 .address = CPTR_SUPERCN0_BASE,
54 .address_bits = DEFAULT_CNODE_BITS,
55 .size_bits = DEFAULT_CNODE_BITS,
58 struct cnoderef cnode_super1 = {
59 .address = CPTR_SUPERCN1_BASE,
60 .address_bits = DEFAULT_CNODE_BITS,
61 .size_bits = DEFAULT_CNODE_BITS,
66 struct cnoderef cnode_page = {
67 .address = ROOTCN_SLOT_PAGECN << DEFAULT_CN_ADDR_BITS,
68 .address_bits = DEFAULT_CNODE_BITS,
69 .size_bits = PAGE_CNODE_BITS,
74 struct cnoderef cnode_module = {
75 .address = CPTR_MODULECN_BASE,
76 .address_bits = DEFAULT_CNODE_BITS,
77 .size_bits = MODULECN_SIZE_BITS,
81 /// Capability to Root CNode
82 struct capref cap_root = {
83 .cnode = TASK_CNODE_INIT,
84 .slot = TASKCN_SLOT_ROOTCN
87 /// Capability for IRQ table
88 struct capref cap_irq = {
89 .cnode = TASK_CNODE_INIT,
90 .slot = TASKCN_SLOT_IRQ
93 /// Capability for legacy IO
94 struct capref cap_io = {
95 .cnode = TASK_CNODE_INIT,
96 .slot = TASKCN_SLOT_IO
99 /// Capability for endpoint to self
100 struct capref cap_selfep = {
101 .cnode = TASK_CNODE_INIT,
102 .slot = TASKCN_SLOT_SELFEP
105 /// Capability for dispatcher
106 struct capref cap_dispatcher = {
107 .cnode = TASK_CNODE_INIT,
108 .slot = TASKCN_SLOT_DISPATCHER
111 /// Capability for dispatcher
112 struct capref cap_dispframe = {
113 .cnode = TASK_CNODE_INIT,
114 .slot = TASKCN_SLOT_DISPFRAME
117 #define ROOT_CNODE_INIT { \
118 .address = CPTR_ROOTCN, \
119 .address_bits = CPTR_BITS, \
120 .size_bits = DEFAULT_CNODE_BITS, \
123 /// Capability for monitor endpoint
124 struct capref cap_monitorep = {
125 .cnode = ROOT_CNODE_INIT,
126 .slot = ROOTCN_SLOT_MONITOREP
129 /// Capability for kernel (only in monitor)
130 struct capref cap_kernel = {
131 .cnode = TASK_CNODE_INIT,
132 .slot = TASKCN_SLOT_KERNELCAP
136 struct capref cap_perfmon = {
137 .cnode = TASK_CNODE_INIT,
138 .slot = TASKCN_SLOT_PERF_MON
141 /// Capability for endpoint to init (only in monitor/mem_serv)
142 struct capref cap_initep = {
143 .cnode = TASK_CNODE_INIT,
144 .slot = TASKCN_SLOT_INITEP
148 struct capref cap_sessionid = {
149 .cnode = TASK_CNODE_INIT,
150 .slot = TASKCN_SLOT_SESSIONID
153 static inline bool backoff(int count)
155 // very crude exponential backoff based upon core id
156 int yieldcnt = 2^count * disp_get_core_id();
157 for (int i=0; i<yieldcnt; i++) {
164 * \brief Retype a capability into one or more new capabilities, going through
165 * the monitor to ensure consistancy with other cores. Only necessary for
166 * caps that have been sent remotely.
168 static errval_t cap_retype_remote(capaddr_t src, enum objtype new_type,
169 uint8_t size_bits, capaddr_t to, capaddr_t slot,
172 struct monitor_blocking_rpc_client *mrc = get_monitor_blocking_rpc_client();
173 errval_t err, remote_cap_err;
176 err = mrc->vtbl.remote_cap_retype(mrc, cap_root, src,
179 dcn_vbits, &remote_cap_err);
180 if (err_is_fail(err)){
181 DEBUG_ERR(err, "remote cap retype\n");
183 } while (remote_cap_err == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
185 return remote_cap_err;
191 * \brief Delete the given capability, going through the monitor to ensure
192 * consistancy with other cores. Only necessary for caps that have been sent
195 * \param cap Capability to be deleted
197 * Deletes (but does not revoke) the given capability, allowing the CNode slot
200 static errval_t cap_delete_remote(capaddr_t src, uint8_t vbits)
202 struct monitor_blocking_rpc_client *mrc = get_monitor_blocking_rpc_client();
203 errval_t err, remote_cap_err;
206 err = mrc->vtbl.remote_cap_delete(mrc, cap_root, src, vbits,
208 if (err_is_fail(err)){
209 DEBUG_ERR(err, "remote cap delete\n");
211 } while (remote_cap_err == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
213 return remote_cap_err;
217 * \brief Revoke (delete all copies and descendants of) the given capability,
218 * going through the monitor to ensure consistancy with other cores. Only
219 * necessary for caps that have been sent remotely.
221 * \param cap Capability to be revoked
223 * Deletes all copies and descendants of the given capability, but not the
224 * capability itself. If this succeeds, the capability is guaranteed to be
225 * the only copy in the system.
227 static errval_t cap_revoke_remote(capaddr_t src, uint8_t vbits)
229 struct monitor_blocking_rpc_client *mrc = get_monitor_blocking_rpc_client();
230 errval_t err, remote_cap_err;
233 err = mrc->vtbl.remote_cap_revoke(mrc, cap_root, src, vbits,
235 if (err_is_fail(err)){
236 DEBUG_ERR(err, "remote cap delete\n");
238 } while (remote_cap_err == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
240 return remote_cap_err;
244 * \brief Retype a capability into one or more new capabilities
246 * \param dest_start Location of first destination slot, which must be empty
247 * \param src Source capability to retype
248 * \param new_type Kernel object type to retype to.
249 * \param size_bits Size of created objects as a power of two
250 * (ignored for fixed-size objects)
252 * Retypes the given source capability into a number of new capabilities, which
253 * may be of the same or of different type. The new capabilities are created
254 * in the slots starting from dest_start, which must all be empty and lie in the
255 * same CNode. The number of objects created is determined by the size of the
256 * source object divided by the size of the destination objects.
258 errval_t cap_retype(struct capref dest_start, struct capref src,
259 enum objtype new_type, uint8_t size_bits)
262 // Number of valid bits in destination CNode address
263 uint8_t dcn_vbits = get_cnode_valid_bits(dest_start);
264 // Address of the cap to the destination CNode
265 capaddr_t dcn_addr = get_cnode_addr(dest_start);
266 // Address of source capability
267 capaddr_t scp_addr = get_cap_addr(src);
269 err = invoke_cnode_retype(cap_root, scp_addr, new_type, size_bits,
270 dcn_addr, dest_start.slot, dcn_vbits);
272 if (err == SYS_ERR_RETRY_THROUGH_MONITOR) {
273 return cap_retype_remote(scp_addr, new_type, size_bits,
274 dcn_addr, dest_start.slot, dcn_vbits);
282 * \brief Create a capability
284 * \param dest Location where to create the cap, which must be empty.
285 * \param type Kernel object type to create.
286 * \param size_bits Size of the created capability as a power of two.
287 * (ignored for fixed-size objects)
289 * Only certain types of capabilities can be created this way. If invoked on
290 * a capability type, that is not creatable at runtime the error
291 * SYS_ERR_TYPE_NOT_CREATABLE is returned. Most capabilities have to be retyped
292 * from other capabilities with cap_retype().
294 errval_t cap_create(struct capref dest, enum objtype type, uint8_t size_bits)
298 // Number of valid bits in the destination CNode address
299 uint8_t dest_vbits = get_cnode_valid_bits(dest);
300 // Address of the cap to the destination CNode
301 capaddr_t dest_cnode_cptr = get_cnode_addr(dest);
303 err = invoke_cnode_create(cap_root, type, size_bits, dest_cnode_cptr,
304 dest.slot, dest_vbits);
310 * \brief Delete the given capability
312 * \param cap Capability to be deleted
314 * Deletes (but does not revoke) the given capability, allowing the CNode slot
317 errval_t cap_delete(struct capref cap)
320 uint8_t vbits = get_cap_valid_bits(cap);
321 capaddr_t caddr = get_cap_addr(cap) >> (CPTR_BITS - vbits);
323 err = invoke_cnode_delete(cap_root, caddr, vbits);
325 if (err == SYS_ERR_RETRY_THROUGH_MONITOR) {
326 return cap_delete_remote(caddr, vbits);
333 * \brief Revoke (delete all copies and descendants of) the given capability
335 * \param cap Capability to be revoked
337 * Deletes all copies and descendants of the given capability, but not the
338 * capability itself. If this succeeds, the capability is guaranteed to be
339 * the only copy in the system.
341 errval_t cap_revoke(struct capref cap)
344 uint8_t vbits = get_cap_valid_bits(cap);
345 capaddr_t caddr = get_cap_addr(cap) >> (CPTR_BITS - vbits);
347 err = invoke_cnode_revoke(cap_root, caddr, vbits);
349 if (err == SYS_ERR_RETRY_THROUGH_MONITOR) {
350 return cap_revoke_remote(caddr, vbits);
357 * \brief Destroy a capability, i.e. delete it and free the slot.
359 * \param cap Capability to be destroyed
361 errval_t cap_destroy(struct capref cap)
364 err = cap_delete(cap);
365 if (err_is_fail(err)) {
369 err = slot_free(cap);
370 if (err_is_fail(err)) {
371 return err_push(err, LIB_ERR_WHILE_FREEING_SLOT);
378 * \brief Create a CNode from a given RAM capability in a specific slot
380 * \param dest location in which to place newly-created CNode cap
381 * \param src location of RAM capability to be retyped to new CNode
382 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
383 * \param slot_bits number of slots in created CNode as a power of two.
384 * must match size of RAM capability.
386 * This function requires that dest refer to an existing but empty slot. It
387 * retypes the given memory to a new CNode.
389 errval_t cnode_create_from_mem(struct capref dest, struct capref src,
390 struct cnoderef *cnoderef, uint8_t slot_bits)
394 // Retype it to the destination
395 err = cap_retype(dest, src, ObjType_CNode, slot_bits);
396 if (err_is_fail(err)) {
397 return err_push(err, LIB_ERR_CAP_RETYPE);
400 // Construct the cnoderef to return
401 if (cnoderef != NULL) {
402 *cnoderef = build_cnoderef(dest, slot_bits);
409 * \brief Create a CNode from newly-allocated RAM in a newly-allocated slot
411 * \param ret_dest capref struct to be filled-in with location of CNode
412 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
413 * \param slots Minimum number of slots in created CNode
414 * \param retslots If non-NULL, filled in with the number of slots in created CNode
416 errval_t cnode_create(struct capref *ret_dest, struct cnoderef *cnoderef,
417 cslot_t slots, cslot_t *retslots)
421 // Allocate a slot for destination.
422 assert(ret_dest != NULL);
423 err = slot_alloc(ret_dest);
424 if (err_is_fail(err)) {
425 return err_push(err, LIB_ERR_SLOT_ALLOC);
428 // Use cnode_create_raw
429 return cnode_create_raw(*ret_dest, cnoderef, slots, retslots);
433 * \brief Create a CNode from newly-allocated RAM in the given slot
435 * \param dest location in which to place CNode cap
436 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
437 * \param slots Minimum number of slots in created CNode
438 * \param retslots If non-NULL, filled in with the number of slots in created CNode
440 * This function requires that dest refer to an existing but empty slot. It
441 * allocates memory (using #ram_alloc), and retypes that memory to a new CNode.
442 * The intermediate ram cap is destroyed.
444 errval_t cnode_create_raw(struct capref dest, struct cnoderef *cnoderef,
445 cslot_t slots, cslot_t *retslots)
451 uint8_t bits = log2ceil(slots);
452 assert((1UL << bits) >= slots);
453 if (bits < DEFAULT_CNODE_BITS) {
454 bits = DEFAULT_CNODE_BITS;
457 if (retslots != NULL) {
458 *retslots = 1UL << bits;
461 // Allocate some memory
462 err = ram_alloc(&ram, bits + OBJBITS_CTE);
463 if (err_is_fail(err)) {
464 return err_push(err, LIB_ERR_RAM_ALLOC);
467 err = cnode_create_from_mem(dest, ram, cnoderef, bits);
468 if (err_is_fail(err)) {
469 return err_push(err, LIB_ERR_CNODE_CREATE_FROM_MEM);
472 err = cap_destroy(ram);
473 if (err_is_fail(err)) {
474 return err_push(err, LIB_ERR_CAP_DESTROY);
481 * \brief Create CNode with a given guard
483 * \param dest Location where to place the cnode
484 * \param cnoderef Filled in cnoderef struct if non-NULL
485 * \param slots Minimum number of slots in created CNode
486 * \param retslots If non-NULL, filled in with the number of slots in created CNode
487 * \param guard The guard value to set
488 * \param guard_size The length of the guard in bits
490 * This function requires that dest refer to an existing but empty slot. It
491 * allocates memory (using #ram_alloc), and retypes that memory to a new CNode
492 * with the given guard value and size. An intermediate slot is used in order to
493 * set the guard value.
495 errval_t cnode_create_with_guard(struct capref dest, struct cnoderef *cnoderef,
496 cslot_t slots, cslot_t *retslots,
497 uint64_t guard, uint8_t guard_size)
501 /* Create an intermediate cnode cap */
503 err = cnode_create(&inter, NULL, slots, retslots);
504 if (err_is_fail(err)) {
505 return err_push(err, LIB_ERR_CNODE_CREATE);
508 /* Mint it to the new destination setting the guard */
509 err = cap_mint(dest, inter, guard, guard_size);
510 if (err_is_fail(err)) {
511 return err_push(err, LIB_ERR_CAP_MINT);
514 /* Free the intermediate cnode cap and slot */
515 err = cap_delete(inter);
516 if (err_is_fail(err)) {
517 return err_push(err, LIB_ERR_WHILE_DELETING);
519 err = slot_free(inter);
520 if (err_is_fail(err)) {
521 return err_push(err, LIB_ERR_WHILE_FREEING_SLOT);
524 /* Build the cnoderef */
525 if (cnoderef != NULL) {
527 uint8_t bits = log2ceil(slots);
528 assert((1UL << bits) >= slots);
529 if (bits < DEFAULT_CNODE_BITS) {
530 bits = DEFAULT_CNODE_BITS;
532 *cnoderef = build_cnoderef(dest, bits);
533 cnoderef->guard_size = guard_size;
540 * \brief Create a VNode in newly-allocated memory
542 * \param dest location to place new VNode cap
543 * \param type VNode type to create
545 * This function requires that dest refer to an existing but empty slot.
546 * The intermidiate ram cap is destroyed.
548 errval_t vnode_create(struct capref dest, enum objtype type)
554 size_t objbits_vnode = vnode_objbits(type);
555 err = ram_alloc(&ram, objbits_vnode);
556 if (err_is_fail(err)) {
557 return err_push(err, LIB_ERR_RAM_ALLOC);
560 assert(type_is_vnode(type));
561 err = cap_retype(dest, ram, type, 0);
562 if (err_is_fail(err)) {
563 return err_push(err, LIB_ERR_CAP_RETYPE);
566 err = cap_destroy(ram);
567 if (err_is_fail(err)) {
568 return err_push(err, LIB_ERR_CAP_DESTROY);
575 * \brief Create a Frame cap referring to newly-allocated RAM in a given slot
577 * \param dest Location to place new frame cap
578 * \param bytes Minimum size of frame to create
579 * \param retbytes If non-NULL, filled in with size of created frame
581 * This function requires that dest refer to an existing but empty slot.
582 * #ram_alloc is used to allocate memory. After retyping the intermediate
583 * ram cap is destroyed.
585 * This function will returns a special error code if ram_alloc fails
586 * due to the constrains on the memory server (size of cap or region
587 * of memory). This is to facilitate retrying with different
590 errval_t frame_create(struct capref dest, size_t bytes, size_t *retbytes)
593 uint8_t bits = log2ceil(bytes);
594 assert((1UL << bits) >= bytes);
597 if (bits < BASE_PAGE_BITS) {
598 bits = BASE_PAGE_BITS;
602 err = ram_alloc(&ram, bits);
603 if (err_is_fail(err)) {
604 if (err_no(err) == MM_ERR_NOT_FOUND ||
605 err_no(err) == LIB_ERR_RAM_ALLOC_WRONG_SIZE) {
606 return err_push(err, LIB_ERR_RAM_ALLOC_MS_CONSTRAINTS);
608 return err_push(err, LIB_ERR_RAM_ALLOC);
611 err = cap_retype(dest, ram, ObjType_Frame, bits);
612 if (err_is_fail(err)) {
613 return err_push(err, LIB_ERR_CAP_RETYPE);
616 err = cap_destroy(ram);
617 if (err_is_fail(err)) {
621 if (retbytes != NULL) {
622 *retbytes = 1UL << bits;
629 * \brief Create a Dispatcher in newly-allocated memory
631 * \param dest location to place new dispatcher cap
633 * This function requires that dest refer to an existing but empty slot. It does
634 * not map in nor initialise the Dispatcher.
635 * The intermediate ram cap is destroyed.
637 errval_t dispatcher_create(struct capref dest)
642 err = ram_alloc(&ram, OBJBITS_DISPATCHER);
643 if (err_is_fail(err)) {
644 return err_push(err, LIB_ERR_RAM_ALLOC);
647 err = cap_retype(dest, ram, ObjType_Dispatcher, 0);
648 if (err_is_fail(err)) {
649 return err_push(err, LIB_ERR_CAP_RETYPE);
652 err = cap_destroy(ram);
653 if (err_is_fail(err)) {
654 return err_push(err, LIB_ERR_CAP_DESTROY);
660 * \brief Create endpoint to caller on current dispatcher.
662 * \param buflen Length of incoming LMP buffer, in words
663 * \param retcap Pointer to capref struct, filled-in with location of cap
664 * \param retep Double pointer to LMP endpoint, filled-in with allocated EP
666 errval_t endpoint_create(size_t buflen, struct capref *retcap,
667 struct lmp_endpoint **retep)
669 errval_t err = slot_alloc(retcap);
670 if (err_is_fail(err)) {
671 return err_push(err, LIB_ERR_SLOT_ALLOC);
674 return lmp_endpoint_create_in_slot(buflen, *retcap, retep);
678 * \brief Create a Frame cap referring to newly-allocated RAM in an allocated slot
680 * \param dest Pointer to capref struct, filled-in with location of new cap
681 * \param bytes Minimum size of frame to create
682 * \param retbytes If non-NULL, filled in with size of created frame
684 errval_t frame_alloc(struct capref *dest, size_t bytes, size_t *retbytes)
686 errval_t err = slot_alloc(dest);
687 if (err_is_fail(err)) {
688 return err_push(err, LIB_ERR_SLOT_ALLOC);
691 return frame_create(*dest, bytes, retbytes);
695 * \brief Create a DevFrame cap by retyping out of given source PhysAddr cap
697 * \param dest Pointer to capref struct, filled-in with location of new cap
698 * \param src Cap_info struct for the source PhysAddr cap
699 * \param size_bits Size of created objects as a power of two
700 * (ignored for fixed-size objects)
702 errval_t devframe_type(struct capref *dest, struct capref src, uint8_t bits)
704 errval_t err = slot_alloc(dest);
705 if (err_is_fail(err)) {
706 return err_push(err, LIB_ERR_SLOT_ALLOC);
709 return cap_retype(*dest, src, ObjType_DevFrame, bits);
713 * \brief Create an ID cap in a newly allocated slot.
715 * \param dest Pointer to capref struct, filld-in with location of new cap.
717 * The caller is responsible for revoking the cap after using it.
719 errval_t idcap_alloc(struct capref *dest)
721 errval_t err = slot_alloc(dest);
723 if (err_is_fail(err)) {
724 return err_push(err, LIB_ERR_SLOT_ALLOC);
727 return idcap_create(*dest);
731 * \brief Create an ID cap in the specified slot.
733 * \param dest Capref, where ID cap should be created.
735 * The caller is responsible for revoking the cap after using it.
737 errval_t idcap_create(struct capref dest)
739 return cap_create(dest, ObjType_ID, 0);
743 * \brief Builds a #cnoderef struct from a #capref struct using cap
746 * \param cnoder Pointer to a cnoderef struct, fill-in by function.
747 * \param capr Capref to a CNode capability.
749 errval_t cnode_build_cnoderef(struct cnoderef *cnoder, struct capref capr)
751 struct capability cap;
752 errval_t err = debug_cap_identify(capr, &cap);
753 if (err_is_fail(err)) {
757 if (cap.type != ObjType_CNode) {
758 return LIB_ERR_NOT_CNODE;
761 cnoder->address = get_cap_addr(capr);
762 cnoder->address_bits = get_cap_valid_bits(capr);
763 cnoder->size_bits = cap.u.cnode.bits;
764 cnoder->guard_size = cap.u.cnode.guard_size;