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_super = {
53 .address = CPTR_SUPERCN_BASE,
54 .address_bits = DEFAULT_CNODE_BITS,
55 .size_bits = DEFAULT_CNODE_BITS,
60 struct cnoderef cnode_page = {
61 .address = ROOTCN_SLOT_PAGECN << DEFAULT_CN_ADDR_BITS,
62 .address_bits = DEFAULT_CNODE_BITS,
63 .size_bits = PAGE_CNODE_BITS,
68 struct cnoderef cnode_module = {
69 .address = CPTR_MODULECN_BASE,
70 .address_bits = DEFAULT_CNODE_BITS,
71 .size_bits = MODULECN_SIZE_BITS,
75 /// Capability to Root CNode
76 struct capref cap_root = {
77 .cnode = TASK_CNODE_INIT,
78 .slot = TASKCN_SLOT_ROOTCN
81 /// Capability for IRQ table
82 struct capref cap_irq = {
83 .cnode = TASK_CNODE_INIT,
84 .slot = TASKCN_SLOT_IRQ
87 /// Capability for legacy IO
88 struct capref cap_io = {
89 .cnode = TASK_CNODE_INIT,
90 .slot = TASKCN_SLOT_IO
93 /// Capability for endpoint to self
94 struct capref cap_selfep = {
95 .cnode = TASK_CNODE_INIT,
96 .slot = TASKCN_SLOT_SELFEP
99 /// Capability for dispatcher
100 struct capref cap_dispatcher = {
101 .cnode = TASK_CNODE_INIT,
102 .slot = TASKCN_SLOT_DISPATCHER
105 /// Capability for dispatcher
106 struct capref cap_dispframe = {
107 .cnode = TASK_CNODE_INIT,
108 .slot = TASKCN_SLOT_DISPFRAME
111 #define ROOT_CNODE_INIT { \
112 .address = CPTR_ROOTCN, \
113 .address_bits = CPTR_BITS, \
114 .size_bits = DEFAULT_CNODE_BITS, \
117 /// Capability for monitor endpoint
118 struct capref cap_monitorep = {
119 .cnode = ROOT_CNODE_INIT,
120 .slot = ROOTCN_SLOT_MONITOREP
123 /// Capability for kernel (only in monitor)
124 struct capref cap_kernel = {
125 .cnode = TASK_CNODE_INIT,
126 .slot = TASKCN_SLOT_KERNELCAP
130 struct capref cap_perfmon = {
131 .cnode = TASK_CNODE_INIT,
132 .slot = TASKCN_SLOT_PERF_MON
135 /// Capability for endpoint to init (only in monitor/mem_serv)
136 struct capref cap_initep = {
137 .cnode = TASK_CNODE_INIT,
138 .slot = TASKCN_SLOT_INITEP
142 struct capref cap_sessionid = {
143 .cnode = TASK_CNODE_INIT,
144 .slot = TASKCN_SLOT_SESSIONID
147 static inline bool backoff(int count)
149 // very crude exponential backoff based upon core id
150 int yieldcnt = 2^count * disp_get_core_id();
151 for (int i=0; i<yieldcnt; i++) {
158 * \brief Retype a capability into one or more new capabilities, going through
159 * the monitor to ensure consistancy with other cores. Only necessary for
160 * caps that have been sent remotely.
162 static errval_t cap_retype_remote(capaddr_t src, enum objtype new_type,
163 uint8_t size_bits, capaddr_t to, capaddr_t slot,
166 struct monitor_blocking_rpc_client *mrc = get_monitor_blocking_rpc_client();
167 errval_t err, remote_cap_err;
170 err = mrc->vtbl.remote_cap_retype(mrc, cap_root, src,
173 dcn_vbits, &remote_cap_err);
174 if (err_is_fail(err)){
175 DEBUG_ERR(err, "remote cap retype\n");
177 } while (remote_cap_err == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
179 return remote_cap_err;
185 * \brief Delete the given capability, going through the monitor to ensure
186 * consistancy with other cores. Only necessary for caps that have been sent
189 * \param cap Capability to be deleted
191 * Deletes (but does not revoke) the given capability, allowing the CNode slot
194 static errval_t cap_delete_remote(capaddr_t src, uint8_t vbits)
196 struct monitor_blocking_rpc_client *mrc = get_monitor_blocking_rpc_client();
197 errval_t err, remote_cap_err;
200 err = mrc->vtbl.remote_cap_delete(mrc, cap_root, src, vbits,
202 if (err_is_fail(err)){
203 DEBUG_ERR(err, "remote cap delete\n");
205 } while (remote_cap_err == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
207 return remote_cap_err;
211 * \brief Revoke (delete all copies and descendants of) the given capability,
212 * going through the monitor to ensure consistancy with other cores. Only
213 * necessary for caps that have been sent remotely.
215 * \param cap Capability to be revoked
217 * Deletes all copies and descendants of the given capability, but not the
218 * capability itself. If this succeeds, the capability is guaranteed to be
219 * the only copy in the system.
221 static errval_t cap_revoke_remote(capaddr_t src, uint8_t vbits)
223 struct monitor_blocking_rpc_client *mrc = get_monitor_blocking_rpc_client();
224 errval_t err, remote_cap_err;
227 err = mrc->vtbl.remote_cap_revoke(mrc, cap_root, src, vbits,
229 if (err_is_fail(err)){
230 DEBUG_ERR(err, "remote cap delete\n");
232 } while (remote_cap_err == MON_ERR_REMOTE_CAP_RETRY && backoff(++count));
234 return remote_cap_err;
238 * \brief Retype a capability into one or more new capabilities
240 * \param dest_start Location of first destination slot, which must be empty
241 * \param src Source capability to retype
242 * \param new_type Kernel object type to retype to.
243 * \param size_bits Size of created objects as a power of two
244 * (ignored for fixed-size objects)
246 * Retypes the given source capability into a number of new capabilities, which
247 * may be of the same or of different type. The new capabilities are created
248 * in the slots starting from dest_start, which must all be empty and lie in the
249 * same CNode. The number of objects created is determined by the size of the
250 * source object divided by the size of the destination objects.
252 errval_t cap_retype(struct capref dest_start, struct capref src,
253 enum objtype new_type, uint8_t size_bits)
256 // Number of valid bits in destination CNode address
257 uint8_t dcn_vbits = get_cnode_valid_bits(dest_start);
258 // Address of the cap to the destination CNode
259 capaddr_t dcn_addr = get_cnode_addr(dest_start);
260 // Address of source capability
261 capaddr_t scp_addr = get_cap_addr(src);
263 err = invoke_cnode_retype(cap_root, scp_addr, new_type, size_bits,
264 dcn_addr, dest_start.slot, dcn_vbits);
266 if (err == SYS_ERR_RETRY_THROUGH_MONITOR) {
267 return cap_retype_remote(scp_addr, new_type, size_bits,
268 dcn_addr, dest_start.slot, dcn_vbits);
276 * \brief Create a capability
278 * \param dest Location where to create the cap, which must be empty.
279 * \param type Kernel object type to create.
280 * \param size_bits Size of the created capability as a power of two.
281 * (ignored for fixed-size objects)
283 * Only certain types of capabilities can be created this way. If invoked on
284 * a capability type, that is not creatable at runtime the error
285 * SYS_ERR_TYPE_NOT_CREATABLE is returned. Most capabilities have to be retyped
286 * from other capabilities with cap_retype().
288 errval_t cap_create(struct capref dest, enum objtype type, uint8_t size_bits)
292 // Number of valid bits in the destination CNode address
293 uint8_t dest_vbits = get_cnode_valid_bits(dest);
294 // Address of the cap to the destination CNode
295 capaddr_t dest_cnode_cptr = get_cnode_addr(dest);
297 err = invoke_cnode_create(cap_root, type, size_bits, dest_cnode_cptr,
298 dest.slot, dest_vbits);
304 * \brief Delete the given capability
306 * \param cap Capability to be deleted
308 * Deletes (but does not revoke) the given capability, allowing the CNode slot
311 errval_t cap_delete(struct capref cap)
314 uint8_t vbits = get_cap_valid_bits(cap);
315 capaddr_t caddr = get_cap_addr(cap) >> (CPTR_BITS - vbits);
317 err = invoke_cnode_delete(cap_root, caddr, vbits);
319 if (err == SYS_ERR_RETRY_THROUGH_MONITOR) {
320 return cap_delete_remote(caddr, vbits);
327 * \brief Revoke (delete all copies and descendants of) the given capability
329 * \param cap Capability to be revoked
331 * Deletes all copies and descendants of the given capability, but not the
332 * capability itself. If this succeeds, the capability is guaranteed to be
333 * the only copy in the system.
335 errval_t cap_revoke(struct capref cap)
338 uint8_t vbits = get_cap_valid_bits(cap);
339 capaddr_t caddr = get_cap_addr(cap) >> (CPTR_BITS - vbits);
341 err = invoke_cnode_revoke(cap_root, caddr, vbits);
343 if (err == SYS_ERR_RETRY_THROUGH_MONITOR) {
344 return cap_revoke_remote(caddr, vbits);
351 * \brief Destroy a capability, i.e. delete it and free the slot.
353 * \param cap Capability to be destroyed
355 errval_t cap_destroy(struct capref cap)
358 err = cap_delete(cap);
359 if (err_is_fail(err)) {
363 err = slot_free(cap);
364 if (err_is_fail(err)) {
365 return err_push(err, LIB_ERR_WHILE_FREEING_SLOT);
372 * \brief Create a CNode from a given RAM capability in a specific slot
374 * \param dest location in which to place newly-created CNode cap
375 * \param src location of RAM capability to be retyped to new CNode
376 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
377 * \param slot_bits number of slots in created CNode as a power of two.
378 * must match size of RAM capability.
380 * This function requires that dest refer to an existing but empty slot. It
381 * retypes the given memory to a new CNode.
383 errval_t cnode_create_from_mem(struct capref dest, struct capref src,
384 struct cnoderef *cnoderef, uint8_t slot_bits)
388 // Retype it to the destination
389 err = cap_retype(dest, src, ObjType_CNode, slot_bits);
390 if (err_is_fail(err)) {
391 return err_push(err, LIB_ERR_CAP_RETYPE);
394 // Construct the cnoderef to return
395 if (cnoderef != NULL) {
396 *cnoderef = build_cnoderef(dest, slot_bits);
403 * \brief Create a CNode from newly-allocated RAM in a newly-allocated slot
405 * \param ret_dest capref struct to be filled-in with location of CNode
406 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
407 * \param slots Minimum number of slots in created CNode
408 * \param retslots If non-NULL, filled in with the number of slots in created CNode
410 errval_t cnode_create(struct capref *ret_dest, struct cnoderef *cnoderef,
411 cslot_t slots, cslot_t *retslots)
415 // Allocate a slot for destination.
416 assert(ret_dest != NULL);
417 err = slot_alloc(ret_dest);
418 if (err_is_fail(err)) {
419 return err_push(err, LIB_ERR_SLOT_ALLOC);
422 // Use cnode_create_raw
423 return cnode_create_raw(*ret_dest, cnoderef, slots, retslots);
427 * \brief Create a CNode from newly-allocated RAM in the given slot
429 * \param dest location in which to place CNode cap
430 * \param cnoderef cnoderef struct, filled-in if non-NULL with relevant info
431 * \param slots Minimum number of slots in created CNode
432 * \param retslots If non-NULL, filled in with the number of slots in created CNode
434 * This function requires that dest refer to an existing but empty slot. It
435 * allocates memory (using #ram_alloc), and retypes that memory to a new CNode.
436 * The intermediate ram cap is destroyed.
438 errval_t cnode_create_raw(struct capref dest, struct cnoderef *cnoderef,
439 cslot_t slots, cslot_t *retslots)
445 uint8_t bits = log2ceil(slots);
446 assert((1UL << bits) >= slots);
447 if (bits < DEFAULT_CNODE_BITS) {
448 bits = DEFAULT_CNODE_BITS;
451 if (retslots != NULL) {
452 *retslots = 1UL << bits;
455 // Allocate some memory
456 err = ram_alloc(&ram, bits + OBJBITS_CTE);
457 if (err_is_fail(err)) {
458 return err_push(err, LIB_ERR_RAM_ALLOC);
461 err = cnode_create_from_mem(dest, ram, cnoderef, bits);
462 if (err_is_fail(err)) {
463 return err_push(err, LIB_ERR_CNODE_CREATE_FROM_MEM);
466 err = cap_destroy(ram);
467 if (err_is_fail(err)) {
468 return err_push(err, LIB_ERR_CAP_DESTROY);
475 * \brief Create CNode with a given guard
477 * \param dest Location where to place the cnode
478 * \param cnoderef Filled in cnoderef struct if non-NULL
479 * \param slots Minimum number of slots in created CNode
480 * \param retslots If non-NULL, filled in with the number of slots in created CNode
481 * \param guard The guard value to set
482 * \param guard_size The length of the guard in bits
484 * This function requires that dest refer to an existing but empty slot. It
485 * allocates memory (using #ram_alloc), and retypes that memory to a new CNode
486 * with the given guard value and size. An intermediate slot is used in order to
487 * set the guard value.
489 errval_t cnode_create_with_guard(struct capref dest, struct cnoderef *cnoderef,
490 cslot_t slots, cslot_t *retslots,
491 uint64_t guard, uint8_t guard_size)
495 /* Create an intermediate cnode cap */
497 err = cnode_create(&inter, NULL, slots, retslots);
498 if (err_is_fail(err)) {
499 return err_push(err, LIB_ERR_CNODE_CREATE);
502 /* Mint it to the new destination setting the guard */
503 err = cap_mint(dest, inter, guard, guard_size);
504 if (err_is_fail(err)) {
505 return err_push(err, LIB_ERR_CAP_MINT);
508 /* Free the intermediate cnode cap and slot */
509 err = cap_delete(inter);
510 if (err_is_fail(err)) {
511 return err_push(err, LIB_ERR_WHILE_DELETING);
513 err = slot_free(inter);
514 if (err_is_fail(err)) {
515 return err_push(err, LIB_ERR_WHILE_FREEING_SLOT);
518 /* Build the cnoderef */
519 if (cnoderef != NULL) {
521 uint8_t bits = log2ceil(slots);
522 assert((1UL << bits) >= slots);
523 if (bits < DEFAULT_CNODE_BITS) {
524 bits = DEFAULT_CNODE_BITS;
526 *cnoderef = build_cnoderef(dest, bits);
527 cnoderef->guard_size = guard_size;
534 * \brief Create a VNode in newly-allocated memory
536 * \param dest location to place new VNode cap
537 * \param type VNode type to create
539 * This function requires that dest refer to an existing but empty slot.
540 * The intermidiate ram cap is destroyed.
542 errval_t vnode_create(struct capref dest, enum objtype type)
548 size_t objbits_vnode = vnode_objbits(type);
549 err = ram_alloc(&ram, objbits_vnode);
550 if (err_is_fail(err)) {
551 return err_push(err, LIB_ERR_RAM_ALLOC);
554 assert(type_is_vnode(type));
555 err = cap_retype(dest, ram, type, 0);
556 if (err_is_fail(err)) {
557 return err_push(err, LIB_ERR_CAP_RETYPE);
560 err = cap_destroy(ram);
561 if (err_is_fail(err)) {
562 return err_push(err, LIB_ERR_CAP_DESTROY);
569 * \brief Create a Frame cap referring to newly-allocated RAM in a given slot
571 * \param dest Location to place new frame cap
572 * \param bytes Minimum size of frame to create
573 * \param retbytes If non-NULL, filled in with size of created frame
575 * This function requires that dest refer to an existing but empty slot.
576 * #ram_alloc is used to allocate memory. After retyping the intermediate
577 * ram cap is destroyed.
579 * This function will returns a special error code if ram_alloc fails
580 * due to the constrains on the memory server (size of cap or region
581 * of memory). This is to facilitate retrying with different
584 errval_t frame_create(struct capref dest, size_t bytes, size_t *retbytes)
587 uint8_t bits = log2ceil(bytes);
588 assert((1UL << bits) >= bytes);
591 if (bits < BASE_PAGE_BITS) {
592 bits = BASE_PAGE_BITS;
596 err = ram_alloc(&ram, bits);
597 if (err_is_fail(err)) {
598 if (err_no(err) == MM_ERR_NOT_FOUND ||
599 err_no(err) == LIB_ERR_RAM_ALLOC_WRONG_SIZE) {
600 return err_push(err, LIB_ERR_RAM_ALLOC_MS_CONSTRAINTS);
602 return err_push(err, LIB_ERR_RAM_ALLOC);
605 err = cap_retype(dest, ram, ObjType_Frame, bits);
606 if (err_is_fail(err)) {
607 return err_push(err, LIB_ERR_CAP_RETYPE);
610 err = cap_destroy(ram);
611 if (err_is_fail(err)) {
615 if (retbytes != NULL) {
616 *retbytes = 1UL << bits;
623 * \brief Create a Dispatcher in newly-allocated memory
625 * \param dest location to place new dispatcher cap
627 * This function requires that dest refer to an existing but empty slot. It does
628 * not map in nor initialise the Dispatcher.
629 * The intermediate ram cap is destroyed.
631 errval_t dispatcher_create(struct capref dest)
636 err = ram_alloc(&ram, OBJBITS_DISPATCHER);
637 if (err_is_fail(err)) {
638 return err_push(err, LIB_ERR_RAM_ALLOC);
641 err = cap_retype(dest, ram, ObjType_Dispatcher, 0);
642 if (err_is_fail(err)) {
643 return err_push(err, LIB_ERR_CAP_RETYPE);
646 err = cap_destroy(ram);
647 if (err_is_fail(err)) {
648 return err_push(err, LIB_ERR_CAP_DESTROY);
654 * \brief Create endpoint to caller on current dispatcher.
656 * \param buflen Length of incoming LMP buffer, in words
657 * \param retcap Pointer to capref struct, filled-in with location of cap
658 * \param retep Double pointer to LMP endpoint, filled-in with allocated EP
660 errval_t endpoint_create(size_t buflen, struct capref *retcap,
661 struct lmp_endpoint **retep)
663 errval_t err = slot_alloc(retcap);
664 if (err_is_fail(err)) {
665 return err_push(err, LIB_ERR_SLOT_ALLOC);
668 return lmp_endpoint_create_in_slot(buflen, *retcap, retep);
672 * \brief Create a Frame cap referring to newly-allocated RAM in an allocated slot
674 * \param dest Pointer to capref struct, filled-in with location of new cap
675 * \param bytes Minimum size of frame to create
676 * \param retbytes If non-NULL, filled in with size of created frame
678 errval_t frame_alloc(struct capref *dest, size_t bytes, size_t *retbytes)
680 errval_t err = slot_alloc(dest);
681 if (err_is_fail(err)) {
682 return err_push(err, LIB_ERR_SLOT_ALLOC);
685 return frame_create(*dest, bytes, retbytes);
689 * \brief Create a DevFrame cap by retyping out of given source PhysAddr cap
691 * \param dest Pointer to capref struct, filled-in with location of new cap
692 * \param src Cap_info struct for the source PhysAddr cap
693 * \param size_bits Size of created objects as a power of two
694 * (ignored for fixed-size objects)
696 errval_t devframe_type(struct capref *dest, struct capref src, uint8_t bits)
698 errval_t err = slot_alloc(dest);
699 if (err_is_fail(err)) {
700 return err_push(err, LIB_ERR_SLOT_ALLOC);
703 return cap_retype(*dest, src, ObjType_DevFrame, bits);
707 * \brief Create an ID cap in a newly allocated slot.
709 * \param dest Pointer to capref struct, filld-in with location of new cap.
711 * The caller is responsible for revoking the cap after using it.
713 errval_t idcap_alloc(struct capref *dest)
715 errval_t err = slot_alloc(dest);
717 if (err_is_fail(err)) {
718 return err_push(err, LIB_ERR_SLOT_ALLOC);
721 return idcap_create(*dest);
725 * \brief Create an ID cap in the specified slot.
727 * \param dest Capref, where ID cap should be created.
729 * The caller is responsible for revoking the cap after using it.
731 errval_t idcap_create(struct capref dest)
733 return cap_create(dest, ObjType_ID, 0);
737 * \brief Builds a #cnoderef struct from a #capref struct using cap
740 * \param cnoder Pointer to a cnoderef struct, fill-in by function.
741 * \param capr Capref to a CNode capability.
743 errval_t cnode_build_cnoderef(struct cnoderef *cnoder, struct capref capr)
745 struct capability cap;
746 errval_t err = debug_cap_identify(capr, &cap);
747 if (err_is_fail(err)) {
751 if (cap.type != ObjType_CNode) {
752 return LIB_ERR_NOT_CNODE;
755 cnoder->address = get_cap_addr(capr);
756 cnoder->address_bits = get_cap_valid_bits(capr);
757 cnoder->size_bits = cap.u.cnode.bits;
758 cnoder->guard_size = cap.u.cnode.guard_size;