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, Haldeneggsteig 4, 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/caddr.h> 23#include <barrelfish_kpi/paging_arch.h> 24 25/** 26 * capability invocation syscall wrapper, copied from x86_32 version 27 */ 28static inline struct sysret cap_invoke(struct capref to, uintptr_t argc, uintptr_t cmd, 29 uintptr_t arg2, uintptr_t arg3, 30 uintptr_t arg4, uintptr_t arg5, 31 uintptr_t arg6, uintptr_t arg7, 32 uintptr_t arg8, uintptr_t arg9, 33 uintptr_t arg10, uintptr_t arg11) 34{ 35 capaddr_t invoke_cptr = get_cap_addr(to); 36 enum cnode_type invoke_level = get_cap_level(to); 37 38 assert(cmd <= 0xFF); 39 assert(invoke_level <= 0xF); 40 // flags << 24 | invoke_bits << 16 | cmd << 8 | syscall_invoke 41 // ^ used for LMP 42 uint32_t invocation = ((invoke_level << 16) | (cmd << 8) | SYSCALL_INVOKE); 43 44 switch (argc) { 45 case 0: 46 return syscall2(invocation, invoke_cptr); 47 case 1: 48 return syscall3(invocation, invoke_cptr, arg2); 49 case 2: 50 return syscall4(invocation, invoke_cptr, arg2, arg3); 51 case 3: 52 return syscall5(invocation, invoke_cptr, arg2, arg3, arg4); 53 case 4: 54 return syscall6(invocation, invoke_cptr, arg2, arg3, arg4, arg5); 55 case 5: 56 return syscall7(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6); 57 case 6: 58 return syscall8(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 59 arg7); 60 case 7: 61 return syscall9(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 62 arg7, arg8); 63 case 8: 64 return syscall10(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 65 arg7, arg8, arg9); 66 case 9: 67 return syscall11(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 68 arg7, arg8, arg9, arg10); 69 case 10: 70 return syscall12(invocation, invoke_cptr, arg2, arg3, arg4, arg5, arg6, 71 arg7, arg8, arg9, arg10, arg11); 72 default: 73 return SYSRET(SYS_ERR_ILLEGAL_INVOCATION); 74 } 75 assert(!"reached"); 76} 77 78#define cap_invoke11(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k) \ 79 cap_invoke(to, 10, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k) 80#define cap_invoke10(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j) \ 81 cap_invoke(to, 9, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, 0) 82#define cap_invoke9(to, _a, _b, _c, _d, _e, _f, _g, _h, _i) \ 83 cap_invoke(to, 8, _a, _b, _c, _d, _e, _f, _g, _h, _i, 0, 0) 84#define cap_invoke8(to, _a, _b, _c, _d, _e, _f, _g, _h) \ 85 cap_invoke(to, 7, _a, _b, _c, _d, _e, _f, _g, _h, 0, 0, 0) 86#define cap_invoke7(to, _a, _b, _c, _d, _e, _f, _g) \ 87 cap_invoke(to, 6, _a, _b, _c, _d, _e, _f, _g, 0, 0, 0, 0) 88#define cap_invoke6(to, _a, _b, _c, _d, _e, _f) \ 89 cap_invoke(to, 5, _a, _b, _c, _d, _e, _f, 0, 0, 0, 0, 0) 90#define cap_invoke5(to, _a, _b, _c, _d, _e) \ 91 cap_invoke(to, 4, _a, _b, _c, _d, _e, 0, 0, 0, 0, 0, 0) 92#define cap_invoke4(to, _a, _b, _c, _d) \ 93 cap_invoke(to, 3, _a, _b, _c, _d, 0, 0, 0, 0, 0, 0, 0) 94#define cap_invoke3(to, _a, _b, _c) \ 95 cap_invoke(to, 2, _a, _b, _c, 0, 0, 0, 0, 0, 0, 0, 0) 96#define cap_invoke2(to, _a, _b) \ 97 cap_invoke(to, 1, _a, _b, 0, 0, 0, 0, 0, 0, 0, 0, 0) 98#define cap_invoke1(to, _a) \ 99 cap_invoke(to, 0, _a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 100 101/** 102 * \brief Retype (part of) a capability. 103 * 104 * Retypes (part of) CPtr 'cap' into 'objsize'd caps of type 'newtype' and places them 105 * into slots starting at slot 'slot' in the CNode, addressed by 'to', with 106 * 'bits' address bits of 'to' valid. 107 * 108 * See also cap_retype(), which wraps this. 109 * 110 * \param root Capability of the Root CNode to invoke 111 * \param cap Address of cap to retype. 112 * \param offset Offset into cap to retype 113 * \param newtype Kernel object type to retype to. 114 * \param objsize Size of created objects, for variable-sized types 115 * \param count Number of objects to create 116 * \param to Address of CNode cap to place retyped caps into. 117 * \param slot Slot in CNode cap to start placement. 118 * \param bits Number of valid address bits in 'to'. 119 * 120 * \return Error code 121 */ 122STATIC_ASSERT(ObjType_Num < 0xFFFF, "retype invocation argument packing does not truncate enum objtype"); 123static inline errval_t 124invoke_cnode_retype(struct capref root, capaddr_t src_cspace, capaddr_t cap, 125 gensize_t offset, enum objtype newtype, gensize_t objsize, 126 size_t count, capaddr_t to_cspace, capaddr_t to, 127 enum cnode_type to_level, capaddr_t slot) 128{ 129 assert(cap != CPTR_NULL); 130 131 assert(newtype < ObjType_Num); 132 assert(offset <= 0xFFFFFFFF); 133 assert(objsize <= 0xFFFFFFFF); 134 assert(count <= 0xFFFFFFFF); 135 assert(to_level <= 0xF); 136 137 return cap_invoke10(root, CNodeCmd_Retype, src_cspace, cap, offset, 138 ((uint32_t)to_level << 16) | newtype, 139 objsize, count, to_cspace, to, slot).error; 140} 141 142static inline errval_t 143invoke_vnode_map(struct capref ptable, capaddr_t slot, 144 capaddr_t src_root, capaddr_t src, 145 enum cnode_type srclevel, size_t 146 flags, size_t offset, size_t pte_count, 147 capaddr_t mcnroot, capaddr_t mcnaddr, 148 enum cnode_type mcnlevel, cslot_t mapping_slot) 149{ 150 assert(slot <= 0xffff); 151 assert(srclevel <= 0xf); 152 assert(mcnlevel <= 0xf); 153 assert(offset <= 0xffffffff); 154 assert(flags <= 0xffffffff); 155 assert(pte_count <= 0xffff); 156 assert(mapping_slot <= L2_CNODE_SLOTS); 157 158 uintptr_t small_values = srclevel | 159 (mcnlevel << 4) | 160 (mapping_slot << 8) | 161 (slot << 16); 162 163 return cap_invoke9(ptable, VNodeCmd_Map, src_root, src, flags, offset, 164 pte_count, mcnroot, mcnaddr, small_values).error; 165} 166 167static inline errval_t invoke_vnode_modify_flags(struct capref cap, 168 size_t entry, size_t num_pages, 169 size_t attr) 170{ 171 return cap_invoke4(cap, VNodeCmd_ModifyFlags, entry, num_pages, attr).error; 172} 173 174/** 175 * \brief Duplicate ARMv7 core_data into the supplied frame. 176 * 177 * \param frame CSpace address of frame capability 178 * 179 * \return Error code 180 */ 181 182static inline errval_t 183invoke_kcb_clone(struct capref kcb, struct capref frame) 184{ 185 capaddr_t frame_cptr = get_cap_addr(frame); 186 enum cnode_type frame_level = get_cap_level(frame); 187 188 return cap_invoke3(kcb, KCBCmd_Clone, frame_cptr, frame_level).error; 189} 190 191static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd, 192 uint16_t port, uint32_t *data) 193{ 194 // Not strictly applicable on ARM 195 return LIB_ERR_NOT_IMPLEMENTED; 196} 197 198static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd, 199 uint16_t port, uint32_t data) 200{ 201 // Not strictly applicable on ARM 202 return LIB_ERR_NOT_IMPLEMENTED; 203} 204 205 206/** 207 * \brief Setup a VM guest DCB 208 * 209 * \param dcb Dispatcher capability 210 */ 211static inline errval_t invoke_dispatcher_setup_guest(struct capref dispatcher, 212 capaddr_t ep_cap, 213 capaddr_t vnode, 214 capaddr_t vmkit_guest, 215 capaddr_t guest_control_cap) 216{ 217 return LIB_ERR_NOT_IMPLEMENTED; 218} 219 220/** 221 * \brief Return the system-wide unique ID of the passed ID capability. 222 * 223 * \param idcap ID capability to invoke. 224 * \param id Filled-in with system-wide unique ID of ID cap. 225 * 226 * \return Error code 227 */ 228static inline errval_t invoke_idcap_identify(struct capref idcap, 229 idcap_id_t *id) 230{ 231 assert(id != NULL); 232 assert(get_croot_addr(idcap) == CPTR_ROOTCN); 233 234 return cap_invoke2(idcap, IDCmd_Identify, (uintptr_t)id).error; 235} 236 237static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global) 238{ 239 assert(global != NULL); 240 return cap_invoke2(kernel_cap, KernelCmd_GetGlobalPhys, (uintptr_t)global).error; 241} 242 243#endif 244