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