Merge branch 'arrakis'
[barrelfish] / include / arch / x86_64 / barrelfish / invocations_arch.h
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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #ifndef INVOCATIONS_ARCH_H
16 #define INVOCATIONS_ARCH_H
17
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>
23
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,
29                                        uintptr_t arg10)
30 {
31     uint8_t invoke_bits = get_cap_valid_bits(to);
32     capaddr_t invoke_cptr = get_cap_addr(to) >> (CPTR_BITS - invoke_bits);
33
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,
37                    arg10);
38 }
39
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)
60
61
62 /**
63  * \brief Retype a capability.
64  *
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.
68  *
69  * See also cap_retype(), which wraps this.
70  *
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'.
78  *
79  * \return Error code
80  */
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)
84 {
85     assert(cap != CPTR_NULL);
86     return cap_invoke7(root, CNodeCmd_Retype, cap, newtype, objbits, to,
87                        slot, bits).error;
88 }
89
90 /**
91  * \brief Create a capability.
92  *
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'.
96  *
97  * See also cap_create(), which wraps this.
98  *
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
104  *                        placed into.
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'.
107  *
108  * \return Error code
109  */
110 static inline errval_t invoke_cnode_create(struct capref root,
111                                            enum objtype type, uint8_t objbits,
112                                            capaddr_t dest_cnode_cptr,
113                                            capaddr_t dest_slot,
114                                            uint8_t dest_vbits)
115 {
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;
119 }
120
121 /**
122  * \brief "Mint" a capability.
123  *
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.
127  *
128  * See also cap_mint(), which wraps this.
129  *
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.
138  *
139  * \return Error code
140  */
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,
144                                          uint64_t param2)
145 {
146     return cap_invoke8(root, CNodeCmd_Mint, to, slot, from, tobits, frombits,
147                        param1, param2).error;
148 }
149
150 /**
151  * \brief Copy a capability.
152  *
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.
156  *
157  * See also cap_copy(), which wraps this.
158  *
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'.
165  *
166  * \return Error code
167  */
168 static inline errval_t invoke_cnode_copy(struct capref root, capaddr_t to,
169                                          capaddr_t slot, capaddr_t from, int tobits,
170                                          int frombits)
171 {
172     return cap_invoke6(root, CNodeCmd_Copy, to, slot, from,
173                        tobits, frombits).error;
174 }
175
176 /**
177  * \brief Delete a capability.
178  *
179  * Delete the capability pointed to by 'cap', with 'bits' address bits
180  * of it valid, from the address space rooted at 'root'.
181  *
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'.
185  *
186  * \return Error code
187  */
188 static inline errval_t invoke_cnode_delete(struct capref root, capaddr_t cap,
189                                            int bits)
190 {
191     return cap_invoke3(root, CNodeCmd_Delete, cap, bits).error;
192 }
193
194 static inline errval_t invoke_cnode_revoke(struct capref root, capaddr_t cap,
195                                            int bits)
196 {
197     return cap_invoke3(root, CNodeCmd_Revoke, cap, bits).error;
198 }
199
200 static inline errval_t invoke_cnode_get_state(struct capref root, capaddr_t cap,
201                                               int bits, distcap_state_t *ret)
202 {
203     struct sysret sysret = cap_invoke3(root, CNodeCmd_GetState, cap, bits);
204
205     assert(ret != NULL);
206     if (err_is_ok(sysret.error)) {
207         *ret = sysret.value;
208     }
209     else {
210         *ret = 0;
211     }
212     return sysret.error;
213 }
214
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 {
219     return cap_invoke7(ptable, VNodeCmd_Map, slot, src, frombits, flags, offset, pte_count).error;
220 }
221
222 static inline errval_t invoke_vnode_unmap(struct capref cap, capaddr_t mapping_addr,
223                                           int bits, size_t entry, size_t num_pages)
224 {
225     return cap_invoke5(cap, VNodeCmd_Unmap, mapping_addr, bits, entry, num_pages).error;
226 }
227
228 /**
229  * \brief Return the physical address and size of a frame capability
230  *
231  * \param frame    CSpace address of frame capability
232  * \param ret      frame_identity struct filled in with relevant data
233  *
234  * \return Error code
235  */
236 static inline errval_t invoke_frame_identify(struct capref frame,
237                                              struct frame_identity *ret)
238 {
239     struct sysret sysret = cap_invoke1(frame, FrameCmd_Identify);
240
241     assert(ret != NULL);
242     if (err_is_ok(sysret.error)) {
243         ret->base = sysret.value & (~BASE_PAGE_MASK);
244         ret->bits = sysret.value & BASE_PAGE_MASK;
245         return sysret.error;
246     }
247
248     ret->base = 0;
249     ret->bits = 0;
250     return sysret.error;
251 }
252
253 static inline errval_t invoke_vnode_identify(struct capref vnode,
254                                              struct vnode_identity *ret)
255 {
256     struct sysret sysret = cap_invoke1(vnode, VNodeCmd_Identify);
257
258     assert(ret != NULL);
259     if (err_is_ok(sysret.error)) {
260         ret->base = sysret.value & (~BASE_PAGE_MASK);
261         ret->type = sysret.value & BASE_PAGE_MASK;
262         return sysret.error;
263     }
264
265     ret->base = 0;
266     ret->type = 0;
267     return sysret.error;
268 }
269
270 /**
271  * \brief Modify mapping flags on parts of a mapped frame
272  *
273  * \param frame    CSpace address of frame capability
274  * \param off      Offset (in #pages) of the first page to get new set of flags
275  *                 from the first page in the mapping identified by `frame`
276  * \param pages    Number of pages that should get new set of flags
277  * \param flags    New set of flags
278  * \param va_hint  Hint for selective TLB flushing
279  *
280  * \return Error code
281  */
282 static inline errval_t invoke_frame_modify_flags(struct capref frame,
283                                                  size_t offset,
284                                                  size_t pages,
285                                                  size_t flags,
286                                                  genvaddr_t va_hint)
287 {
288     return cap_invoke5(frame, FrameCmd_ModifyFlags, offset,
289                        pages, flags, va_hint).error;
290 }
291
292 static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd,
293                                        uint16_t port, uint32_t *data)
294 {
295     struct sysret sysret = cap_invoke2(iocap, cmd, port);
296
297     if (err_is_ok(sysret.error)) {
298         assert(data != NULL);
299         *data = sysret.value;
300     }
301     return sysret.error;
302 }
303
304 static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd,
305                                         uint16_t port, uint32_t data)
306 {
307     return cap_invoke3(iocap, cmd, port, data).error;
308 }
309
310 /**
311  * \brief Setup a dispatcher, possibly making it runnable
312  *
313  * \param dispatcher    Address of dispatcher capability
314  * \param domdispatcher Address of existing dispatcher for domain ID
315  * \param cspace_root   Root of CSpace for new dispatcher
316  * \param cspace_root_bits  Number of valid bits in cspace_root
317  * \param vspace_root   Root of VSpace for new dispatcher
318  * \param dispatcher_frame Frame capability for dispatcher structure
319  * \param run           Make runnable if true
320  *
321  * Any arguments of CPTR_NULL are ignored.
322  *
323  * \return Error code
324  */
325 static inline errval_t
326 invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher,
327                   struct capref cspace, struct capref vspace,
328                   struct capref dispframe, bool run)
329 {
330     uint8_t root_vbits = get_cap_valid_bits(cspace);
331     capaddr_t root_caddr = get_cap_addr(cspace) >> (CPTR_BITS - root_vbits);
332     capaddr_t vtree_caddr = get_cap_addr(vspace);
333     capaddr_t disp_caddr = get_cap_addr(dispframe);
334     capaddr_t dd_caddr = get_cap_addr(domdispatcher);
335
336     return cap_invoke7(dispatcher, DispatcherCmd_Setup, root_caddr,
337                        root_vbits, vtree_caddr, disp_caddr, run,
338                        dd_caddr).error;
339 }
340
341 /**
342  * \brief Execute vmread on the VMCS of the VM guest DCB
343  *
344  * The VMCS must be current and active.
345  *
346  * \param dcb       Dispatcher capability
347  * \param encoding  Encoding of the field to read from the VMCS
348  * \param addr      The address to write the value of the field to.
349  */
350 static inline errval_t invoke_dispatcher_vmread(struct capref dispatcher, 
351                                                 uintptr_t encoding, 
352                                                 lvaddr_t *addr)
353 {
354     return cap_invoke3(dispatcher, DispatcherCmd_Vmread, 
355                        encoding, (uintptr_t)addr).error; 
356 }
357
358 /**
359  * \brief Execute vmwrite on the VMCS of the VM guest DCB
360  *
361  * The VMCS must be current and active.
362  *
363  * \param dcb       Dispatcher capability
364  * \param encoding  Encoding of the field to write to the VMCS.
365  * \param value     Value of the field to write.
366  */
367
368 static inline errval_t invoke_dispatcher_vmwrite(struct capref dispatcher, 
369                                                  uintptr_t encoding, 
370                                                  uintptr_t value)
371 {
372     return cap_invoke3(dispatcher, DispatcherCmd_Vmwrite, 
373                        encoding, value).error; 
374 }
375
376 /**
377  * \brief Execute vmptrld on the VMCS of the VM guest DCB
378  *
379  * \param dcb       Dispatcher capability
380  */
381 static inline errval_t invoke_dispatcher_vmptrld(struct capref dispatcher)
382 {
383     return cap_invoke1(dispatcher, DispatcherCmd_Vmptrld).error; 
384 }
385
386 /**
387  * \brief Execute vmclear on the VMCS of the VM guest DCB
388  *   
389  * \param dcb       Dispatcher capability
390  */
391 static inline errval_t invoke_dispatcher_vmclear(struct capref dispatcher)
392 {
393     return cap_invoke1(dispatcher, DispatcherCmd_Vmclear).error; 
394 }
395
396 /**
397  * \brief Setup a VM guest DCB
398  *
399  * \param dcb       Dispatcher capability
400  */
401 static inline errval_t
402 invoke_dispatcher_setup_guest(struct capref dispatcher,
403                               struct capref ep_cap,
404                               struct capref vnode,
405                               struct capref vmkit_guest,
406                               struct capref guest_control_cap)
407 {
408     return cap_invoke5(dispatcher, DispatcherCmd_SetupGuest,
409                        get_cap_addr(ep_cap), get_cap_addr(vnode),
410                        get_cap_addr(vmkit_guest),
411                        get_cap_addr(guest_control_cap)).error;
412 }
413
414
415 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
416 {
417     struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc);
418     if (err_is_ok(ret.error)) {
419         *retirq = ret.value;
420     } else {
421         *retirq = 0;
422     }
423     return ret.error;
424 }
425
426 static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq,
427                                            struct capref ep)
428 {
429     return cap_invoke3(irqcap, IRQTableCmd_Set, irq, get_cap_addr(ep)).error;
430 }
431
432 static inline errval_t invoke_irqtable_delete(struct capref irqcap, int irq)
433 {
434     return cap_invoke2(irqcap, IRQTableCmd_Delete, irq).error;
435 }
436
437 /**
438  * \brief do a kernel cap invocation to get the core id
439  */
440 static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap,
441                                                  coreid_t *core_id)
442 {
443     assert(core_id != NULL);
444
445     struct sysret sysret = cap_invoke1(kern_cap, KernelCmd_Get_core_id);
446     if (sysret.error == SYS_ERR_OK) {
447         *core_id = sysret.value;
448     }
449     return sysret.error;
450 }
451
452 static inline errval_t invoke_dispatcher_dump_ptables(struct capref dispcap)
453 {
454     return cap_invoke1(dispcap, DispatcherCmd_DumpPTables).error;
455 }
456
457 static inline errval_t invoke_dispatcher_dump_capabilities(struct capref dispcap)
458 {
459     return cap_invoke1(dispcap, DispatcherCmd_DumpCapabilities).error;
460 }
461
462 static inline errval_t invoke_perfmon_activate(struct capref perfmon_cap,
463                                                uint8_t event, uint8_t perf_umask,
464                                                bool kernel, uint8_t counter_id,
465                                                uint64_t counter_value,
466                                                capaddr_t ep_addr)
467 {
468     return cap_invoke7(perfmon_cap, PerfmonCmd_Activate,
469                        event, perf_umask, counter_id, kernel,
470                        counter_value, ep_addr).error;
471 }
472
473 static inline errval_t invoke_perfmon_write(struct capref perfmon_cap,
474                                                   uint8_t counter_id,
475                                                   uint64_t counter_value)
476 {
477     return cap_invoke3(perfmon_cap, PerfmonCmd_Write, counter_id, counter_value).error;
478 }
479
480 static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap)
481 {
482     return cap_invoke1(perfmon_cap, PerfmonCmd_Deactivate).error;
483 }
484
485 static inline errval_t
486 invoke_dispatcher_properties(struct capref dispatcher,
487                              enum task_type type, unsigned long deadline,
488                              unsigned long wcet, unsigned long period,
489                              unsigned long release, unsigned short weight)
490 {
491     return cap_invoke7(dispatcher, DispatcherCmd_Properties, type, deadline,
492                        wcet, period, release, weight).error;
493 }
494
495 static inline errval_t invoke_ipi_notify_send(struct capref notify_cap)
496 {
497     return cap_invoke1(notify_cap, NotifyCmd_Send).error;
498 }
499
500 /**
501  * \brief Return the system-wide unique ID of the passed ID capability.
502  *
503  * \param idcap ID capability to invoke.
504  * \param id    Filled-in with system-wide unique ID of ID cap.
505  *
506  * \return      Error code
507  */
508 static inline errval_t invoke_idcap_identify(struct capref idcap,
509                                              idcap_id_t *id)
510 {
511     assert(id != NULL);
512
513     struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify);
514
515     if (err_is_ok(sysret.error)) {
516         *id = sysret.value;
517     }
518
519     return sysret.error;
520 }
521
522 static inline errval_t invoke_send_init_ipi(struct capref ipi_cap, coreid_t core_id)
523 {
524     return cap_invoke2(ipi_cap, IPICmd_Send_Init,
525                        core_id).error;
526 }
527
528 static inline errval_t invoke_send_start_ipi(struct capref ipi_cap, coreid_t core_id, forvaddr_t entry)
529 {
530     return cap_invoke3(ipi_cap, IPICmd_Send_Start,
531                        core_id, entry).error;
532 }
533
534 static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global)
535
536     struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys);
537     if (err_is_ok(sr.error)) {
538         *global = sr.value;
539     }
540
541     return sr.error;
542 }
543
544 #endif