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, Universitaetstrasse 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(58 == 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_VNode_x86_64_ept_ptable_Mapping: 106 case ObjType_VNode_x86_64_ept_pdir_Mapping: 107 case ObjType_VNode_x86_64_ept_pdpt_Mapping: 108 case ObjType_VNode_x86_64_ept_pml4_Mapping: 109 case ObjType_DevFrame_Mapping: 110 case ObjType_Frame_Mapping: 111 return cap->u.frame_mapping.offset << 10; 112 default: 113 return 0; 114 } 115} 116*/ 117 118int sprint_cap(char *buf, size_t len, struct capability *cap); 119void caps_trace(const char *func, int line, struct cte *cte, const char *msg); 120errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bits, 121 size_t objbits, coreid_t owner, struct cte *caps); 122errval_t caps_create_from_existing(struct capability *root, capaddr_t cnode_cptr, 123 int cnode_vbits, cslot_t dest_slot, 124 coreid_t owner, struct capability *src); 125errval_t caps_copy_to_cnode(struct cte *dest_cnode_cte, cslot_t dest_slot, 126 struct cte *src_cte, bool mint, uintptr_t param1, 127 uintptr_t param2); 128errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint, 129 uintptr_t param1, uintptr_t param2); 130errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot, 131 struct cte *src_cte, uintptr_t flags, 132 uintptr_t offset, uintptr_t pte_count, 133 struct cte *mapping_cte); 134errval_t paging_copy_remap(struct cte *dest_vnode_cte, cslot_t dest_slot, 135 struct cte *src_cte, uintptr_t flags, 136 uintptr_t offset, uintptr_t pte_count, 137 struct cte *mapping_cte); 138size_t do_unmap(lvaddr_t pt, cslot_t slot, size_t num_pages); 139errval_t page_mappings_unmap(struct capability *pgtable, struct cte *mapping); 140errval_t page_mappings_modify_flags(struct capability *mapping, size_t offset, 141 size_t pages, size_t mflags, 142 genvaddr_t va_hint); 143errval_t ptable_modify_flags(struct capability *leaf_pt, size_t offset, 144 size_t pages, size_t mflags); 145errval_t paging_modify_flags(struct capability *frame, uintptr_t offset, 146 uintptr_t pages, uintptr_t kpi_paging_flags); 147void paging_dump_tables_around(struct dcb *dispatcher, lvaddr_t vaddr); 148void paging_dump_tables(struct dcb *dispatcher); 149 150errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count, 151 struct capability *dest_cnode, cslot_t dest_slot, 152 struct cte *src_cte, gensize_t offset, 153 bool from_monitor); 154errval_t is_retypeable(struct cte *src_cte, 155 enum objtype src_type, 156 enum objtype dest_type, 157 bool from_monitor); 158 159errval_t caps_lookup_cap(struct capability *cnode_cap, capaddr_t cptr, 160 uint8_t level, struct capability **ret, CapRights rights); 161errval_t caps_lookup_slot(struct capability *rootcn, capaddr_t cptr, 162 uint8_t level, struct cte **ret, CapRights rights); 163 164/* 165 * Delete and revoke 166 */ 167 168errval_t caps_delete_last(struct cte *cte, struct cte *ret_ram_cap); 169errval_t caps_delete_foreigns(struct cte *cte); 170errval_t caps_mark_revoke(struct capability *base, struct cte *revoked); 171errval_t caps_delete_step(struct cte *ret_next); 172errval_t caps_clear_step(struct cte *ret_ram_cap); 173errval_t caps_delete(struct cte *cte); 174errval_t caps_revoke(struct cte *cte); 175 176/* 177 * Reclaim "dropped" caps 178 */ 179errval_t caps_reclaim_ram(struct cte *ret_ram_cap); 180 181/* 182 * redact struct capability for passing to user code 183 */ 184errval_t redact_capability(struct capability *cap); 185 186/* 187 * Cap tracing 188 */ 189#ifdef TRACE_PMEM_CAPS 190// XXX: this is not gonna work anymore! -SG, 2018-10-22. 191STATIC_ASSERT(68 == ObjType_Num, "knowledge of all cap types"); 192STATIC_ASSERT(64 >= ObjType_Num, "cap types fit in uint64_t bitfield"); 193#define MAPPING_TYPES \ 194 ((1ull<<ObjType_VNode_x86_64_pml4_Mapping) | \ 195 (1ull<<ObjType_VNode_x86_64_pdpt_Mapping) | \ 196 (1ull<<ObjType_VNode_x86_64_pdir_Mapping) | \ 197 (1ull<<ObjType_VNode_x86_64_ptable_Mapping) | \ 198 (1ul<<ObjType_VNode_x86_64_ept_pml4_Mapping) | \ 199 (1ul<<ObjType_VNode_x86_64_ept_pdpt_Mapping) | \ 200 (1ul<<ObjType_VNode_x86_64_ept_pdir_Mapping) | \ 201 (1ul<<ObjType_VNode_x86_64_ept_ptable_Mapping) | \ 202 (1ull<<ObjType_VNode_x86_32_pdpt_Mapping) | \ 203 (1ull<<ObjType_VNode_x86_32_pdir_Mapping) | \ 204 (1ull<<ObjType_VNode_x86_32_ptable_Mapping) | \ 205 (1ull<<ObjType_VNode_ARM_l1_Mapping) | \ 206 (1ull<<ObjType_VNode_ARM_l2_Mapping) | \ 207 (1ull<<ObjType_VNode_AARCH64_l0_Mapping) | \ 208 (1ull<<ObjType_VNode_AARCH64_l1_Mapping) | \ 209 (1ull<<ObjType_VNode_AARCH64_l2_Mapping) | \ 210 (1ull<<ObjType_VNode_AARCH64_l3_Mapping) | \ 211 (1ull<<ObjType_Frame_Mapping) | \ 212 (1ull<<ObjType_DevFrame_Mapping)) 213 214#define ALL_PMEM_TYPES \ 215 ((1ull<<ObjType_RAM) | \ 216 (1ull<<ObjType_Frame) | \ 217 (1ull<<ObjType_DevFrame) | \ 218 (1ull<<ObjType_L1CNode) | \ 219 (1ull<<ObjType_L2CNode) | \ 220 (1ull<<ObjType_FCNode) | \ 221 (1ull<<ObjType_VNode_x86_64_pml4) | \ 222 (1ull<<ObjType_VNode_x86_64_pdpt) | \ 223 (1ull<<ObjType_VNode_x86_64_pdir) | \ 224 (1ull<<ObjType_VNode_x86_64_ptable) | \ 225 (1ul<<ObjType_VNode_x86_64_ept_pml4) | \ 226 (1ul<<ObjType_VNode_x86_64_ept_pdpt) | \ 227 (1ul<<ObjType_VNode_x86_64_ept_pdir) | \ 228 (1ul<<ObjType_VNode_x86_64_ept_ptable) | \ 229 (1ull<<ObjType_VNode_x86_32_pdpt) | \ 230 (1ull<<ObjType_VNode_x86_32_pdir) | \ 231 (1ull<<ObjType_VNode_x86_32_ptable) | \ 232 (1ull<<ObjType_VNode_ARM_l1) | \ 233 (1ull<<ObjType_VNode_ARM_l2) | \ 234 (1ull<<ObjType_VNode_AARCH64_l0) | \ 235 (1ull<<ObjType_VNode_AARCH64_l1) | \ 236 (1ull<<ObjType_VNode_AARCH64_l2) | \ 237 (1ull<<ObjType_VNode_AARCH64_l3) | \ 238 (1ull<<ObjType_PhysAddr) | \ 239 (1ull<<ObjType_KernelControlBlock) | \ 240 MAPPING_TYPES) 241 242#define TRACE_TYPES_ENABLED_INITIAL 0x0 243#define TRACE_PMEM_BEGIN_INITIAL 0x0 244#define TRACE_PMEM_SIZE_INITIAL (~(uint32_t)0) 245 246extern uint64_t trace_types_enabled; 247extern genpaddr_t TRACE_PMEM_BEGIN; 248extern gensize_t TRACE_PMEM_SIZE; 249void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size); 250static inline bool caps_should_trace(struct capability *cap) 251{ 252 if (!(trace_types_enabled & (1ull<<cap->type))) { 253 return false; 254 } 255 if (!(ALL_PMEM_TYPES & (1ull<<cap->type))) { 256 return true; 257 } 258 genpaddr_t begin = get_address(cap); 259 gensize_t size = get_size(cap); 260 genpaddr_t end = begin+size; 261 return (begin < TRACE_PMEM_BEGIN && end > TRACE_PMEM_BEGIN) 262 || (begin >= TRACE_PMEM_BEGIN && begin < (TRACE_PMEM_BEGIN+TRACE_PMEM_SIZE)); 263} 264#define TRACE_CAP_MSGF(trace_cte, msgfmt, ...) do { \ 265 struct cte *__tmp_cte = (trace_cte); \ 266 if (__tmp_cte && caps_should_trace(&__tmp_cte->cap)) { \ 267 char __tmp_msg_buf[256]; \ 268 snprintf(__tmp_msg_buf, 256, msgfmt, __VA_ARGS__); \ 269 caps_trace(__func__, __LINE__, __tmp_cte, (__tmp_msg_buf)); \ 270 } \ 271} while (0) 272#define TRACE_CAP_MSG(msg, trace_cte) do { \ 273 struct cte *__tmp_cte = (trace_cte); \ 274 if (__tmp_cte && caps_should_trace(&__tmp_cte->cap)) { \ 275 caps_trace(__func__, __LINE__, __tmp_cte, (msg)); \ 276 } \ 277} while (0) 278#define TRACE_CAP(trace_cte) TRACE_CAP_MSG(NULL, trace_cte) 279#else 280#define TRACE_CAP_MSGF(trace_cte, msgfmt, ...) ((void)0) 281#define TRACE_CAP_MSG(msg, trace_cte) ((void)0) 282#define TRACE_CAP(trace_cte) ((void)0) 283#endif 284 285#endif 286