1/** 2 * \file 3 * \brief Low-level capability invocations 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, 2012, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14#ifndef INVOCATIONS_ARCH_H 15#define INVOCATIONS_ARCH_H 16 17#include <barrelfish/syscall_arch.h> 18#include <barrelfish_kpi/dispatcher_shared.h> 19#include <barrelfish_kpi/distcaps.h> // for distcap_state_t 20#include <barrelfish_kpi/syscalls.h> 21#include <barrelfish/caddr.h> 22#include <barrelfish_kpi/paging_arch.h> 23#include <barrelfish/debug.h> 24 25/** 26 * capability invocation syscall wrapper, copied from x86_64 version 27 */ 28static inline struct sysret cap_invoke(struct capref to, uintptr_t arg1, 29 uintptr_t arg2, uintptr_t arg3, 30 uintptr_t arg4, uintptr_t arg5, 31 uintptr_t arg6) 32{ 33 uint8_t invoke_bits = get_cap_valid_bits(to); 34 capaddr_t invoke_cptr = get_cap_addr(to) >> (CPTR_BITS - invoke_bits); 35 36 // invoke_bits << 16 | cmd << 8 | syscall_invoke 37 uint32_t invocation = ((invoke_bits << 16) | (arg1 << 8) | SYSCALL_INVOKE); 38 39 return syscall(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6); 40} 41 42#define cap_invoke6(to, _a, _b, _c, _d, _e, _f) \ 43 cap_invoke(to, _a, _b, _c, _d, _e, _f) 44#define cap_invoke5(to, _a, _b, _c, _d, _e) \ 45 cap_invoke6(to, _a, _b, _c, _d, _e, 0) 46#define cap_invoke4(to, _a, _b, _c, _d) \ 47 cap_invoke5(to, _a, _b, _c, _d, 0) 48#define cap_invoke3(to, _a, _b, _c) \ 49 cap_invoke4(to, _a, _b, _c, 0) 50#define cap_invoke2(to, _a, _b) \ 51 cap_invoke3(to, _a, _b, 0) 52#define cap_invoke1(to, _a) \ 53 cap_invoke2(to, _a, 0) 54 55/** 56 * \brief Retype a capability. 57 * 58 * Retypes CPtr 'cap' into 2^'objbits' caps of type 'newtype' and places them 59 * into slots starting at slot 'slot' in the CNode, addressed by 'to', with 60 * 'bits' address bits of 'to' valid. 61 * 62 * See also cap_retype(), which wraps this. 63 * 64 * \param root Capability of the CNode to invoke 65 * \param cap Address of cap to retype. 66 * \param newtype Kernel object type to retype to. 67 * \param objbits Size of created objects, for variable-sized types 68 * \param to Address of CNode cap to place retyped caps into. 69 * \param slot Slot in CNode cap to start placement. 70 * \param bits Number of valid address bits in 'to'. 71 * 72 * \return Error code 73 */ 74static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t cap, 75 enum objtype newtype, int objbits, 76 capaddr_t to, capaddr_t slot, int bits) 77{ 78 assert(cap != CPTR_NULL); 79 80 uint8_t invoke_bits = get_cap_valid_bits(root); 81 capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits); 82 83 assert(newtype <= ObjType_Num); 84 assert(objbits <= 0xff); 85 assert(bits <= 0xff); 86 87 return syscall6((invoke_bits << 16) | (CNodeCmd_Retype << 8) | SYSCALL_INVOKE, 88 invoke_cptr, cap, (newtype << 16) | (objbits << 8) | bits, to, 89 slot).error; 90} 91 92/** 93 * \brief Create a capability. 94 * 95 * Create a new capability of type 'type' and size 'objbits'. The new cap will 96 * be placed in the slot 'dest_slot' of the CNode located at 'dest_cnode_cptr' 97 * in the address space rooted at 'root'. 98 * 99 * See also cap_create(), which wraps this. 100 * 101 * \param root Capability of the CNode to invoke. 102 * \param type Kernel object type to create. 103 * \param objbits Size of created object 104 * (ignored for fixed-size objects) 105 * \param dest_cnode_cptr Address of CNode cap, where newly created cap will be 106 * placed into. 107 * \param dest_slot Slot in CNode cap to place new cap. 108 * \param dest_vbits Number of valid address bits in 'dest_cnode_cptr'. 109 * 110 * \return Error code 111 */ 112static inline errval_t invoke_cnode_create(struct capref root, 113 enum objtype type, uint8_t objbits, 114 capaddr_t dest_cnode_cptr, 115 capaddr_t dest_slot, 116 uint8_t dest_vbits) 117{ 118 /* Pack arguments */ 119 assert(dest_cnode_cptr != CPTR_NULL); 120 121 uint8_t invoke_bits = get_cap_valid_bits(root); 122 capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits); 123 124 assert(type <= ObjType_Num); 125 126 return syscall5((invoke_bits << 16) | (CNodeCmd_Create << 8) | SYSCALL_INVOKE, 127 invoke_cptr, (type << 16) | (objbits << 8) | dest_vbits, 128 dest_cnode_cptr, dest_slot).error; 129} 130 131/** 132 * \brief "Mint" a capability. 133 * 134 * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within 135 * the address space, rooted at 'root' and with 'tobits' and 'frombits' address 136 * bits of 'to' and 'from' valid, respectively. 137 * 138 * See also cap_mint(), which wraps this. 139 * 140 * \param root Capability of the CNode to invoke 141 * \param to CNode to place copy into. 142 * \param slot Slot in CNode cap to place copy into. 143 * \param from Address of cap to copy. 144 * \param tobits Number of valid address bits in 'to'. 145 * \param frombits Number of valid address bits in 'from'. 146 * \param param1 1st cap-dependent parameter. 147 * \param param2 2nd cap-dependent parameter. 148 * 149 * \return Error code 150 */ 151static inline errval_t invoke_cnode_mint(struct capref root, capaddr_t to, 152 capaddr_t slot, capaddr_t from, int tobits, 153 int frombits, uintptr_t param1, 154 uintptr_t param2) 155{ 156 uint8_t invoke_bits = get_cap_valid_bits(root); 157 capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits); 158 159 assert(slot <= 0xffff); 160 assert(tobits <= 0xff); 161 assert(frombits <= 0xff); 162 163 return syscall7((invoke_bits << 16) | (CNodeCmd_Mint << 8) | SYSCALL_INVOKE, 164 invoke_cptr, to, from, 165 (slot << 16) | (tobits << 8) | frombits, param1, 166 param2).error; 167} 168 169/** 170 * \brief Copy a capability. 171 * 172 * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within 173 * the address space, rooted at 'root' and with 'tobits' and 'frombits' address 174 * bits of 'to' and 'from' valid, respectively. 175 * 176 * See also cap_copy(), which wraps this. 177 * 178 * \param root Capability of the CNode to invoke 179 * \param to CNode to place copy into. 180 * \param slot Slot in CNode cap to place copy into. 181 * \param from Address of cap to copy. 182 * \param tobits Number of valid address bits in 'to'. 183 * \param frombits Number of valid address bits in 'from'. 184 * 185 * \return Error code 186 */ 187// XXX: workaround for an inlining bug in gcc 4.3.4 188#if defined(__GNUC__) \ 189 && __GNUC__ == 4 && __GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ <= 4 190static __attribute__ ((noinline,unused)) errval_t 191invoke_cnode_copy(struct capref root, capaddr_t to, 192 capaddr_t slot, capaddr_t from, int tobits, 193 int frombits) 194#else 195static inline errval_t invoke_cnode_copy(struct capref root, capaddr_t to, 196 capaddr_t slot, capaddr_t from, int tobits, 197 int frombits) 198#endif 199{ 200 uint8_t invoke_bits = get_cap_valid_bits(root); 201 capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits); 202 203 assert(slot <= 0xffff); 204 assert(tobits <= 0xff); 205 assert(frombits <= 0xff); 206 207 return syscall5((invoke_bits << 16) | (CNodeCmd_Copy << 8) | SYSCALL_INVOKE, 208 invoke_cptr, to, from, 209 (slot << 16) | (tobits << 8) | frombits).error; 210} 211 212/** 213 * \brief Delete a capability. 214 * 215 * Delete the capability pointed to by 'cap', with 'bits' address bits 216 * of it valid, from the address space rooted at 'root'. 217 * 218 * \param root Capability of the CNode to invoke 219 * \param cap Address of cap to delete. 220 * \param bits Number of valid bits within 'cap'. 221 * 222 * \return Error code 223 */ 224static inline errval_t invoke_cnode_delete(struct capref root, capaddr_t cap, 225 int bits) 226{ 227 uint8_t invoke_bits = get_cap_valid_bits(root); 228 capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits); 229 230 assert(bits <= 0xff); 231 232 return syscall4((invoke_bits << 16) | (CNodeCmd_Delete << 8) | SYSCALL_INVOKE, 233 invoke_cptr, cap, bits).error; 234} 235 236static inline errval_t invoke_cnode_revoke(struct capref root, capaddr_t cap, 237 int bits) 238{ 239 uint8_t invoke_bits = get_cap_valid_bits(root); 240 capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits); 241 242 assert(bits <= 0xff); 243 244 return syscall4((invoke_bits << 16) | (CNodeCmd_Revoke << 8) | SYSCALL_INVOKE, 245 invoke_cptr, cap, bits).error; 246} 247 248static inline errval_t invoke_cnode_get_state(struct capref root, capaddr_t cap, 249 int bits, distcap_state_t *ret) 250{ 251 uint8_t invoke_bits = get_cap_valid_bits(root); 252 capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits); 253 254 assert (bits <= 0xff); 255 256 struct sysret sysret = 257 syscall4((invoke_bits << 16) | (CNodeCmd_GetState << 8) | SYSCALL_INVOKE, 258 invoke_cptr, cap, bits); 259 260 assert(ret != NULL); 261 if (err_is_ok(sysret.error)) { 262 *ret = sysret.value; 263 } 264 else { 265 *ret = 0; 266 } 267 return sysret.error; 268} 269 270// XXX: workaround for an inlining bug in gcc 4.3.4 271#if defined(__GNUC__) \ 272 && __GNUC__ == 4 && __GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ <= 4 273static __attribute__ ((noinline,unused)) errval_t 274invoke_vnode_map(struct capref ptable, capaddr_t slot, capaddr_t from, 275 int frombits, uintptr_t flags, uintptr_t offset, uintptr_t pte_count) 276#else 277static inline errval_t invoke_vnode_map(struct capref ptable, capaddr_t slot, 278 capaddr_t from, int frombits, uintptr_t flags, 279 uintptr_t offset, uintptr_t pte_count, 280 capaddr_t mcn_addr, int mcn_vbits, 281 int mapping_slot) 282#endif 283{ 284 uint8_t invoke_bits = get_cap_valid_bits(ptable); 285 capaddr_t invoke_cptr = get_cap_addr(ptable) >> (CPTR_BITS - invoke_bits); 286 287 assert(slot <= 0xffff); 288 assert(pte_count <= 0xffff); 289 assert(frombits <= 0xff); 290 assert(mcn_vbits <= 0xff); 291 assert(mapping_slot <= 0xffff); 292 293 uintptr_t invocation = (invoke_bits << 16) | (VNodeCmd_Map << 8) | SYSCALL_INVOKE; 294 uintptr_t mapping_slot_and_bits = (mapping_slot << 16) | (mcn_vbits << 8) | frombits; 295 uintptr_t pte_slot_and_count = (slot << 16) | pte_count; 296 297 uint64_t overflow[] = { offset, flags }; 298 299 300 // XXX: needs check of flags, offset, and pte_count sizes 301 // XXX: flag transfer breaks for PAE (flags are 64 bits for PAE) 302 return syscall7(invocation, invoke_cptr, from, 303 mapping_slot_and_bits, mcn_addr, 304 pte_slot_and_count, (uintptr_t)overflow).error; 305} 306 307 308static inline errval_t invoke_vnode_unmap(struct capref cap, capaddr_t mapping_cptr, 309 int mapping_bits) 310{ 311 uint8_t invoke_bits = get_cap_valid_bits(cap); 312 capaddr_t invoke_cptr = get_cap_addr(cap) >> (CPTR_BITS - invoke_bits); 313 314 assert(mapping_bits <= 0xff); 315 316 return syscall4((invoke_bits << 16) | (VNodeCmd_Unmap << 8) | SYSCALL_INVOKE, 317 invoke_cptr, mapping_cptr, mapping_bits).error; 318} 319 320/** 321 * \brief Return the physical address and size of a frame capability 322 * 323 * \param frame CSpace address of frame capability 324 * \param ret frame_identity struct filled in with relevant data 325 * 326 * \return Error code 327 */ 328static inline errval_t invoke_frame_identify(struct capref frame, 329 struct frame_identity *ret) 330{ 331 struct sysret sysret = cap_invoke1(frame, FrameCmd_Identify); 332 333 assert(ret != NULL); 334 if (err_is_ok(sysret.error)) { 335 ret->base = sysret.value & (~BASE_PAGE_MASK); 336 ret->bits = sysret.value & BASE_PAGE_MASK; 337 return sysret.error; 338 } 339 340 ret->base = 0; 341 ret->bits = 0; 342 return sysret.error; 343} 344 345static inline errval_t invoke_vnode_identify(struct capref vnode, 346 struct vnode_identity *ret) 347{ 348 struct sysret sysret = cap_invoke1(vnode, VNodeCmd_Identify); 349 350 assert(ret != NULL); 351 if (err_is_ok(sysret.error)) { 352 ret->base = sysret.value & (~BASE_PAGE_MASK); 353 ret->type = sysret.value & BASE_PAGE_MASK; 354 return sysret.error; 355 } 356 357 ret->base = 0; 358 ret->type = 0; 359 return sysret.error; 360} 361 362 363/** 364 * \brief Modify mapping flags on parts of a mapped frame 365 * 366 * \param frame CSpace address of frame capability 367 * \param off Offset (in #pages) of the first page to get new set of flags 368 * from the first page in the mapping identified by `frame` 369 * \param pages Number of pages that should get new set of flags 370 * \param flags New set of flags 371 * 372 * \return Error code 373 */ 374static inline errval_t invoke_mapping_modify_flags(struct capref mapping, 375 size_t offset, 376 size_t pages, 377 size_t flags, 378 genvaddr_t va_hint) 379{ 380 return cap_invoke5(mapping, MappingCmd_Modify, offset, 381 pages, flags, va_hint).error; 382} 383 384 385static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd, 386 uint16_t port, uint32_t *data) 387{ 388 uint8_t invoke_bits = get_cap_valid_bits(iocap); 389 capaddr_t invoke_cptr = get_cap_addr(iocap) >> (CPTR_BITS - invoke_bits); 390 391 assert(cmd <= 0xff); 392 393 struct sysret sysret = 394 syscall3((invoke_bits << 16) | (cmd << 8) | SYSCALL_INVOKE, 395 invoke_cptr, port); 396 397 if (err_is_ok(sysret.error)) { 398 assert(data != NULL); 399 *data = sysret.value; 400 } 401 return sysret.error; 402} 403 404static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd, 405 uint16_t port, uint32_t data) 406{ 407 uint8_t invoke_bits = get_cap_valid_bits(iocap); 408 capaddr_t invoke_cptr = get_cap_addr(iocap) >> (CPTR_BITS - invoke_bits); 409 410 assert(cmd <= 0xff); 411 return syscall4((invoke_bits << 16) | (cmd << 8) | SYSCALL_INVOKE, 412 invoke_cptr, port, data).error; 413} 414 415/** 416 * \brief Setup a dispatcher, possibly making it runnable 417 * 418 * \param dispatcher Address of dispatcher capability 419 * \param domdispatcher Address of existing dispatcher for domain ID 420 * \param cspace_root Root of CSpace for new dispatcher 421 * \param cspace_root_bits Number of valid bits in cspace_root 422 * \param vspace_root Root of VSpace for new dispatcher 423 * \param dispatcher_frame Frame capability for dispatcher structure 424 * \param run Make runnable if true 425 * 426 * Any arguments of CPTR_NULL are ignored. 427 * 428 * \return Error code 429 */ 430// XXX: workaround for an inlining bug in gcc 4.3.4 431#if defined(__GNUC__) \ 432 && __GNUC__ == 4 && __GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ <= 4 433static __attribute__ ((noinline,unused)) errval_t 434#else 435static inline errval_t 436#endif 437invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher, 438 struct capref cspace, struct capref vspace, 439 struct capref dispframe, bool run) 440{ 441 uint8_t root_vbits = get_cap_valid_bits(cspace); 442 capaddr_t root_caddr = get_cap_addr(cspace) >> (CPTR_BITS - root_vbits); 443 capaddr_t vtree_caddr = get_cap_addr(vspace); 444 capaddr_t disp_caddr = get_cap_addr(dispframe); 445 capaddr_t dd_caddr = get_cap_addr(domdispatcher); 446 uint8_t invoke_bits = get_cap_valid_bits(dispatcher); 447 capaddr_t invoke_cptr = get_cap_addr(dispatcher) >> (CPTR_BITS - invoke_bits); 448 449 return syscall7((invoke_bits << 16) | (DispatcherCmd_Setup << 8) | 450 SYSCALL_INVOKE, 451 invoke_cptr, dd_caddr, root_caddr, 452 (run << 8) | (root_vbits & 0xff), vtree_caddr, 453 disp_caddr).error; 454} 455 456/** 457 * \brief Setup a VM guest DCB 458 * 459 * \param dcb Dispatcher capability 460 */ 461static inline errval_t invoke_dispatcher_setup_guest(struct capref dispatcher, 462 capaddr_t ep_cap, 463 capaddr_t vnode, 464 capaddr_t vmkit_guest, 465 capaddr_t guest_control_cap) 466{ 467 USER_PANIC("NYI"); 468 return LIB_ERR_NOT_IMPLEMENTED; 469} 470 471static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap) 472{ 473 struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap)); 474 return ret.error; 475} 476 477static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t * out_vec) 478{ 479 struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector); 480 *out_vec = ret.value; 481 return ret.error; 482} 483 484static inline errval_t invoke_irqsrc_get_vec_start(struct capref irqcap, uint32_t * out_vec) 485{ 486 USER_PANIC("NYI"); 487 return LIB_ERR_NOT_IMPLEMENTED; 488} 489 490static inline errval_t invoke_irqsrc_get_vec_end(struct capref irqcap, uint32_t * out_vec) 491{ 492 USER_PANIC("NYI"); 493 return LIB_ERR_NOT_IMPLEMENTED; 494} 495 496static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap) 497{ 498 USER_PANIC("NYI"); 499 return LIB_ERR_NOT_IMPLEMENTED; 500} 501 502/** 503 * Deprecated. Use invoke_irqtable_alloc_dest_cap 504 */ 505static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq) 506{ 507 uint8_t invoke_bits = get_cap_valid_bits(irqcap); 508 capaddr_t invoke_cptr = get_cap_addr(irqcap) >> (CPTR_BITS - invoke_bits); 509 510 struct sysret ret = syscall2( 511 (invoke_bits << 16) | (IRQTableCmd_Alloc << 8) | SYSCALL_INVOKE, 512 invoke_cptr); 513 if (err_is_ok(ret.error)) { 514 *retirq = ret.value; 515 } else { 516 *retirq = 0; 517 } 518 return ret.error; 519} 520 521static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq, 522 struct capref ep) 523{ 524 uint8_t invoke_bits = get_cap_valid_bits(irqcap); 525 capaddr_t invoke_cptr = get_cap_addr(irqcap) >> (CPTR_BITS - invoke_bits); 526 527 return syscall4((invoke_bits << 16) | (IRQTableCmd_Set << 8) | 528 SYSCALL_INVOKE, invoke_cptr, 529 irq, get_cap_addr(ep)).error; 530} 531 532static inline errval_t invoke_irqtable_delete(struct capref irqcap, int irq) 533{ 534 USER_PANIC("NYI"); 535 return LIB_ERR_NOT_IMPLEMENTED; 536} 537 538/** 539 * \brief do a kernel cap invocation to get the core id 540 */ 541static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap, 542 uint8_t *core_id) 543{ 544 assert(core_id != NULL); 545 546 uint8_t invoke_bits = get_cap_valid_bits(kern_cap); 547 capaddr_t invoke_cptr = get_cap_addr(kern_cap) >> (CPTR_BITS - invoke_bits); 548 549 struct sysret sysret = 550 syscall2((invoke_bits << 16) | (KernelCmd_Get_core_id << 8) | SYSCALL_INVOKE, 551 invoke_cptr); 552 553 if (sysret.error == SYS_ERR_OK) { 554 *core_id = sysret.value; 555 } 556 557 return sysret.error; 558} 559 560static inline errval_t invoke_dispatcher_dump_ptables(struct capref dispcap) 561{ 562 uint8_t invoke_bits = get_cap_valid_bits(dispcap); 563 capaddr_t invoke_cptr = get_cap_addr(dispcap) >> (CPTR_BITS - invoke_bits); 564 565 return syscall2((invoke_bits << 16) | (DispatcherCmd_DumpPTables << 8) | 566 SYSCALL_INVOKE, invoke_cptr).error; 567} 568 569static inline errval_t invoke_dispatcher_dump_capabilities(struct capref dispcap) 570{ 571 uint8_t invoke_bits = get_cap_valid_bits(dispcap); 572 capaddr_t invoke_cptr = get_cap_addr(dispcap) >> (CPTR_BITS - invoke_bits); 573 574 return syscall2((invoke_bits << 16) | (DispatcherCmd_DumpCapabilities << 8) | 575 SYSCALL_INVOKE, invoke_cptr).error; 576} 577 578static inline errval_t invoke_ipi_notify_send(struct capref notify_cap) 579{ 580 uint8_t invoke_bits = get_cap_valid_bits(notify_cap); 581 capaddr_t invoke_cptr = get_cap_addr(notify_cap) >> (CPTR_BITS - invoke_bits); 582 583 return syscall2((invoke_bits << 16) | (NotifyCmd_Send << 8) | SYSCALL_INVOKE, 584 invoke_cptr).error; 585} 586 587static inline errval_t invoke_perfmon_setup(struct capref dispcap, 588 uint8_t counter, uint64_t evt, 589 uint64_t umsk, bool os) 590{ 591 uint8_t invoke_bits = get_cap_valid_bits(dispcap); 592 capaddr_t invoke_cptr = get_cap_addr(dispcap) >> (CPTR_BITS - invoke_bits); 593 594 return syscall7((invoke_bits << 16) | (DispatcherCmd_PerfMon << 8) | SYSCALL_INVOKE, 595 invoke_cptr, counter, 0, evt, umsk, os ? 1 : 0).error; 596} 597 598static inline errval_t invoke_perfmon_write(struct capref dispcap, 599 uint8_t counter, uint64_t value) 600{ 601 uint8_t invoke_bits = get_cap_valid_bits(dispcap); 602 capaddr_t invoke_cptr = get_cap_addr(dispcap) >> (CPTR_BITS - invoke_bits); 603 uint32_t value_lo = value & 0xffffffff, value_hi = value >> 32; 604 605 return syscall6((invoke_bits << 16) | (DispatcherCmd_PerfMon << 8) | SYSCALL_INVOKE, 606 invoke_cptr, counter, 1, value_hi, value_lo).error; 607} 608 609static inline errval_t 610invoke_dispatcher_properties(struct capref dispatcher, 611 enum task_type type, unsigned long deadline, 612 unsigned long wcet, unsigned long period, 613 unsigned long release, unsigned short weight) 614{ 615 uint8_t invoke_bits = get_cap_valid_bits(dispatcher); 616 capaddr_t invoke_cptr = get_cap_addr(dispatcher) >> (CPTR_BITS - invoke_bits); 617 618 return syscall7((invoke_bits << 16) | (DispatcherCmd_Properties << 8) | SYSCALL_INVOKE, 619 invoke_cptr, (type << 16) | weight, deadline, wcet, period, release).error; 620} 621 622static inline errval_t invoke_perfmon_activate(struct capref perfmon_cap, 623 uint8_t event, uint8_t perf_umask, 624 bool kernel, uint8_t counter_id, 625 uint64_t counter_value, 626 capaddr_t ep_addr) 627{ 628 return ERR_NOTIMP; 629} 630 631static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap) 632{ 633 return ERR_NOTIMP; 634} 635 636/** 637 * \brief Return the system-wide unique ID of the passed ID capability. 638 * 639 * \param idcap ID capability to invoke. 640 * \param id Filled-in with system-wide unique ID of ID cap. 641 * 642 * \return Error code 643 */ 644static inline errval_t invoke_idcap_identify(struct capref idcap, 645 idcap_id_t *id) 646{ 647 assert(id != NULL); 648 uint8_t invoke_bits = get_cap_valid_bits(idcap); 649 capaddr_t invoke_cptr = get_cap_addr(idcap) >> (CPTR_BITS - invoke_bits); 650 651 // user-space pointer 'id' is directly written to by kernel. 652 struct sysret sysret = 653 syscall3((invoke_bits << 16) | (IDCmd_Identify << 8) | SYSCALL_INVOKE, 654 invoke_cptr, (uintptr_t) id); 655 656 return sysret.error; 657} 658 659static inline errval_t invoke_send_init_ipi(struct capref ipi_cap, coreid_t core_id) 660{ 661 uint8_t invoke_bits = get_cap_valid_bits(ipi_cap); 662 capaddr_t invoke_cptr = get_cap_addr(ipi_cap) >> (CPTR_BITS - invoke_bits); 663 664 return 665 syscall3((invoke_bits << 16) | (IPICmd_Send_Init << 8) | SYSCALL_INVOKE, 666 invoke_cptr, (uintptr_t) core_id).error; 667} 668 669static inline errval_t invoke_send_start_ipi(struct capref ipi_cap, coreid_t core_id, forvaddr_t entry) 670{ 671 uint8_t invoke_bits = get_cap_valid_bits(ipi_cap); 672 capaddr_t invoke_cptr = get_cap_addr(ipi_cap) >> (CPTR_BITS - invoke_bits); 673 674 return 675 syscall4((invoke_bits << 16) | (IPICmd_Send_Start << 8) | SYSCALL_INVOKE, 676 invoke_cptr, (uintptr_t) core_id, (uintptr_t) entry).error; 677 678} 679 680static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global) 681{ 682 struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys); 683 if (err_is_ok(sr.error)) { 684 *global = sr.value; 685 } 686 687 return sr.error; 688} 689 690#endif // INVOCATIONS_ARCH_H 691