IRQ: added irq source capability and make the inthandler setup use it
[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                                         capaddr_t mcnaddr, int mcnbits,
219                                         cslot_t mapping_slot)
220 {
221     return cap_invoke10(ptable, VNodeCmd_Map, slot, src, frombits, flags,
222                         offset, pte_count, mcnaddr, mcnbits, mapping_slot).error;
223 }
224
225 static inline errval_t invoke_vnode_unmap(struct capref cap,
226                                           capaddr_t mapping_addr, int bits)
227 {
228     return cap_invoke3(cap, VNodeCmd_Unmap, mapping_addr, bits).error;
229 }
230
231 /**
232  * \brief Return the physical address and size of a frame capability
233  *
234  * \param frame    CSpace address of frame capability
235  * \param ret      frame_identity struct filled in with relevant data
236  *
237  * \return Error code
238  */
239 static inline errval_t invoke_frame_identify(struct capref frame,
240                                              struct frame_identity *ret)
241 {
242     struct sysret sysret = cap_invoke1(frame, FrameCmd_Identify);
243
244     assert(ret != NULL);
245     if (err_is_ok(sysret.error)) {
246         ret->base = sysret.value & (~BASE_PAGE_MASK);
247         ret->bits = sysret.value & BASE_PAGE_MASK;
248         return sysret.error;
249     }
250
251     ret->base = 0;
252     ret->bits = 0;
253     return sysret.error;
254 }
255
256 static inline errval_t invoke_vnode_identify(struct capref vnode,
257                                              struct vnode_identity *ret)
258 {
259     struct sysret sysret = cap_invoke1(vnode, VNodeCmd_Identify);
260
261     assert(ret != NULL);
262     if (err_is_ok(sysret.error)) {
263         ret->base = sysret.value & (~BASE_PAGE_MASK);
264         ret->type = sysret.value & BASE_PAGE_MASK;
265         return sysret.error;
266     }
267
268     ret->base = 0;
269     ret->type = 0;
270     return sysret.error;
271 }
272
273 /**
274  * \brief Modify mapping flags on parts of a mapping
275  *
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
282  *
283  * \return Error code
284  */
285 static inline errval_t invoke_mapping_modify_flags(struct capref mapping,
286                                                    size_t offset,
287                                                    size_t pages,
288                                                    size_t flags,
289                                                    genvaddr_t va_hint)
290 {
291     return cap_invoke5(mapping, MappingCmd_Modify, offset,
292                        pages, flags, va_hint).error;
293 }
294
295 static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd,
296                                        uint16_t port, uint32_t *data)
297 {
298     struct sysret sysret = cap_invoke2(iocap, cmd, port);
299
300     if (err_is_ok(sysret.error)) {
301         assert(data != NULL);
302         *data = sysret.value;
303     }
304     return sysret.error;
305 }
306
307 static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd,
308                                         uint16_t port, uint32_t data)
309 {
310     return cap_invoke3(iocap, cmd, port, data).error;
311 }
312
313 /**
314  * \brief Setup a dispatcher, possibly making it runnable
315  *
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
323  *
324  * Any arguments of CPTR_NULL are ignored.
325  *
326  * \return Error code
327  */
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)
332 {
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);
338
339     return cap_invoke7(dispatcher, DispatcherCmd_Setup, root_caddr,
340                        root_vbits, vtree_caddr, disp_caddr, run,
341                        dd_caddr).error;
342 }
343
344 /**
345  * \brief Execute vmread on the VMCS of the VM guest DCB
346  *
347  * The VMCS must be current and active.
348  *
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.
352  */
353 static inline errval_t invoke_dispatcher_vmread(struct capref dispatcher, 
354                                                 uintptr_t encoding, 
355                                                 lvaddr_t *addr)
356 {
357     return cap_invoke3(dispatcher, DispatcherCmd_Vmread, 
358                        encoding, (uintptr_t)addr).error; 
359 }
360
361 /**
362  * \brief Execute vmwrite on the VMCS of the VM guest DCB
363  *
364  * The VMCS must be current and active.
365  *
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.
369  */
370
371 static inline errval_t invoke_dispatcher_vmwrite(struct capref dispatcher, 
372                                                  uintptr_t encoding, 
373                                                  uintptr_t value)
374 {
375     return cap_invoke3(dispatcher, DispatcherCmd_Vmwrite, 
376                        encoding, value).error; 
377 }
378
379 /**
380  * \brief Execute vmptrld on the VMCS of the VM guest DCB
381  *
382  * \param dcb       Dispatcher capability
383  */
384 static inline errval_t invoke_dispatcher_vmptrld(struct capref dispatcher)
385 {
386     return cap_invoke1(dispatcher, DispatcherCmd_Vmptrld).error; 
387 }
388
389 /**
390  * \brief Execute vmclear on the VMCS of the VM guest DCB
391  *   
392  * \param dcb       Dispatcher capability
393  */
394 static inline errval_t invoke_dispatcher_vmclear(struct capref dispatcher)
395 {
396     return cap_invoke1(dispatcher, DispatcherCmd_Vmclear).error; 
397 }
398
399 /**
400  * \brief Setup a VM guest DCB
401  *
402  * \param dcb       Dispatcher capability
403  */
404 static inline errval_t
405 invoke_dispatcher_setup_guest(struct capref dispatcher,
406                               struct capref ep_cap,
407                               struct capref vnode,
408                               struct capref vmkit_guest,
409                               struct capref guest_control_cap)
410 {
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;
415 }
416
417 static inline errval_t invoke_irqvector_connect(struct capref irqcap, struct capref epcap)
418 {
419     struct sysret ret = cap_invoke2(irqcap, IRQVectorCmd_Connect, get_cap_addr(epcap));
420     return ret.error;
421 }
422
423 static inline errval_t invoke_irqvector_get_vector(struct capref irqcap, uint32_t * out_vec)
424 {
425     struct sysret ret = cap_invoke1(irqcap, IRQVectorCmd_GetVector);
426     *out_vec = ret.value;
427     return ret.error;
428 }
429
430 static inline errval_t invoke_irq_get_vector(struct capref irqcap, uint32_t * out_vec)
431 {
432     struct sysret ret = cap_invoke1(irqcap, IRQCmd_GetVector);
433     *out_vec = ret.value;
434     return ret.error;
435 }
436
437 static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
438 {
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);
442     return ret.error;
443 }
444
445 /**
446  * Deprecated. Use
447  */
448 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
449 {
450     struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc);
451     if (err_is_ok(ret.error)) {
452         *retirq = ret.value;
453     } else {
454         *retirq = 0;
455     }
456     return ret.error;
457 }
458
459 static inline errval_t invoke_irqtable_set(struct capref irqcap, int irq,
460                                            struct capref ep)
461 {
462     return cap_invoke3(irqcap, IRQTableCmd_Set, irq, get_cap_addr(ep)).error;
463 }
464
465 static inline errval_t invoke_irqtable_delete(struct capref irqcap, int irq)
466 {
467     return cap_invoke2(irqcap, IRQTableCmd_Delete, irq).error;
468 }
469
470 /**
471  * \brief do a kernel cap invocation to get the core id
472  */
473 static inline errval_t invoke_kernel_get_core_id(struct capref kern_cap,
474                                                  coreid_t *core_id)
475 {
476     assert(core_id != NULL);
477
478     struct sysret sysret = cap_invoke1(kern_cap, KernelCmd_Get_core_id);
479     if (sysret.error == SYS_ERR_OK) {
480         *core_id = sysret.value;
481     }
482     return sysret.error;
483 }
484
485 static inline errval_t invoke_dispatcher_dump_ptables(struct capref dispcap)
486 {
487     return cap_invoke1(dispcap, DispatcherCmd_DumpPTables).error;
488 }
489
490 static inline errval_t invoke_dispatcher_dump_capabilities(struct capref dispcap)
491 {
492     return cap_invoke1(dispcap, DispatcherCmd_DumpCapabilities).error;
493 }
494
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,
499                                                capaddr_t ep_addr)
500 {
501     return cap_invoke7(perfmon_cap, PerfmonCmd_Activate,
502                        event, perf_umask, counter_id, kernel,
503                        counter_value, ep_addr).error;
504 }
505
506 static inline errval_t invoke_perfmon_write(struct capref perfmon_cap,
507                                                   uint8_t counter_id,
508                                                   uint64_t counter_value)
509 {
510     return cap_invoke3(perfmon_cap, PerfmonCmd_Write, counter_id, counter_value).error;
511 }
512
513 static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap)
514 {
515     return cap_invoke1(perfmon_cap, PerfmonCmd_Deactivate).error;
516 }
517
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)
523 {
524     return cap_invoke7(dispatcher, DispatcherCmd_Properties, type, deadline,
525                        wcet, period, release, weight).error;
526 }
527
528 static inline errval_t invoke_ipi_notify_send(struct capref notify_cap)
529 {
530     return cap_invoke1(notify_cap, NotifyCmd_Send).error;
531 }
532
533 /**
534  * \brief Return the system-wide unique ID of the passed ID capability.
535  *
536  * \param idcap ID capability to invoke.
537  * \param id    Filled-in with system-wide unique ID of ID cap.
538  *
539  * \return      Error code
540  */
541 static inline errval_t invoke_idcap_identify(struct capref idcap,
542                                              idcap_id_t *id)
543 {
544     assert(id != NULL);
545
546     struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify);
547
548     if (err_is_ok(sysret.error)) {
549         *id = sysret.value;
550     }
551
552     return sysret.error;
553 }
554
555 static inline errval_t invoke_send_init_ipi(struct capref ipi_cap, coreid_t core_id)
556 {
557     return cap_invoke2(ipi_cap, IPICmd_Send_Init,
558                        core_id).error;
559 }
560
561 static inline errval_t invoke_send_start_ipi(struct capref ipi_cap, coreid_t core_id, forvaddr_t entry)
562 {
563     return cap_invoke3(ipi_cap, IPICmd_Send_Start,
564                        core_id, entry).error;
565 }
566
567 static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global)
568
569     struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys);
570     if (err_is_ok(sr.error)) {
571         *global = sr.value;
572     }
573
574     return sr.error;
575 }
576
577 #endif