1/** 2 * \file 3 * \brief Architecture independent capability invocations 4 */ 5 6/* 7 * Copyright (c) 2016, ETH Zurich. 8 * All rights reserved. 9 * 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. 13 */ 14 15#ifndef INVOCATIONS_H 16#define INVOCATIONS_H 17 18#include <barrelfish_kpi/dispatcher_shared.h> 19#include <barrelfish_kpi/distcaps.h> // for distcap_state_t 20#include <barrelfish/caddr.h> 21 22#include <barrelfish/invocations_arch.h> 23 24/** 25 * \brief Create a capability. 26 * 27 * Create a new capability of type 'type' and size 'objbits'. The new cap will 28 * be placed in the slot 'dest_slot' of the CNode located at 'dest_cnode_cptr' 29 * in the address space rooted at 'root'. 30 * 31 * See also cap_create(), which wraps this. 32 * 33 * \param root Capability of the CNode to invoke. 34 * \param type Kernel object type to create. 35 * \param objsize Size of created object 36 * (ignored for fixed-size objects) 37 * \param dest_cnode_cptr Address of CNode cap, where newly created cap will be 38 * placed into. 39 * \param dest_level Depth/level of destination CNode. 40 * \param dest_slot Slot in CNode cap to place new cap. 41 * 42 * \return Error code 43 */ 44static inline errval_t invoke_cnode_create(struct capref root, 45 enum objtype type, size_t objsize, 46 capaddr_t dest_cnode_cptr, 47 enum cnode_type dest_level, 48 capaddr_t dest_slot) 49{ 50 assert(dest_cnode_cptr != CPTR_NULL); 51 return cap_invoke6(root, CNodeCmd_Create, type, objsize, dest_cnode_cptr, 52 dest_level, dest_slot).error; 53} 54 55/** 56 * \brief "Mint" a capability. 57 * 58 * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within 59 * the address space, rooted at 'root' and with 'tobits' and 'frombits' address 60 * bits of 'to' and 'from' valid, respectively. 61 * 62 * See also cap_mint(), which wraps this. 63 * 64 * \param root Capability of the source cspace root CNode to invoke 65 * \param to_cspace Destination cspace cap address relative to source cspace 66 * \param to Destination CNode address relative to destination cspace 67 * \param slot Slot in destination CNode cap to place copy into 68 * \param from Address of cap to copy. 69 * \param tolevel Level/depth of 'to'. 70 * \param fromlevel Level/depth of 'from'. 71 * \param param1 1st cap-dependent parameter. 72 * \param param2 2nd cap-dependent parameter. 73 * 74 * \return Error code 75 */ 76static inline errval_t invoke_cnode_mint(struct capref root, capaddr_t to_cspace, 77 capaddr_t to, capaddr_t slot, 78 capaddr_t from_cspace, capaddr_t from, 79 enum cnode_type tolevel, 80 enum cnode_type fromlevel, 81 uint64_t param1, uint64_t param2) 82{ 83 return cap_invoke10(root, CNodeCmd_Mint, to_cspace, to, slot, from_cspace, 84 from, tolevel, fromlevel, param1, param2).error; 85} 86 87/** 88 * \brief Copy a capability. 89 * 90 * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within 91 * the address space, rooted at 'root' and with 'tobits' and 'frombits' address 92 * bits of 'to' and 'from' valid, respectively. 93 * 94 * See also cap_copy(), which wraps this. 95 * 96 * \param root Capability of the source cspace root CNode to invoke 97 * \param to_cspace Capability address of destination root cnode relative 98 * to our cspace 99 * \param to CNode address to place copy into relative to 100 * destination cspace. 101 * \param slot Slot in CNode cap to place copy into. 102 * \param from_cspace Capability address of source root cnode relative 103 * to our cspace 104 * \param from Address of cap to copy. 105 * \param tolevel Level/depth of 'to'. 106 * \param fromlevel Level/depth of 'from'. 107 * 108 * \return Error code 109 */ 110static inline errval_t invoke_cnode_copy(struct capref root, capaddr_t to_cspace, 111 capaddr_t to, capaddr_t slot, 112 capaddr_t from_cspace, capaddr_t from, 113 enum cnode_type tolevel, 114 enum cnode_type fromlevel) 115{ 116 return cap_invoke8(root, CNodeCmd_Copy, to_cspace, to, slot, from_cspace, 117 from, tolevel, fromlevel).error; 118} 119 120/** 121 * \brief Delete a capability. 122 * 123 * Delete the capability pointed to by 'cap', with 'bits' address bits 124 * of it valid, from the address space rooted at 'root'. 125 * 126 * \param root Capability of the CNode to invoke 127 * \param cap Address of cap to delete. 128 * \param level Level/depth of 'cap'. 129 * 130 * \return Error code 131 */ 132static inline errval_t invoke_cnode_delete(struct capref root, capaddr_t cap, 133 enum cnode_type level) 134{ 135 return cap_invoke3(root, CNodeCmd_Delete, cap, level).error; 136} 137 138static inline errval_t invoke_cnode_revoke(struct capref root, capaddr_t cap, 139 enum cnode_type level) 140{ 141 return cap_invoke3(root, CNodeCmd_Revoke, cap, level).error; 142} 143 144static inline errval_t invoke_cnode_get_state(struct capref root, capaddr_t cap, 145 enum cnode_type level, distcap_state_t *ret) 146{ 147 struct sysret sysret = cap_invoke3(root, CNodeCmd_GetState, cap, level); 148 149 assert(ret != NULL); 150 if (err_is_ok(sysret.error)) { 151 *ret = sysret.value; 152 } 153 else { 154 *ret = 0; 155 } 156 return sysret.error; 157} 158 159 160/** 161 * \brief Get the size of a L1 CNode in bytes. 162 * 163 * \param root Size of this L1 CNode will be returned 164 * \param ret Result will be stored here in bytes. 165 * 166 * \return Error code 167 */ 168static inline errval_t invoke_cnode_get_size(struct capref root, size_t * ret) 169{ 170 struct sysret sys_ret = cap_invoke1(root, CNodeCmd_GetSize); 171 if(err_is_ok(sys_ret.error)){ 172 *ret = sys_ret.value; 173 } else { 174 *ret = 0; 175 } 176 177 return sys_ret.error; 178} 179 180static inline errval_t invoke_cnode_resize(struct capref root, capaddr_t new_cptr, 181 capaddr_t retcn_ptr, cslot_t retslot) 182{ 183 return cap_invoke4(root, CNodeCmd_Resize, new_cptr, retcn_ptr, retslot).error; 184} 185 186static inline errval_t invoke_vnode_unmap(struct capref cap, 187 capaddr_t mapping_addr, 188 enum cnode_type level) 189{ 190 return cap_invoke3(cap, VNodeCmd_Unmap, mapping_addr, level).error; 191} 192 193/** 194 * \brief Return the physical address and size of a frame capability 195 * 196 * \param frame CSpace address of frame capability 197 * \param ret frame_identity struct filled in with relevant data 198 * 199 * \return Error code 200 */ 201static inline errval_t invoke_frame_identify(struct capref frame, 202 struct frame_identity *ret) 203{ 204 assert(ret != NULL); 205 assert(get_croot_addr(frame) == CPTR_ROOTCN); 206 207 struct sysret sysret = cap_invoke2(frame, FrameCmd_Identify, (uintptr_t)ret); 208 209 if (err_is_ok(sysret.error)) { 210 return sysret.error; 211 } 212 213 ret->base = 0; 214 ret->bytes = 0; 215 return sysret.error; 216} 217 218static inline errval_t invoke_vnode_identify(struct capref vnode, 219 struct vnode_identity *ret) 220{ 221 assert(get_croot_addr(vnode) == CPTR_ROOTCN); 222 struct sysret sysret = cap_invoke1(vnode, VNodeCmd_Identify); 223 224 assert(ret != NULL); 225 if (err_is_ok(sysret.error)) { 226 ret->base = sysret.value & (~BASE_PAGE_MASK); 227 ret->type = sysret.value & BASE_PAGE_MASK; 228 return sysret.error; 229 } 230 231 ret->base = 0; 232 ret->type = 0; 233 return sysret.error; 234} 235 236/** 237 * \brief Modify mapping flags on parts of a mapping 238 * 239 * \param mapping CSpace address of mapping capability 240 * \param off Offset (in #pages) of the first page to get new set of flags 241 * from the first page in the mapping identified by `frame` 242 * \param pages Number of pages that should get new set of flags 243 * \param flags New set of flags 244 * \param va_hint Hint for selective TLB flushing 245 * 246 * \return Error code 247 */ 248static inline errval_t invoke_mapping_modify_flags(struct capref mapping, 249 size_t offset, 250 size_t pages, 251 size_t flags, 252 genvaddr_t va_hint) 253{ 254 return cap_invoke5(mapping, MappingCmd_Modify, offset, 255 pages, flags, va_hint).error; 256} 257 258/** 259 * \brief Setup a dispatcher, possibly making it runnable 260 * 261 * \param dispatcher Address of dispatcher capability relative to own 262 * cspace 263 * \param domdispatcher Address of existing dispatcher for domain ID relative 264 * to own cspace 265 * \param cspace Root of CSpace for new dispatcher relative to own 266 * cspace 267 * \param vspace Root of VSpace for new dispatcher relative to cspace 268 * for new dispatcher. 269 * \param dispframe Frame capability for dispatcher structure relative to 270 * cspace for new dispatcher. 271 * \param run Make runnable if true 272 * 273 * Need to either supply caprefs for all or none of cspace, vspace, dispframe 274 * and domdispatcher. 275 * 276 * \return Error code 277 */ 278static inline errval_t 279invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher, 280 struct capref cspace, struct capref vspace, 281 struct capref dispframe, bool run) 282{ 283 assert(get_croot_addr(dispatcher) == CPTR_ROOTCN); 284 assert(capref_is_null(cspace) || get_croot_addr(cspace) == CPTR_ROOTCN); 285 assert(capref_is_null(domdispatcher) || get_croot_addr(domdispatcher) == CPTR_ROOTCN); 286 assert(capref_is_null(vspace) || get_croot_addr(vspace) == get_cap_addr(cspace)); 287 assert(capref_is_null(dispframe) || get_croot_addr(dispframe) == get_cap_addr(cspace)); 288 289 capaddr_t root_caddr = get_cap_addr(cspace); 290 uint8_t root_level = get_cap_level(cspace); 291 capaddr_t vtree_caddr = get_cap_addr(vspace); 292 capaddr_t disp_caddr = get_cap_addr(dispframe); 293 capaddr_t dd_caddr = get_cap_addr(domdispatcher); 294 295 return cap_invoke7(dispatcher, DispatcherCmd_Setup, root_caddr, 296 root_level, vtree_caddr, disp_caddr, run, 297 dd_caddr).error; 298} 299 300static inline errval_t 301invoke_dispatcher_properties(struct capref dispatcher, 302 enum task_type type, unsigned long deadline, 303 unsigned long wcet, unsigned long period, 304 unsigned long release, unsigned short weight) 305{ 306 return cap_invoke7(dispatcher, DispatcherCmd_Properties, type, deadline, 307 wcet, period, release, weight).error; 308} 309 310 311static inline errval_t invoke_dispatcher_dump_ptables(struct capref dispcap) 312{ 313 return cap_invoke1(dispcap, DispatcherCmd_DumpPTables).error; 314} 315 316static inline errval_t invoke_dispatcher_dump_capabilities(struct capref dispcap) 317{ 318 return cap_invoke1(dispcap, DispatcherCmd_DumpCapabilities).error; 319} 320 321/** 322 * IRQ manipulations 323 */ 324static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap) 325{ 326 struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap)); 327 return ret.error; 328} 329 330static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint64_t * out_vec) 331{ 332 struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector); 333 *out_vec = ret.value; 334 return ret.error; 335} 336 337static inline errval_t invoke_irqdest_get_cpu(struct capref irqcap, uint64_t * out_cpu) 338{ 339 struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetCpu); 340 *out_cpu = ret.value; 341 return ret.error; 342} 343 344static inline errval_t invoke_irqsrc_get_vec_start(struct capref irqcap, uint64_t * out_vec) 345{ 346 struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVecStart); 347 *out_vec = ret.value; 348 return ret.error; 349} 350 351static inline errval_t invoke_irqsrc_get_vec_end(struct capref irqcap, uint64_t * out_vec) 352{ 353 struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVecEnd); 354 *out_vec = ret.value; 355 return ret.error; 356} 357 358static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap) 359{ 360 uint8_t dcn_level = get_cnode_level(dest_cap); 361 capaddr_t dcn_addr = get_cnode_addr(dest_cap); 362 struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, 363 dcn_level, dcn_addr, dest_cap.slot); 364 return ret.error; 365} 366 367/** 368 * Deprecated. Use invoke_irqtable_alloc_dest_cap 369 */ 370static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq) 371{ 372 struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc); 373 if (err_is_ok(ret.error)) { 374 *retirq = ret.value; 375 } else { 376 *retirq = 0; 377 } 378 return ret.error; 379} 380 381static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq, 382 struct capref ep) 383{ 384 return cap_invoke3(irqcap, IRQTableCmd_Set, irq, get_cap_addr(ep)).error; 385} 386 387static inline errval_t invoke_irqtable_delete(struct capref irqcap, int irq) 388{ 389 return cap_invoke2(irqcap, IRQTableCmd_Delete, irq).error; 390} 391 392/** 393 * \brief do a kernel cap invocation to get the core id 394 */ 395static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap, 396 coreid_t *core_id) 397{ 398 assert(core_id != NULL); 399 400 struct sysret sysret = cap_invoke1(kern_cap, KernelCmd_Get_core_id); 401 if (sysret.error == SYS_ERR_OK) { 402 *core_id = sysret.value; 403 } 404 return sysret.error; 405} 406 407#endif // INVOCATIONS_H 408