3 * \brief Low-level capability invocations
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.
15 #ifndef INVOCATIONS_ARCH_H
16 #define INVOCATIONS_ARCH_H
18 #include <barrelfish/syscall_arch.h>
19 #include <barrelfish_kpi/dispatcher_shared.h>
20 #include <barrelfish_kpi/distcaps.h>
21 #include <barrelfish/caddr.h>
22 #include <barrelfish_kpi/paging_arch.h>
24 static inline struct sysret cap_invoke(struct capref to, uintptr_t arg1,
25 uintptr_t arg2, uintptr_t arg3,
26 uintptr_t arg4, uintptr_t arg5,
27 uintptr_t arg6, uintptr_t arg7,
28 uintptr_t arg8, uintptr_t arg9,
31 uint8_t invoke_bits = get_cap_valid_bits(to);
32 capaddr_t invoke_cptr = get_cap_addr(to) >> (CPTR_BITS - invoke_bits);
34 return syscall(SYSCALL_INVOKE, (uint64_t)invoke_cptr << 32 |
35 (uint64_t)invoke_bits << 16 | 10 << 8, 0,
36 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
40 #define cap_invoke10(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j) \
41 cap_invoke(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j)
42 #define cap_invoke9(to, _a, _b, _c, _d, _e, _f, _g, _h, _i) \
43 cap_invoke10(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, 0)
44 #define cap_invoke8(to, _a, _b, _c, _d, _e, _f, _g, _h) \
45 cap_invoke9(to, _a, _b, _c, _d, _e, _f, _g, _h, 0)
46 #define cap_invoke7(to, _a, _b, _c, _d, _e, _f, _g) \
47 cap_invoke8(to, _a, _b, _c, _d, _e, _f, _g, 0)
48 #define cap_invoke6(to, _a, _b, _c, _d, _e, _f) \
49 cap_invoke7(to, _a, _b, _c, _d, _e, _f, 0)
50 #define cap_invoke5(to, _a, _b, _c, _d, _e) \
51 cap_invoke6(to, _a, _b, _c, _d, _e, 0)
52 #define cap_invoke4(to, _a, _b, _c, _d) \
53 cap_invoke5(to, _a, _b, _c, _d, 0)
54 #define cap_invoke3(to, _a, _b, _c) \
55 cap_invoke4(to, _a, _b, _c, 0)
56 #define cap_invoke2(to, _a, _b) \
57 cap_invoke3(to, _a, _b, 0)
58 #define cap_invoke1(to, _a) \
59 cap_invoke2(to, _a, 0)
63 * \brief Retype a capability.
65 * Retypes CPtr 'cap' into 2^'objbits' caps of type 'newtype' and places them
66 * into slots starting at slot 'slot' in the CNode, addressed by 'to', with
67 * 'bits' address bits of 'to' valid.
69 * See also cap_retype(), which wraps this.
71 * \param root Capability of the CNode to invoke
72 * \param cap Address of cap to retype.
73 * \param newtype Kernel object type to retype to.
74 * \param objbits Size of created objects, for variable-sized types
75 * \param to Address of CNode cap to place retyped caps into.
76 * \param slot Slot in CNode cap to start placement.
77 * \param bits Number of valid address bits in 'to'.
81 static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t cap,
82 enum objtype newtype, int objbits,
83 capaddr_t to, capaddr_t slot, int bits)
85 assert(cap != CPTR_NULL);
86 return cap_invoke7(root, CNodeCmd_Retype, cap, newtype, objbits, to,
90 static inline errval_t invoke_cnode_retype2(struct capref root, capaddr_t cap,
91 gensize_t offset, enum objtype newtype,
92 gensize_t objsize, size_t count,
93 capaddr_t to, capaddr_t slot, int bits)
95 assert(cap != CPTR_NULL);
96 return cap_invoke9(root, CNodeCmd_Retype, cap, offset, newtype, objsize,
97 count, to, slot, bits).error;
101 * \brief Create a capability.
103 * Create a new capability of type 'type' and size 'objbits'. The new cap will
104 * be placed in the slot 'dest_slot' of the CNode located at 'dest_cnode_cptr'
105 * in the address space rooted at 'root'.
107 * See also cap_create(), which wraps this.
109 * \param root Capability of the CNode to invoke.
110 * \param type Kernel object type to create.
111 * \param objbits Size of created object
112 * (ignored for fixed-size objects)
113 * \param dest_cnode_cptr Address of CNode cap, where newly created cap will be
115 * \param dest_slot Slot in CNode cap to place new cap.
116 * \param dest_vbits Number of valid address bits in 'dest_cnode_cptr'.
120 static inline errval_t invoke_cnode_create(struct capref root,
121 enum objtype type, uint8_t objbits,
122 capaddr_t dest_cnode_cptr,
126 assert(dest_cnode_cptr != CPTR_NULL);
127 return cap_invoke6(root, CNodeCmd_Create, type, objbits, dest_cnode_cptr,
128 dest_slot, dest_vbits).error;
132 * \brief "Mint" a capability.
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.
138 * See also cap_mint(), which wraps this.
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.
151 static inline errval_t invoke_cnode_mint(struct capref root, capaddr_t to,
152 capaddr_t slot, capaddr_t from, int tobits,
153 int frombits, uint64_t param1,
156 return cap_invoke8(root, CNodeCmd_Mint, to, slot, from, tobits, frombits,
157 param1, param2).error;
161 * \brief Copy a capability.
163 * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within
164 * the address space, rooted at 'root' and with 'tobits' and 'frombits' address
165 * bits of 'to' and 'from' valid, respectively.
167 * See also cap_copy(), which wraps this.
169 * \param root Capability of the CNode to invoke
170 * \param to CNode to place copy into.
171 * \param slot Slot in CNode cap to place copy into.
172 * \param from Address of cap to copy.
173 * \param tobits Number of valid address bits in 'to'.
174 * \param frombits Number of valid address bits in 'from'.
178 static inline errval_t invoke_cnode_copy(struct capref root, capaddr_t to,
179 capaddr_t slot, capaddr_t from, int tobits,
182 return cap_invoke6(root, CNodeCmd_Copy, to, slot, from,
183 tobits, frombits).error;
187 * \brief Delete a capability.
189 * Delete the capability pointed to by 'cap', with 'bits' address bits
190 * of it valid, from the address space rooted at 'root'.
192 * \param root Capability of the CNode to invoke
193 * \param cap Address of cap to delete.
194 * \param bits Number of valid bits within 'cap'.
198 static inline errval_t invoke_cnode_delete(struct capref root, capaddr_t cap,
201 return cap_invoke3(root, CNodeCmd_Delete, cap, bits).error;
204 static inline errval_t invoke_cnode_revoke(struct capref root, capaddr_t cap,
207 return cap_invoke3(root, CNodeCmd_Revoke, cap, bits).error;
210 static inline errval_t invoke_cnode_get_state(struct capref root, capaddr_t cap,
211 int bits, distcap_state_t *ret)
213 struct sysret sysret = cap_invoke3(root, CNodeCmd_GetState, cap, bits);
216 if (err_is_ok(sysret.error)) {
225 static inline errval_t invoke_vnode_map(struct capref ptable, capaddr_t slot,
226 capaddr_t src, int frombits, size_t flags,
227 size_t offset, size_t pte_count,
228 capaddr_t mcnaddr, int mcnbits,
229 cslot_t mapping_slot)
231 return cap_invoke10(ptable, VNodeCmd_Map, slot, src, frombits, flags,
232 offset, pte_count, mcnaddr, mcnbits, mapping_slot).error;
235 static inline errval_t invoke_vnode_unmap(struct capref cap,
236 capaddr_t mapping_addr, int bits)
238 return cap_invoke3(cap, VNodeCmd_Unmap, mapping_addr, bits).error;
242 * \brief Return the physical address and size of a frame capability
244 * \param frame CSpace address of frame capability
245 * \param ret frame_identity struct filled in with relevant data
249 static inline errval_t invoke_frame_identify(struct capref frame,
250 struct frame_identity *ret)
254 struct sysret sysret = cap_invoke2(frame, FrameCmd_Identify, (uintptr_t)ret);
256 if (err_is_ok(sysret.error)) {
265 static inline errval_t invoke_vnode_identify(struct capref vnode,
266 struct vnode_identity *ret)
268 struct sysret sysret = cap_invoke1(vnode, VNodeCmd_Identify);
271 if (err_is_ok(sysret.error)) {
272 ret->base = sysret.value & (~BASE_PAGE_MASK);
273 ret->type = sysret.value & BASE_PAGE_MASK;
283 * \brief Modify mapping flags on parts of a mapping
285 * \param mapping CSpace address of mapping capability
286 * \param off Offset (in #pages) of the first page to get new set of flags
287 * from the first page in the mapping identified by `frame`
288 * \param pages Number of pages that should get new set of flags
289 * \param flags New set of flags
290 * \param va_hint Hint for selective TLB flushing
294 static inline errval_t invoke_mapping_modify_flags(struct capref mapping,
300 return cap_invoke5(mapping, MappingCmd_Modify, offset,
301 pages, flags, va_hint).error;
304 static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd,
305 uint16_t port, uint32_t *data)
307 struct sysret sysret = cap_invoke2(iocap, cmd, port);
309 if (err_is_ok(sysret.error)) {
310 assert(data != NULL);
311 *data = sysret.value;
316 static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd,
317 uint16_t port, uint32_t data)
319 return cap_invoke3(iocap, cmd, port, data).error;
323 * \brief Setup a dispatcher, possibly making it runnable
325 * \param dispatcher Address of dispatcher capability
326 * \param domdispatcher Address of existing dispatcher for domain ID
327 * \param cspace_root Root of CSpace for new dispatcher
328 * \param cspace_root_bits Number of valid bits in cspace_root
329 * \param vspace_root Root of VSpace for new dispatcher
330 * \param dispatcher_frame Frame capability for dispatcher structure
331 * \param run Make runnable if true
333 * Any arguments of CPTR_NULL are ignored.
337 static inline errval_t
338 invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher,
339 struct capref cspace, struct capref vspace,
340 struct capref dispframe, bool run)
342 uint8_t root_vbits = get_cap_valid_bits(cspace);
343 capaddr_t root_caddr = get_cap_addr(cspace) >> (CPTR_BITS - root_vbits);
344 capaddr_t vtree_caddr = get_cap_addr(vspace);
345 capaddr_t disp_caddr = get_cap_addr(dispframe);
346 capaddr_t dd_caddr = get_cap_addr(domdispatcher);
348 return cap_invoke7(dispatcher, DispatcherCmd_Setup, root_caddr,
349 root_vbits, vtree_caddr, disp_caddr, run,
354 * \brief Execute vmread on the VMCS of the VM guest DCB
356 * The VMCS must be current and active.
358 * \param dcb Dispatcher capability
359 * \param encoding Encoding of the field to read from the VMCS
360 * \param addr The address to write the value of the field to.
362 static inline errval_t invoke_dispatcher_vmread(struct capref dispatcher,
366 return cap_invoke3(dispatcher, DispatcherCmd_Vmread,
367 encoding, (uintptr_t)addr).error;
371 * \brief Execute vmwrite on the VMCS of the VM guest DCB
373 * The VMCS must be current and active.
375 * \param dcb Dispatcher capability
376 * \param encoding Encoding of the field to write to the VMCS.
377 * \param value Value of the field to write.
380 static inline errval_t invoke_dispatcher_vmwrite(struct capref dispatcher,
384 return cap_invoke3(dispatcher, DispatcherCmd_Vmwrite,
385 encoding, value).error;
389 * \brief Execute vmptrld on the VMCS of the VM guest DCB
391 * \param dcb Dispatcher capability
393 static inline errval_t invoke_dispatcher_vmptrld(struct capref dispatcher)
395 return cap_invoke1(dispatcher, DispatcherCmd_Vmptrld).error;
399 * \brief Execute vmclear on the VMCS of the VM guest DCB
401 * \param dcb Dispatcher capability
403 static inline errval_t invoke_dispatcher_vmclear(struct capref dispatcher)
405 return cap_invoke1(dispatcher, DispatcherCmd_Vmclear).error;
409 * \brief Setup a VM guest DCB
411 * \param dcb Dispatcher capability
413 static inline errval_t
414 invoke_dispatcher_setup_guest(struct capref dispatcher,
415 struct capref ep_cap,
417 struct capref vmkit_guest,
418 struct capref guest_control_cap)
420 return cap_invoke5(dispatcher, DispatcherCmd_SetupGuest,
421 get_cap_addr(ep_cap), get_cap_addr(vnode),
422 get_cap_addr(vmkit_guest),
423 get_cap_addr(guest_control_cap)).error;
426 static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap)
428 struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap));
432 static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t * out_vec)
434 struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector);
435 *out_vec = ret.value;
439 static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
441 struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
442 *out_vec = ret.value;
446 static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
448 uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
449 capaddr_t dcn_addr = get_cnode_addr(dest_cap);
450 struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
455 * Deprecated. Use invoke_irqtable_alloc_dest_cap
457 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
459 struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc);
460 if (err_is_ok(ret.error)) {
468 static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq,
471 return cap_invoke3(irqcap, IRQTableCmd_Set, irq, get_cap_addr(ep)).error;
474 static inline errval_t invoke_irqtable_delete(struct capref irqcap, int irq)
476 return cap_invoke2(irqcap, IRQTableCmd_Delete, irq).error;
480 * \brief do a kernel cap invocation to get the core id
482 static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap,
485 assert(core_id != NULL);
487 struct sysret sysret = cap_invoke1(kern_cap, KernelCmd_Get_core_id);
488 if (sysret.error == SYS_ERR_OK) {
489 *core_id = sysret.value;
494 static inline errval_t invoke_dispatcher_dump_ptables(struct capref dispcap)
496 return cap_invoke1(dispcap, DispatcherCmd_DumpPTables).error;
499 static inline errval_t invoke_dispatcher_dump_capabilities(struct capref dispcap)
501 return cap_invoke1(dispcap, DispatcherCmd_DumpCapabilities).error;
504 static inline errval_t invoke_perfmon_activate(struct capref perfmon_cap,
505 uint8_t event, uint8_t perf_umask,
506 bool kernel, uint8_t counter_id,
507 uint64_t counter_value,
510 return cap_invoke7(perfmon_cap, PerfmonCmd_Activate,
511 event, perf_umask, counter_id, kernel,
512 counter_value, ep_addr).error;
515 static inline errval_t invoke_perfmon_write(struct capref perfmon_cap,
517 uint64_t counter_value)
519 return cap_invoke3(perfmon_cap, PerfmonCmd_Write, counter_id, counter_value).error;
522 static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap)
524 return cap_invoke1(perfmon_cap, PerfmonCmd_Deactivate).error;
527 static inline errval_t
528 invoke_dispatcher_properties(struct capref dispatcher,
529 enum task_type type, unsigned long deadline,
530 unsigned long wcet, unsigned long period,
531 unsigned long release, unsigned short weight)
533 return cap_invoke7(dispatcher, DispatcherCmd_Properties, type, deadline,
534 wcet, period, release, weight).error;
537 static inline errval_t invoke_ipi_notify_send(struct capref notify_cap)
539 return cap_invoke1(notify_cap, NotifyCmd_Send).error;
543 * \brief Return the system-wide unique ID of the passed ID capability.
545 * \param idcap ID capability to invoke.
546 * \param id Filled-in with system-wide unique ID of ID cap.
550 static inline errval_t invoke_idcap_identify(struct capref idcap,
555 struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify);
557 if (err_is_ok(sysret.error)) {
564 static inline errval_t invoke_send_init_ipi(struct capref ipi_cap, coreid_t core_id)
566 return cap_invoke2(ipi_cap, IPICmd_Send_Init,
570 static inline errval_t invoke_send_start_ipi(struct capref ipi_cap, coreid_t core_id, forvaddr_t entry)
572 return cap_invoke3(ipi_cap, IPICmd_Send_Start,
573 core_id, entry).error;
576 static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global)
578 struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys);
579 if (err_is_ok(sr.error)) {