1/**
2 * \file
3 * \brief Kernel capability management.
4 */
5
6/*
7 * Copyright (c) 2007-2009,2011, 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#ifndef CAPABILITIES_H
17#define CAPABILITIES_H
18
19#include <barrelfish_kpi/capabilities.h>
20#include <mdb/mdb.h>
21#include <offsets.h>
22#include <cap_predicates.h>
23#include <paging_generic.h>
24
25struct cte;
26
27#define DELETE_LIST_SIZE (sizeof(uint64_t))
28struct delete_list {
29    struct cte *next;
30    // make sure delete list is always the same size!
31    char padding[DELETE_LIST_SIZE - sizeof(struct cte*)];
32};
33
34#ifndef ROUND_UP
35#define ROUND_UP(n, size)           ((((n) + (size) - 1)) & (~((size) - 1)))
36#endif
37
38STATIC_ASSERT((ROUND_UP(sizeof(struct capability), 8)
39               + ROUND_UP(sizeof(struct mdbnode), 8)
40               + sizeof(struct delete_list))
41               <= (1UL << OBJBITS_CTE),
42              "cap+mdbnode fit in cte");
43
44STATIC_ASSERT(sizeof(enum objtype) == 1, "short enums work");
45
46/**
47 * \brief A CTE (Capability Table Entry).
48 *
49 * A CTE is an entry in a CNode, which in turn is an entry in CSpace, the
50 * capability space. CSpace is a guarded tree structure. Refer to the seL4
51 * reference manual for further information about how CSpace is implemented.
52 */
53struct cte {
54    struct capability   cap;            ///< The capability
55    char padding0[ROUND_UP(sizeof(struct capability), 8)- sizeof(struct capability)];
56    struct mdbnode      mdbnode;        ///< MDB "root" node for the cap
57    char padding1[ROUND_UP(sizeof(struct mdbnode), 8) - sizeof(struct mdbnode)];
58    struct delete_list  delete_node;    ///< State for in-progress delete cascades
59
60    /// Padding to fill the struct out to the size required by OBJBITS_CTE
61    char padding[(1UL << OBJBITS_CTE)
62                 - sizeof(struct delete_list)
63                 - ROUND_UP(sizeof(struct capability), 8)
64                 - ROUND_UP(sizeof(struct mdbnode), 8)];
65};
66
67STATIC_ASSERT_SIZEOF(struct cte, (1UL << OBJBITS_CTE));
68
69static inline struct cte *caps_locate_slot(lpaddr_t cnode, cslot_t offset)
70{
71    return (struct cte *)(local_phys_to_mem(cnode) +
72                          (1UL << OBJBITS_CTE) * offset);
73}
74
75static inline struct cte *cte_for_cap(struct capability *cap)
76{
77    return (struct cte *) ((char *)cap - offsetof(struct cte, cap));
78}
79
80/*
81 * \brief Get a mapping's offset into a frame.
82 *
83 * Return the offset at which the mapping cap maps the backing frame.
84 */
85/*
86static inline size_t caps_get_mapping_offset(struct capability *cap) {
87
88    // This function should be emitted by hamlet or somesuch.
89    STATIC_ASSERT(50 == ObjType_Num, "Check Mapping definitions");
90
91    switch (cap->type) {
92    case ObjType_VNode_AARCH64_l3_Mapping:
93    case ObjType_VNode_AARCH64_l2_Mapping:
94    case ObjType_VNode_AARCH64_l1_Mapping:
95    case ObjType_VNode_AARCH64_l0_Mapping:
96    case ObjType_VNode_ARM_l2_Mapping:
97    case ObjType_VNode_ARM_l1_Mapping:
98    case ObjType_VNode_x86_32_ptable_Mapping:
99    case ObjType_VNode_x86_32_pdir_Mapping:
100    case ObjType_VNode_x86_32_pdpt_Mapping:
101    case ObjType_VNode_x86_64_ptable_Mapping:
102    case ObjType_VNode_x86_64_pdir_Mapping:
103    case ObjType_VNode_x86_64_pdpt_Mapping:
104    case ObjType_VNode_x86_64_pml4_Mapping:
105    case ObjType_DevFrame_Mapping:
106    case ObjType_Frame_Mapping:
107        return cap->u.frame_mapping.offset << 10;
108    default:
109        return 0;
110    }
111}
112*/
113
114int sprint_cap(char *buf, size_t len, struct capability *cap);
115void caps_trace(const char *func, int line, struct cte *cte, const char *msg);
116errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bits,
117                         size_t objbits, coreid_t owner, struct cte *caps);
118errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr,
119                                   int cnode_vbits, cslot_t dest_slot,
120                                   coreid_t owner, struct capability *src);
121errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot,
122                            struct cte *src_cte, bool mint, uintptr_t param1,
123                            uintptr_t param2);
124errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
125                          uintptr_t param1, uintptr_t param2);
126errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
127                            struct cte *src_cte, uintptr_t flags,
128                            uintptr_t offset, uintptr_t pte_count,
129                            struct cte *mapping_cte);
130size_t do_unmap(lvaddr_t pt, cslot_t slot, size_t num_pages);
131errval_t page_mappings_unmap(struct capability *pgtable, struct cte *mapping);
132errval_t page_mappings_modify_flags(struct capability *mapping, size_t offset,
133                                    size_t pages, size_t mflags,
134                                    genvaddr_t va_hint);
135errval_t ptable_modify_flags(struct capability *leaf_pt, size_t offset,
136                                    size_t pages, size_t mflags);
137errval_t paging_modify_flags(struct capability *frame, uintptr_t offset,
138                             uintptr_t pages, uintptr_t kpi_paging_flags);
139void paging_dump_tables(struct dcb *dispatcher);
140
141errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count,
142                     struct capability *dest_cnode, cslot_t dest_slot,
143                     struct cte *src_cte, gensize_t offset,
144                     bool from_monitor);
145errval_t is_retypeable(struct cte *src_cte,
146                       enum objtype src_type,
147                       enum objtype dest_type,
148                       bool from_monitor);
149
150errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr,
151                         uint8_t level, struct capability **ret, CapRights rights);
152errval_t caps_lookup_slot(struct capability *rootcn, capaddr_t cptr,
153                          uint8_t level, struct cte **ret, CapRights rights);
154
155/*
156 * Delete and revoke
157 */
158
159errval_t caps_delete_last(struct cte *cte, struct cte *ret_ram_cap);
160errval_t caps_delete_foreigns(struct cte *cte);
161errval_t caps_mark_revoke(struct capability *base, struct cte *revoked);
162errval_t caps_delete_step(struct cte *ret_next);
163errval_t caps_clear_step(struct cte *ret_ram_cap);
164errval_t caps_delete(struct cte *cte);
165errval_t caps_revoke(struct cte *cte);
166
167/*
168 * Cap tracing
169 */
170#ifdef TRACE_PMEM_CAPS
171STATIC_ASSERT(50 == ObjType_Num, "knowledge of all cap types");
172STATIC_ASSERT(64 >= ObjType_Num, "cap types fit in uint64_t bitfield");
173#define MAPPING_TYPES \
174    ((1ull<<ObjType_VNode_x86_64_pml4_Mapping) | \
175     (1ull<<ObjType_VNode_x86_64_pdpt_Mapping) | \
176     (1ull<<ObjType_VNode_x86_64_pdir_Mapping) | \
177     (1ull<<ObjType_VNode_x86_64_ptable_Mapping) | \
178     (1ull<<ObjType_VNode_x86_32_pdpt_Mapping) | \
179     (1ull<<ObjType_VNode_x86_32_pdir_Mapping) | \
180     (1ull<<ObjType_VNode_x86_32_ptable_Mapping) | \
181     (1ull<<ObjType_VNode_ARM_l1_Mapping) | \
182     (1ull<<ObjType_VNode_ARM_l2_Mapping) | \
183     (1ull<<ObjType_VNode_AARCH64_l0_Mapping) | \
184     (1ull<<ObjType_VNode_AARCH64_l1_Mapping) | \
185     (1ull<<ObjType_VNode_AARCH64_l2_Mapping) | \
186     (1ull<<ObjType_VNode_AARCH64_l3_Mapping) | \
187     (1ull<<ObjType_Frame_Mapping) | \
188     (1ull<<ObjType_DevFrame_Mapping))
189
190#define ALL_PMEM_TYPES \
191    ((1ull<<ObjType_RAM) | \
192     (1ull<<ObjType_Frame) | \
193     (1ull<<ObjType_DevFrame) | \
194     (1ull<<ObjType_L1CNode) | \
195     (1ull<<ObjType_L2CNode) | \
196     (1ull<<ObjType_FCNode) | \
197     (1ull<<ObjType_VNode_x86_64_pml4) | \
198     (1ull<<ObjType_VNode_x86_64_pdpt) | \
199     (1ull<<ObjType_VNode_x86_64_pdir) | \
200     (1ull<<ObjType_VNode_x86_64_ptable) | \
201     (1ull<<ObjType_VNode_x86_32_pdpt) | \
202     (1ull<<ObjType_VNode_x86_32_pdir) | \
203     (1ull<<ObjType_VNode_x86_32_ptable) | \
204     (1ull<<ObjType_VNode_ARM_l1) | \
205     (1ull<<ObjType_VNode_ARM_l2) | \
206     (1ull<<ObjType_VNode_AARCH64_l0) | \
207     (1ull<<ObjType_VNode_AARCH64_l1) | \
208     (1ull<<ObjType_VNode_AARCH64_l2) | \
209     (1ull<<ObjType_VNode_AARCH64_l3) | \
210     (1ull<<ObjType_PhysAddr) | \
211     (1ull<<ObjType_KernelControlBlock) | \
212     MAPPING_TYPES)
213
214#define TRACE_TYPES_ENABLED_INITIAL 0x0
215#define TRACE_PMEM_BEGIN_INITIAL    0x0
216#define TRACE_PMEM_SIZE_INITIAL     (~(uint32_t)0)
217
218extern uint64_t trace_types_enabled;
219extern genpaddr_t TRACE_PMEM_BEGIN;
220extern gensize_t TRACE_PMEM_SIZE;
221void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size);
222static inline bool caps_should_trace(struct capability *cap)
223{
224    if (!(trace_types_enabled & (1ull<<cap->type))) {
225        return false;
226    }
227    if (!(ALL_PMEM_TYPES & (1ull<<cap->type))) {
228        return true;
229    }
230    genpaddr_t begin = get_address(cap);
231    gensize_t size = get_size(cap);
232    genpaddr_t end = begin+size;
233    return (begin < TRACE_PMEM_BEGIN && end > TRACE_PMEM_BEGIN)
234        || (begin >= TRACE_PMEM_BEGIN && begin < (TRACE_PMEM_BEGIN+TRACE_PMEM_SIZE));
235}
236#define TRACE_CAP_MSGF(trace_cte, msgfmt, ...) do { \
237    struct cte *__tmp_cte = (trace_cte); \
238    if (__tmp_cte && caps_should_trace(&__tmp_cte->cap)) { \
239        char __tmp_msg_buf[256]; \
240        snprintf(__tmp_msg_buf, 256, msgfmt, __VA_ARGS__); \
241        caps_trace(__func__, __LINE__, __tmp_cte, (__tmp_msg_buf)); \
242    } \
243} while (0)
244#define TRACE_CAP_MSG(msg, trace_cte) do { \
245    struct cte *__tmp_cte = (trace_cte); \
246    if (__tmp_cte && caps_should_trace(&__tmp_cte->cap)) { \
247        caps_trace(__func__, __LINE__, __tmp_cte, (msg)); \
248    } \
249} while (0)
250#define TRACE_CAP(trace_cte) TRACE_CAP_MSG(NULL, trace_cte)
251#else
252#define TRACE_CAP_MSGF(trace_cte, msgfmt, ...) ((void)0)
253#define TRACE_CAP_MSG(msg, trace_cte) ((void)0)
254#define TRACE_CAP(trace_cte) ((void)0)
255#endif
256
257#endif
258