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,
91 * \brief Create a capability.
93 * Create a new capability of type 'type' and size 'objbits'. The new cap will
94 * be placed in the slot 'dest_slot' of the CNode located at 'dest_cnode_cptr'
95 * in the address space rooted at 'root'.
97 * See also cap_create(), which wraps this.
99 * \param root Capability of the CNode to invoke.
100 * \param type Kernel object type to create.
101 * \param objbits Size of created object
102 * (ignored for fixed-size objects)
103 * \param dest_cnode_cptr Address of CNode cap, where newly created cap will be
105 * \param dest_slot Slot in CNode cap to place new cap.
106 * \param dest_vbits Number of valid address bits in 'dest_cnode_cptr'.
110 static inline errval_t invoke_cnode_create(struct capref root,
111 enum objtype type, uint8_t objbits,
112 capaddr_t dest_cnode_cptr,
116 assert(dest_cnode_cptr != CPTR_NULL);
117 return cap_invoke6(root, CNodeCmd_Create, type, objbits, dest_cnode_cptr,
118 dest_slot, dest_vbits).error;
122 * \brief "Mint" a capability.
124 * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within
125 * the address space, rooted at 'root' and with 'tobits' and 'frombits' address
126 * bits of 'to' and 'from' valid, respectively.
128 * See also cap_mint(), which wraps this.
130 * \param root Capability of the CNode to invoke
131 * \param to CNode to place copy into.
132 * \param slot Slot in CNode cap to place copy into.
133 * \param from Address of cap to copy.
134 * \param tobits Number of valid address bits in 'to'.
135 * \param frombits Number of valid address bits in 'from'.
136 * \param param1 1st cap-dependent parameter.
137 * \param param2 2nd cap-dependent parameter.
141 static inline errval_t invoke_cnode_mint(struct capref root, capaddr_t to,
142 capaddr_t slot, capaddr_t from, int tobits,
143 int frombits, uint64_t param1,
146 return cap_invoke8(root, CNodeCmd_Mint, to, slot, from, tobits, frombits,
147 param1, param2).error;
151 * \brief Copy a capability.
153 * Copies CPtr 'from' into slot 'slot' in the CNode, addressed by 'to', within
154 * the address space, rooted at 'root' and with 'tobits' and 'frombits' address
155 * bits of 'to' and 'from' valid, respectively.
157 * See also cap_copy(), which wraps this.
159 * \param root Capability of the CNode to invoke
160 * \param to CNode to place copy into.
161 * \param slot Slot in CNode cap to place copy into.
162 * \param from Address of cap to copy.
163 * \param tobits Number of valid address bits in 'to'.
164 * \param frombits Number of valid address bits in 'from'.
168 static inline errval_t invoke_cnode_copy(struct capref root, capaddr_t to,
169 capaddr_t slot, capaddr_t from, int tobits,
172 return cap_invoke6(root, CNodeCmd_Copy, to, slot, from,
173 tobits, frombits).error;
177 * \brief Delete a capability.
179 * Delete the capability pointed to by 'cap', with 'bits' address bits
180 * of it valid, from the address space rooted at 'root'.
182 * \param root Capability of the CNode to invoke
183 * \param cap Address of cap to delete.
184 * \param bits Number of valid bits within 'cap'.
188 static inline errval_t invoke_cnode_delete(struct capref root, capaddr_t cap,
191 return cap_invoke3(root, CNodeCmd_Delete, cap, bits).error;
194 static inline errval_t invoke_cnode_revoke(struct capref root, capaddr_t cap,
197 return cap_invoke3(root, CNodeCmd_Revoke, cap, bits).error;
200 static inline errval_t invoke_cnode_get_state(struct capref root, capaddr_t cap,
201 int bits, distcap_state_t *ret)
203 struct sysret sysret = cap_invoke3(root, CNodeCmd_GetState, cap, bits);
206 if (err_is_ok(sysret.error)) {
215 static inline errval_t invoke_vnode_map(struct capref ptable, capaddr_t slot,
216 capaddr_t src, int frombits, size_t flags,
217 size_t offset, size_t pte_count,
218 capaddr_t mcnaddr, int mcnbits,
219 cslot_t mapping_slot)
221 return cap_invoke10(ptable, VNodeCmd_Map, slot, src, frombits, flags,
222 offset, pte_count, mcnaddr, mcnbits, mapping_slot).error;
225 static inline errval_t invoke_vnode_unmap(struct capref cap,
226 capaddr_t mapping_addr, int bits)
228 return cap_invoke3(cap, VNodeCmd_Unmap, mapping_addr, bits).error;
232 * \brief Return the physical address and size of a frame capability
234 * \param frame CSpace address of frame capability
235 * \param ret frame_identity struct filled in with relevant data
239 static inline errval_t invoke_frame_identify(struct capref frame,
240 struct frame_identity *ret)
242 struct sysret sysret = cap_invoke1(frame, FrameCmd_Identify);
245 if (err_is_ok(sysret.error)) {
246 ret->base = sysret.value & (~BASE_PAGE_MASK);
247 ret->bits = sysret.value & BASE_PAGE_MASK;
256 static inline errval_t invoke_vnode_identify(struct capref vnode,
257 struct vnode_identity *ret)
259 struct sysret sysret = cap_invoke1(vnode, VNodeCmd_Identify);
262 if (err_is_ok(sysret.error)) {
263 ret->base = sysret.value & (~BASE_PAGE_MASK);
264 ret->type = sysret.value & BASE_PAGE_MASK;
274 * \brief Modify mapping flags on parts of a mapping
276 * \param mapping CSpace address of mapping capability
277 * \param off Offset (in #pages) of the first page to get new set of flags
278 * from the first page in the mapping identified by `frame`
279 * \param pages Number of pages that should get new set of flags
280 * \param flags New set of flags
281 * \param va_hint Hint for selective TLB flushing
285 static inline errval_t invoke_mapping_modify_flags(struct capref mapping,
291 return cap_invoke5(mapping, MappingCmd_Modify, offset,
292 pages, flags, va_hint).error;
295 static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd,
296 uint16_t port, uint32_t *data)
298 struct sysret sysret = cap_invoke2(iocap, cmd, port);
300 if (err_is_ok(sysret.error)) {
301 assert(data != NULL);
302 *data = sysret.value;
307 static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd,
308 uint16_t port, uint32_t data)
310 return cap_invoke3(iocap, cmd, port, data).error;
314 * \brief Setup a dispatcher, possibly making it runnable
316 * \param dispatcher Address of dispatcher capability
317 * \param domdispatcher Address of existing dispatcher for domain ID
318 * \param cspace_root Root of CSpace for new dispatcher
319 * \param cspace_root_bits Number of valid bits in cspace_root
320 * \param vspace_root Root of VSpace for new dispatcher
321 * \param dispatcher_frame Frame capability for dispatcher structure
322 * \param run Make runnable if true
324 * Any arguments of CPTR_NULL are ignored.
328 static inline errval_t
329 invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher,
330 struct capref cspace, struct capref vspace,
331 struct capref dispframe, bool run)
333 uint8_t root_vbits = get_cap_valid_bits(cspace);
334 capaddr_t root_caddr = get_cap_addr(cspace) >> (CPTR_BITS - root_vbits);
335 capaddr_t vtree_caddr = get_cap_addr(vspace);
336 capaddr_t disp_caddr = get_cap_addr(dispframe);
337 capaddr_t dd_caddr = get_cap_addr(domdispatcher);
339 return cap_invoke7(dispatcher, DispatcherCmd_Setup, root_caddr,
340 root_vbits, vtree_caddr, disp_caddr, run,
345 * \brief Execute vmread on the VMCS of the VM guest DCB
347 * The VMCS must be current and active.
349 * \param dcb Dispatcher capability
350 * \param encoding Encoding of the field to read from the VMCS
351 * \param addr The address to write the value of the field to.
353 static inline errval_t invoke_dispatcher_vmread(struct capref dispatcher,
357 return cap_invoke3(dispatcher, DispatcherCmd_Vmread,
358 encoding, (uintptr_t)addr).error;
362 * \brief Execute vmwrite on the VMCS of the VM guest DCB
364 * The VMCS must be current and active.
366 * \param dcb Dispatcher capability
367 * \param encoding Encoding of the field to write to the VMCS.
368 * \param value Value of the field to write.
371 static inline errval_t invoke_dispatcher_vmwrite(struct capref dispatcher,
375 return cap_invoke3(dispatcher, DispatcherCmd_Vmwrite,
376 encoding, value).error;
380 * \brief Execute vmptrld on the VMCS of the VM guest DCB
382 * \param dcb Dispatcher capability
384 static inline errval_t invoke_dispatcher_vmptrld(struct capref dispatcher)
386 return cap_invoke1(dispatcher, DispatcherCmd_Vmptrld).error;
390 * \brief Execute vmclear on the VMCS of the VM guest DCB
392 * \param dcb Dispatcher capability
394 static inline errval_t invoke_dispatcher_vmclear(struct capref dispatcher)
396 return cap_invoke1(dispatcher, DispatcherCmd_Vmclear).error;
400 * \brief Setup a VM guest DCB
402 * \param dcb Dispatcher capability
404 static inline errval_t
405 invoke_dispatcher_setup_guest(struct capref dispatcher,
406 struct capref ep_cap,
408 struct capref vmkit_guest,
409 struct capref guest_control_cap)
411 return cap_invoke5(dispatcher, DispatcherCmd_SetupGuest,
412 get_cap_addr(ep_cap), get_cap_addr(vnode),
413 get_cap_addr(vmkit_guest),
414 get_cap_addr(guest_control_cap)).error;
417 static inline errval_t invoke_irqvector_connect(struct capref irqcap, struct capref epcap)
419 struct sysret ret = cap_invoke2(irqcap, IRQVectorCmd_Connect, get_cap_addr(epcap));
423 static inline errval_t invoke_irqvector_get_vector(struct capref irqcap, uint32_t * out_vec)
425 struct sysret ret = cap_invoke1(irqcap, IRQVectorCmd_GetVector);
426 *out_vec = ret.value;
430 static inline errval_t invoke_irq_get_vector(struct capref irqcap, uint32_t * out_vec)
432 struct sysret ret = cap_invoke1(irqcap, IRQCmd_GetVector);
433 *out_vec = ret.value;
437 static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
439 uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
440 capaddr_t dcn_addr = get_cnode_addr(dest_cap);
441 struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
448 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
450 struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc);
451 if (err_is_ok(ret.error)) {
459 static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq,
462 return cap_invoke3(irqcap, IRQTableCmd_Set, irq, get_cap_addr(ep)).error;
465 static inline errval_t invoke_irqtable_delete(struct capref irqcap, int irq)
467 return cap_invoke2(irqcap, IRQTableCmd_Delete, irq).error;
471 * \brief do a kernel cap invocation to get the core id
473 static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap,
476 assert(core_id != NULL);
478 struct sysret sysret = cap_invoke1(kern_cap, KernelCmd_Get_core_id);
479 if (sysret.error == SYS_ERR_OK) {
480 *core_id = sysret.value;
485 static inline errval_t invoke_dispatcher_dump_ptables(struct capref dispcap)
487 return cap_invoke1(dispcap, DispatcherCmd_DumpPTables).error;
490 static inline errval_t invoke_dispatcher_dump_capabilities(struct capref dispcap)
492 return cap_invoke1(dispcap, DispatcherCmd_DumpCapabilities).error;
495 static inline errval_t invoke_perfmon_activate(struct capref perfmon_cap,
496 uint8_t event, uint8_t perf_umask,
497 bool kernel, uint8_t counter_id,
498 uint64_t counter_value,
501 return cap_invoke7(perfmon_cap, PerfmonCmd_Activate,
502 event, perf_umask, counter_id, kernel,
503 counter_value, ep_addr).error;
506 static inline errval_t invoke_perfmon_write(struct capref perfmon_cap,
508 uint64_t counter_value)
510 return cap_invoke3(perfmon_cap, PerfmonCmd_Write, counter_id, counter_value).error;
513 static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap)
515 return cap_invoke1(perfmon_cap, PerfmonCmd_Deactivate).error;
518 static inline errval_t
519 invoke_dispatcher_properties(struct capref dispatcher,
520 enum task_type type, unsigned long deadline,
521 unsigned long wcet, unsigned long period,
522 unsigned long release, unsigned short weight)
524 return cap_invoke7(dispatcher, DispatcherCmd_Properties, type, deadline,
525 wcet, period, release, weight).error;
528 static inline errval_t invoke_ipi_notify_send(struct capref notify_cap)
530 return cap_invoke1(notify_cap, NotifyCmd_Send).error;
534 * \brief Return the system-wide unique ID of the passed ID capability.
536 * \param idcap ID capability to invoke.
537 * \param id Filled-in with system-wide unique ID of ID cap.
541 static inline errval_t invoke_idcap_identify(struct capref idcap,
546 struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify);
548 if (err_is_ok(sysret.error)) {
555 static inline errval_t invoke_send_init_ipi(struct capref ipi_cap, coreid_t core_id)
557 return cap_invoke2(ipi_cap, IPICmd_Send_Init,
561 static inline errval_t invoke_send_start_ipi(struct capref ipi_cap, coreid_t core_id, forvaddr_t entry)
563 return cap_invoke3(ipi_cap, IPICmd_Send_Start,
564 core_id, entry).error;
567 static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global)
569 struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys);
570 if (err_is_ok(sr.error)) {