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