1/**
2 * \file
3 * \brief Low-level capability invocations
4 */
5
6/*
7 * Copyright (c) 2007-2010, 2012, 2013, 2015, ETH Zurich.
8 * Copyright (c) 2015, Hewlett Packard Enterprise Development LP.
9 * All rights reserved.
10 *
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
14 */
15
16#ifndef INCLUDEBARRELFISH_INVOCATIONS_ARCH_H
17#define INCLUDEBARRELFISH_INVOCATIONS_ARCH_H
18
19#include <barrelfish/syscall_arch.h> // for sys_invoke and cap_invoke
20#include <barrelfish_kpi/dispatcher_shared.h>
21#include <barrelfish_kpi/distcaps.h>            // for distcap_state_t
22#include <barrelfish_kpi/syscalls.h>
23#include <barrelfish/caddr.h>
24#include <barrelfish_kpi/paging_arch.h>
25
26/**
27 * capability invocation syscall wrapper, copied from x86_32 version
28 */
29static inline struct sysret cap_invoke(struct capref to, uintptr_t argc, uintptr_t cmd,
30                                       uintptr_t arg2, uintptr_t arg3,
31                                       uintptr_t arg4, uintptr_t arg5,
32                                       uintptr_t arg6, uintptr_t arg7,
33                                       uintptr_t arg8, uintptr_t arg9,
34                                       uintptr_t arg10, uintptr_t arg11)
35{
36    uint8_t invoke_level = get_cap_level(to);
37    capaddr_t invoke_cptr = get_cap_addr(to);
38
39    assert(cmd < 0xFF);
40
41    // flags << 24 | invoke_bits << 16 | cmd << 8 | syscall_invoke
42    // ^ used for LMP
43    uint32_t invocation = ((invoke_level << 16) | (cmd << 8) | SYSCALL_INVOKE);
44
45    switch (argc) {
46        case 0:
47        return syscall2(invocation, invoke_cptr);
48        case 1:
49        return syscall3(invocation, invoke_cptr, arg2);
50        case 2:
51        return syscall4(invocation, invoke_cptr, arg2, arg3);
52        case 3:
53        return syscall5(invocation, invoke_cptr, arg2, arg3, arg4);
54        case 4:
55        return syscall6(invocation, invoke_cptr, arg2, arg3, arg4, arg5);
56        case 5:
57        return syscall7(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6);
58        case 6:
59        return syscall8(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6,
60                        arg7);
61        case 7:
62        return syscall9(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6,
63                        arg7, arg8);
64        case 8:
65        return syscall10(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6,
66                        arg7, arg8, arg9);
67        case 9:
68        return syscall11(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6,
69                         arg7, arg8, arg9, arg10);
70        case 10:
71        return syscall12(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6,
72                         arg7, arg8, arg9, arg10, arg11);
73        default:
74        return SYSRET(SYS_ERR_ILLEGAL_INVOCATION);
75    }
76    assert(!"reached");
77}
78
79#define cap_invoke11(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k)   \
80    cap_invoke(to, 10, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k)
81#define cap_invoke10(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j)   \
82    cap_invoke(to, 9, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, 0)
83#define cap_invoke9(to, _a, _b, _c, _d, _e, _f, _g, _h, _i)        \
84    cap_invoke(to, 8, _a, _b, _c, _d, _e, _f, _g, _h, _i, 0, 0)
85#define cap_invoke8(to, _a, _b, _c, _d, _e, _f, _g, _h)    \
86    cap_invoke(to, 7, _a, _b, _c, _d, _e, _f, _g, _h, 0, 0, 0)
87#define cap_invoke7(to, _a, _b, _c, _d, _e, _f, _g)    \
88    cap_invoke(to, 6, _a, _b, _c, _d, _e, _f, _g, 0, 0, 0, 0)
89#define cap_invoke6(to, _a, _b, _c, _d, _e, _f)        \
90    cap_invoke(to, 5, _a, _b, _c, _d, _e, _f, 0, 0, 0, 0, 0)
91#define cap_invoke5(to, _a, _b, _c, _d, _e)            \
92    cap_invoke(to, 4, _a, _b, _c, _d, _e, 0, 0, 0, 0, 0, 0)
93#define cap_invoke4(to, _a, _b, _c, _d)                \
94    cap_invoke(to, 3, _a, _b, _c, _d, 0, 0, 0, 0, 0, 0, 0)
95#define cap_invoke3(to, _a, _b, _c)                    \
96    cap_invoke(to, 2, _a, _b, _c, 0, 0, 0, 0, 0, 0, 0, 0)
97#define cap_invoke2(to, _a, _b)                        \
98    cap_invoke(to, 1, _a, _b, 0, 0, 0, 0, 0, 0, 0, 0, 0)
99#define cap_invoke1(to, _a)                            \
100    cap_invoke(to, 0, _a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
101
102/**
103 * \brief Retype (part of) a capability.
104 *
105 * Retypes (part of) CPtr 'cap' into 'objsize'd caps of type 'newtype' and places them
106 * into slots starting at slot 'slot' in the CNode, addressed by 'to', with
107 * 'bits' address bits of 'to' valid.
108 *
109 * See also cap_retype(), which wraps this.
110 *
111 * \param root          Capability of the source cspace root CNode to invoke
112 * \param src_cspace    Source cspace cap address in our cspace.
113 * \param cap           Address of cap to retype in source cspace.
114 * \param offset        Offset into cap to retype
115 * \param newtype       Kernel object type to retype to.
116 * \param objsize       Size of created objects, for variable-sized types
117 * \param count         Number of objects to create
118 * \param to_cspace     Destination cspace cap address in our cspace
119 * \param to            Address of CNode cap in destination cspcae to place
120 *                      retyped caps into.
121 * \param to_level      Level/depth of CNode cap in destination cspace
122 * \param slot          Slot in CNode cap to start placement.
123 *
124 * \return Error code
125 */
126STATIC_ASSERT(ObjType_Num < 0xFFFF, "retype invocation argument packing does not truncate enum objtype");
127static inline errval_t
128invoke_cnode_retype(struct capref root, capaddr_t src_cspace, capaddr_t cap,
129                    gensize_t offset, enum objtype newtype, gensize_t objsize,
130                    size_t count, capaddr_t to_cspace, capaddr_t to,
131                    enum cnode_type to_level, capaddr_t slot)
132{
133    assert(cap != CPTR_NULL);
134
135    assert(newtype < ObjType_Num);
136    assert(count <= 0xFFFFFFFF);
137    assert(to_level <= 0xF);
138
139    return cap_invoke10(root, CNodeCmd_Retype, src_cspace, cap, offset,
140                        ((uint32_t)to_level << 16) | newtype,
141                        objsize, count, to_cspace, to, slot).error;
142}
143
144
145static inline errval_t
146invoke_vnode_map(struct capref ptable, capaddr_t slot,
147                 capaddr_t src_root, capaddr_t src,
148                 enum cnode_type srclevel, size_t
149                 flags, size_t offset, size_t pte_count,
150                 capaddr_t mcnroot, capaddr_t mcnaddr,
151                 enum cnode_type mcnlevel, cslot_t mapping_slot)
152{
153    assert(slot <= 0xffff);
154    assert(srclevel <= 0xf);
155    assert(mcnlevel <= 0xf);
156    assert(offset <= 0xffffffff);
157    assert(flags <= 0xffffffff);
158    assert(pte_count <= 0xffff);
159    assert(mapping_slot <= L2_CNODE_SLOTS);
160
161    uintptr_t small_values = srclevel |
162                             (mcnlevel << 4) |
163                             (mapping_slot << 8) |
164                             (slot << 16);
165
166    return cap_invoke9(ptable, VNodeCmd_Map, src_root, src, flags, offset,
167                       pte_count, mcnroot, mcnaddr, small_values).error;
168}
169
170static inline errval_t invoke_vnode_modify_flags(struct capref cap,
171                                          size_t entry, size_t num_pages,
172                                          size_t attr)
173{
174    return cap_invoke4(cap, VNodeCmd_ModifyFlags, entry, num_pages, attr).error;
175}
176
177/**
178 * \brief Return the physical address and size of a frame capability
179 *
180 * \param frame    CSpace address of frame capability
181 * \param ret      frame_identity struct filled in with relevant data
182 *
183 * \return Error code
184 */
185static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd,
186                                       uint16_t port, uint32_t *data)
187{
188    // Not strictly applicable on ARM
189//    USER_PANIC("NYI");
190    return LIB_ERR_NOT_IMPLEMENTED;
191}
192
193static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd,
194                                        uint16_t port, uint32_t data)
195{
196    // Not strictly applicable on ARM
197//    USER_PANIC("NYI");
198    return LIB_ERR_NOT_IMPLEMENTED;
199}
200
201
202static inline errval_t
203invoke_idcap_identify(struct capref idcap, idcap_id_t *id)
204{
205    assert(id != NULL);
206    assert(get_croot_addr(idcap) == CPTR_ROOTCN);
207
208    struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify);
209
210    if (err_is_ok(sysret.error)) {
211        *id = sysret.value;
212    }
213
214    return sysret.error;
215}
216
217static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global)
218{
219    struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys);
220    if (err_is_ok(sr.error)) {
221        *global = sr.value;
222    }
223
224    return sr.error;
225}
226
227#endif
228