T191: Implement prototype for new retype
[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 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)
94 {
95     assert(cap != CPTR_NULL);
96     return cap_invoke9(root, CNodeCmd_Retype, cap, offset, newtype, objsize,
97                        count, to, slot, bits).error;
98 }
99
100 /**
101  * \brief Create a capability.
102  *
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'.
106  *
107  * See also cap_create(), which wraps this.
108  *
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
114  *                        placed into.
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'.
117  *
118  * \return Error code
119  */
120 static inline errval_t invoke_cnode_create(struct capref root,
121                                            enum objtype type, uint8_t objbits,
122                                            capaddr_t dest_cnode_cptr,
123                                            capaddr_t dest_slot,
124                                            uint8_t dest_vbits)
125 {
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;
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  */
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,
154                                          uint64_t param2)
155 {
156     return cap_invoke8(root, CNodeCmd_Mint, to, slot, from, tobits, frombits,
157                        param1, param2).error;
158 }
159
160 /**
161  * \brief Copy a capability.
162  *
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.
166  *
167  * See also cap_copy(), which wraps this.
168  *
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'.
175  *
176  * \return Error code
177  */
178 static inline errval_t invoke_cnode_copy(struct capref root, capaddr_t to,
179                                          capaddr_t slot, capaddr_t from, int tobits,
180                                          int frombits)
181 {
182     return cap_invoke6(root, CNodeCmd_Copy, to, slot, from,
183                        tobits, frombits).error;
184 }
185
186 /**
187  * \brief Delete a capability.
188  *
189  * Delete the capability pointed to by 'cap', with 'bits' address bits
190  * of it valid, from the address space rooted at 'root'.
191  *
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'.
195  *
196  * \return Error code
197  */
198 static inline errval_t invoke_cnode_delete(struct capref root, capaddr_t cap,
199                                            int bits)
200 {
201     return cap_invoke3(root, CNodeCmd_Delete, cap, bits).error;
202 }
203
204 static inline errval_t invoke_cnode_revoke(struct capref root, capaddr_t cap,
205                                            int bits)
206 {
207     return cap_invoke3(root, CNodeCmd_Revoke, cap, bits).error;
208 }
209
210 static inline errval_t invoke_cnode_get_state(struct capref root, capaddr_t cap,
211                                               int bits, distcap_state_t *ret)
212 {
213     struct sysret sysret = cap_invoke3(root, CNodeCmd_GetState, cap, bits);
214
215     assert(ret != NULL);
216     if (err_is_ok(sysret.error)) {
217         *ret = sysret.value;
218     }
219     else {
220         *ret = 0;
221     }
222     return sysret.error;
223 }
224
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)
230 {
231     return cap_invoke10(ptable, VNodeCmd_Map, slot, src, frombits, flags,
232                         offset, pte_count, mcnaddr, mcnbits, mapping_slot).error;
233 }
234
235 static inline errval_t invoke_vnode_unmap(struct capref cap,
236                                           capaddr_t mapping_addr, int bits)
237 {
238     return cap_invoke3(cap, VNodeCmd_Unmap, mapping_addr, bits).error;
239 }
240
241 /**
242  * \brief Return the physical address and size of a frame capability
243  *
244  * \param frame    CSpace address of frame capability
245  * \param ret      frame_identity struct filled in with relevant data
246  *
247  * \return Error code
248  */
249 static inline errval_t invoke_frame_identify(struct capref frame,
250                                              struct frame_identity *ret)
251 {
252     assert(ret != NULL);
253
254     struct sysret sysret = cap_invoke2(frame, FrameCmd_Identify, (uintptr_t)ret);
255
256     if (err_is_ok(sysret.error)) {
257         return sysret.error;
258     }
259
260     ret->base = 0;
261     ret->bytes = 0;
262     return sysret.error;
263 }
264
265 static inline errval_t invoke_vnode_identify(struct capref vnode,
266                                              struct vnode_identity *ret)
267 {
268     struct sysret sysret = cap_invoke1(vnode, VNodeCmd_Identify);
269
270     assert(ret != NULL);
271     if (err_is_ok(sysret.error)) {
272         ret->base = sysret.value & (~BASE_PAGE_MASK);
273         ret->type = sysret.value & BASE_PAGE_MASK;
274         return sysret.error;
275     }
276
277     ret->base = 0;
278     ret->type = 0;
279     return sysret.error;
280 }
281
282 /**
283  * \brief Modify mapping flags on parts of a mapping
284  *
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
291  *
292  * \return Error code
293  */
294 static inline errval_t invoke_mapping_modify_flags(struct capref mapping,
295                                                    size_t offset,
296                                                    size_t pages,
297                                                    size_t flags,
298                                                    genvaddr_t va_hint)
299 {
300     return cap_invoke5(mapping, MappingCmd_Modify, offset,
301                        pages, flags, va_hint).error;
302 }
303
304 static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd,
305                                        uint16_t port, uint32_t *data)
306 {
307     struct sysret sysret = cap_invoke2(iocap, cmd, port);
308
309     if (err_is_ok(sysret.error)) {
310         assert(data != NULL);
311         *data = sysret.value;
312     }
313     return sysret.error;
314 }
315
316 static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd,
317                                         uint16_t port, uint32_t data)
318 {
319     return cap_invoke3(iocap, cmd, port, data).error;
320 }
321
322 /**
323  * \brief Setup a dispatcher, possibly making it runnable
324  *
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
332  *
333  * Any arguments of CPTR_NULL are ignored.
334  *
335  * \return Error code
336  */
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)
341 {
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);
347
348     return cap_invoke7(dispatcher, DispatcherCmd_Setup, root_caddr,
349                        root_vbits, vtree_caddr, disp_caddr, run,
350                        dd_caddr).error;
351 }
352
353 /**
354  * \brief Execute vmread on the VMCS of the VM guest DCB
355  *
356  * The VMCS must be current and active.
357  *
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.
361  */
362 static inline errval_t invoke_dispatcher_vmread(struct capref dispatcher, 
363                                                 uintptr_t encoding, 
364                                                 lvaddr_t *addr)
365 {
366     return cap_invoke3(dispatcher, DispatcherCmd_Vmread, 
367                        encoding, (uintptr_t)addr).error; 
368 }
369
370 /**
371  * \brief Execute vmwrite on the VMCS of the VM guest DCB
372  *
373  * The VMCS must be current and active.
374  *
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.
378  */
379
380 static inline errval_t invoke_dispatcher_vmwrite(struct capref dispatcher, 
381                                                  uintptr_t encoding, 
382                                                  uintptr_t value)
383 {
384     return cap_invoke3(dispatcher, DispatcherCmd_Vmwrite, 
385                        encoding, value).error; 
386 }
387
388 /**
389  * \brief Execute vmptrld on the VMCS of the VM guest DCB
390  *
391  * \param dcb       Dispatcher capability
392  */
393 static inline errval_t invoke_dispatcher_vmptrld(struct capref dispatcher)
394 {
395     return cap_invoke1(dispatcher, DispatcherCmd_Vmptrld).error; 
396 }
397
398 /**
399  * \brief Execute vmclear on the VMCS of the VM guest DCB
400  *   
401  * \param dcb       Dispatcher capability
402  */
403 static inline errval_t invoke_dispatcher_vmclear(struct capref dispatcher)
404 {
405     return cap_invoke1(dispatcher, DispatcherCmd_Vmclear).error; 
406 }
407
408 /**
409  * \brief Setup a VM guest DCB
410  *
411  * \param dcb       Dispatcher capability
412  */
413 static inline errval_t
414 invoke_dispatcher_setup_guest(struct capref dispatcher,
415                               struct capref ep_cap,
416                               struct capref vnode,
417                               struct capref vmkit_guest,
418                               struct capref guest_control_cap)
419 {
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;
424 }
425
426 static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap)
427 {
428     struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap));
429     return ret.error;
430 }
431
432 static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t * out_vec)
433 {
434     struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector);
435     *out_vec = ret.value;
436     return ret.error;
437 }
438
439 static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
440 {
441     struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
442     *out_vec = ret.value;
443     return ret.error;
444 }
445
446 static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
447 {
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);
451     return ret.error;
452 }
453
454 /**
455  * Deprecated. Use invoke_irqtable_alloc_dest_cap
456  */
457 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
458 {
459     struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc);
460     if (err_is_ok(ret.error)) {
461         *retirq = ret.value;
462     } else {
463         *retirq = 0;
464     }
465     return ret.error;
466 }
467
468 static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq,
469                                            struct capref ep)
470 {
471     return cap_invoke3(irqcap, IRQTableCmd_Set, irq, get_cap_addr(ep)).error;
472 }
473
474 static inline errval_t invoke_irqtable_delete(struct capref irqcap, int irq)
475 {
476     return cap_invoke2(irqcap, IRQTableCmd_Delete, irq).error;
477 }
478
479 /**
480  * \brief do a kernel cap invocation to get the core id
481  */
482 static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap,
483                                                  coreid_t *core_id)
484 {
485     assert(core_id != NULL);
486
487     struct sysret sysret = cap_invoke1(kern_cap, KernelCmd_Get_core_id);
488     if (sysret.error == SYS_ERR_OK) {
489         *core_id = sysret.value;
490     }
491     return sysret.error;
492 }
493
494 static inline errval_t invoke_dispatcher_dump_ptables(struct capref dispcap)
495 {
496     return cap_invoke1(dispcap, DispatcherCmd_DumpPTables).error;
497 }
498
499 static inline errval_t invoke_dispatcher_dump_capabilities(struct capref dispcap)
500 {
501     return cap_invoke1(dispcap, DispatcherCmd_DumpCapabilities).error;
502 }
503
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,
508                                                capaddr_t ep_addr)
509 {
510     return cap_invoke7(perfmon_cap, PerfmonCmd_Activate,
511                        event, perf_umask, counter_id, kernel,
512                        counter_value, ep_addr).error;
513 }
514
515 static inline errval_t invoke_perfmon_write(struct capref perfmon_cap,
516                                                   uint8_t counter_id,
517                                                   uint64_t counter_value)
518 {
519     return cap_invoke3(perfmon_cap, PerfmonCmd_Write, counter_id, counter_value).error;
520 }
521
522 static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap)
523 {
524     return cap_invoke1(perfmon_cap, PerfmonCmd_Deactivate).error;
525 }
526
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)
532 {
533     return cap_invoke7(dispatcher, DispatcherCmd_Properties, type, deadline,
534                        wcet, period, release, weight).error;
535 }
536
537 static inline errval_t invoke_ipi_notify_send(struct capref notify_cap)
538 {
539     return cap_invoke1(notify_cap, NotifyCmd_Send).error;
540 }
541
542 /**
543  * \brief Return the system-wide unique ID of the passed ID capability.
544  *
545  * \param idcap ID capability to invoke.
546  * \param id    Filled-in with system-wide unique ID of ID cap.
547  *
548  * \return      Error code
549  */
550 static inline errval_t invoke_idcap_identify(struct capref idcap,
551                                              idcap_id_t *id)
552 {
553     assert(id != NULL);
554
555     struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify);
556
557     if (err_is_ok(sysret.error)) {
558         *id = sysret.value;
559     }
560
561     return sysret.error;
562 }
563
564 static inline errval_t invoke_send_init_ipi(struct capref ipi_cap, coreid_t core_id)
565 {
566     return cap_invoke2(ipi_cap, IPICmd_Send_Init,
567                        core_id).error;
568 }
569
570 static inline errval_t invoke_send_start_ipi(struct capref ipi_cap, coreid_t core_id, forvaddr_t entry)
571 {
572     return cap_invoke3(ipi_cap, IPICmd_Send_Start,
573                        core_id, entry).error;
574 }
575
576 static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global)
577
578     struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys);
579     if (err_is_ok(sr.error)) {
580         *global = sr.value;
581     }
582
583     return sr.error;
584 }
585
586 #endif