1/** 2 * \file 3 * \brief Low-level capability invocations 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, 2012, 2013, 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 15#ifndef INCLUDEBARRELFISH_INVOCATIONS_ARCH_H 16#define INCLUDEBARRELFISH_INVOCATIONS_ARCH_H 17 18#include <barrelfish/syscall_arch.h> // for sys_invoke and cap_invoke 19#include <barrelfish_kpi/dispatcher_shared.h> 20#include <barrelfish_kpi/distcaps.h> // for distcap_state_t 21#include <barrelfish_kpi/syscalls.h> 22#include <barrelfish_kpi/lmp.h> // invoking lmp endpoint requires flags 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 capaddr_t invoke_cptr = get_cap_addr(to); 37 enum cnode_type invoke_level = get_cap_level(to); 38 39 assert(cmd <= 0xFF); 40 assert(invoke_level <= 0xF); 41 // flags << 24 | invoke_bits << 16 | cmd << 8 | syscall_invoke 42 // ^ used for LMP 43 uint32_t invocation = ((LMP_FLAG_IDENTIFY << 24) | 44 (invoke_level << 16) | (cmd << 8) | 45 SYSCALL_INVOKE ); 46 47 switch (argc) { 48 case 0: 49 return syscall2(invocation, invoke_cptr); 50 case 1: 51 return syscall3(invocation, invoke_cptr, arg2); 52 case 2: 53 return syscall4(invocation, invoke_cptr, arg2, arg3); 54 case 3: 55 return syscall5(invocation, invoke_cptr, arg2, arg3, arg4); 56 case 4: 57 return syscall6(invocation, invoke_cptr, arg2, arg3, arg4, arg5); 58 case 5: 59 return syscall7(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6); 60 case 6: 61 return syscall8(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 62 arg7); 63 case 7: 64 return syscall9(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 65 arg7, arg8); 66 case 8: 67 return syscall10(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 68 arg7, arg8, arg9); 69 case 9: 70 return syscall11(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 71 arg7, arg8, arg9, arg10); 72 case 10: 73 return syscall12(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 74 arg7, arg8, arg9, arg10, arg11); 75 default: 76 return SYSRET(SYS_ERR_ILLEGAL_INVOCATION); 77 } 78 assert(!"reached"); 79} 80 81#define cap_invoke11(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k) \ 82 cap_invoke(to, 10, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k) 83#define cap_invoke10(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j) \ 84 cap_invoke(to, 9, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, 0) 85#define cap_invoke9(to, _a, _b, _c, _d, _e, _f, _g, _h, _i) \ 86 cap_invoke(to, 8, _a, _b, _c, _d, _e, _f, _g, _h, _i, 0, 0) 87#define cap_invoke8(to, _a, _b, _c, _d, _e, _f, _g, _h) \ 88 cap_invoke(to, 7, _a, _b, _c, _d, _e, _f, _g, _h, 0, 0, 0) 89#define cap_invoke7(to, _a, _b, _c, _d, _e, _f, _g) \ 90 cap_invoke(to, 6, _a, _b, _c, _d, _e, _f, _g, 0, 0, 0, 0) 91#define cap_invoke6(to, _a, _b, _c, _d, _e, _f) \ 92 cap_invoke(to, 5, _a, _b, _c, _d, _e, _f, 0, 0, 0, 0, 0) 93#define cap_invoke5(to, _a, _b, _c, _d, _e) \ 94 cap_invoke(to, 4, _a, _b, _c, _d, _e, 0, 0, 0, 0, 0, 0) 95#define cap_invoke4(to, _a, _b, _c, _d) \ 96 cap_invoke(to, 3, _a, _b, _c, _d, 0, 0, 0, 0, 0, 0, 0) 97#define cap_invoke3(to, _a, _b, _c) \ 98 cap_invoke(to, 2, _a, _b, _c, 0, 0, 0, 0, 0, 0, 0, 0) 99#define cap_invoke2(to, _a, _b) \ 100 cap_invoke(to, 1, _a, _b, 0, 0, 0, 0, 0, 0, 0, 0, 0) 101#define cap_invoke1(to, _a) \ 102 cap_invoke(to, 0, _a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 103 104/** 105 * \brief Retype (part of) a capability. 106 * 107 * Retypes (part of) CPtr 'cap' into 'objsize'd caps of type 'newtype' and places them 108 * into slots starting at slot 'slot' in the CNode, addressed by 'to', with 109 * 'bits' address bits of 'to' valid. 110 * 111 * See also cap_retype(), which wraps this. 112 * 113 * \param root Capability of the Root CNode to invoke 114 * \param cap Address of cap to retype. 115 * \param offset Offset into cap to retype 116 * \param newtype Kernel object type to retype to. 117 * \param objsize Size of created objects, for variable-sized types 118 * \param count Number of objects to create 119 * \param to Address of CNode cap to place retyped caps into. 120 * \param slot Slot in CNode cap to start placement. 121 * \param bits Number of valid address bits in 'to'. 122 * 123 * \return Error code 124 */ 125STATIC_ASSERT(ObjType_Num < 0xFFFF, "retype invocation argument packing does not truncate enum objtype"); 126static inline errval_t 127invoke_cnode_retype(struct capref root, capaddr_t src_cspace, capaddr_t cap, 128 gensize_t offset, enum objtype newtype, gensize_t objsize, 129 size_t count, capaddr_t to_cspace, capaddr_t to, 130 enum cnode_type to_level, capaddr_t slot) 131{ 132 assert(cap != CPTR_NULL); 133 134 assert(newtype < ObjType_Num); 135 assert(offset <= 0xFFFFFFFF); 136 assert(objsize <= 0xFFFFFFFF); 137 assert(count <= 0xFFFFFFFF); 138 assert(to_level <= 0xF); 139 140 return cap_invoke10(root, CNodeCmd_Retype, src_cspace, cap, offset, 141 ((uint32_t)to_level << 16) | newtype, 142 objsize, count, to_cspace, to, slot).error; 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 170/** 171 * \brief Duplicate ARMv7 core_data into the supplied frame. 172 * 173 * \param frame CSpace address of frame capability 174 * 175 * \return Error code 176 */ 177 178static inline errval_t 179invoke_kcb_clone(struct capref kcb, struct capref frame) 180{ 181 capaddr_t frame_cptr = get_cap_addr(frame); 182 enum cnode_type frame_level = get_cap_level(frame); 183 184 return cap_invoke3(kcb, KCBCmd_Clone, frame_cptr, frame_level).error; 185} 186 187static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd, 188 uint16_t port, uint32_t *data) 189{ 190 // Not strictly applicable on ARM 191 return LIB_ERR_NOT_IMPLEMENTED; 192} 193 194static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd, 195 uint16_t port, uint32_t data) 196{ 197 // Not strictly applicable on ARM 198 return LIB_ERR_NOT_IMPLEMENTED; 199} 200 201 202/** 203 * \brief Setup a VM guest DCB 204 * 205 * \param dcb Dispatcher capability 206 */ 207static inline errval_t invoke_dispatcher_setup_guest(struct capref dispatcher, 208 capaddr_t ep_cap, 209 capaddr_t vnode, 210 capaddr_t vmkit_guest, 211 capaddr_t guest_control_cap) 212{ 213 return LIB_ERR_NOT_IMPLEMENTED; 214} 215 216/** 217 * \brief Return the system-wide unique ID of the passed ID capability. 218 * 219 * \param idcap ID capability to invoke. 220 * \param id Filled-in with system-wide unique ID of ID cap. 221 * 222 * \return Error code 223 */ 224static inline errval_t invoke_idcap_identify(struct capref idcap, 225 idcap_id_t *id) 226{ 227 assert(id != NULL); 228 assert(get_croot_addr(idcap) == CPTR_ROOTCN); 229 230 return cap_invoke2(idcap, IDCmd_Identify, (uintptr_t)id).error; 231} 232 233static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global) 234{ 235 assert(global != NULL); 236 return cap_invoke2(kernel_cap, KernelCmd_GetGlobalPhys, (uintptr_t)global).error; 237} 238 239/* 240 * MVA extensions 241 */ 242 243/** 244 * \brief clone vnode 245 * 246 * \arg mcn capaddr array of cnodes holding mapping caps for vnode slots 247 * \arg newflags new flags for cloned table entries. Ignored if 0. 248 */ 249static inline errval_t invoke_vnode_inherit(struct capref dest, capaddr_t src, 250 enum cnode_type slevel, 251 cslot_t start, cslot_t end, 252 uintptr_t newflags, 253 capaddr_t *mcn) 254{ 255 assert(ARM_L2_MAX_ENTRIES / L2_CNODE_SLOTS == 1); 256 assert(mcn[1] == CPTR_NULL); 257 assert(mcn[2] == CPTR_NULL); 258 assert(mcn[3] == CPTR_NULL); 259 assert(mcn[5] == CPTR_NULL); 260 assert(mcn[6] == CPTR_NULL); 261 assert(mcn[7] == CPTR_NULL); 262 // mcn[0] is source mcn, mcn[4] is dest mcn. 263 return cap_invoke8(dest, VNodeCmd_Inherit, src, slevel, start, end, 264 newflags, mcn[0], mcn[4]).error; 265} 266 267#endif 268