1/** 2 * \file 3 * \brief Arch-specific Low-level capability invocations 4 */ 5 6/* 7 * Copyright (c) 2007-2016, 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, Universitaetstr. 6, 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/caddr.h> 21#include <barrelfish_kpi/paging_arch.h> 22 23static inline struct sysret cap_invoke(struct capref to, uintptr_t arg1, 24 uintptr_t arg2, uintptr_t arg3, 25 uintptr_t arg4, uintptr_t arg5, 26 uintptr_t arg6, uintptr_t arg7, 27 uintptr_t arg8, uintptr_t arg9, 28 uintptr_t arg10) 29{ 30 capaddr_t invoke_cptr = get_cap_addr(to); 31 enum cnode_type invoke_level = get_cap_level(to); 32 33 return syscall(SYSCALL_INVOKE, (uint64_t)invoke_cptr << 32 | 34 (uint64_t)invoke_level << 16 | 10 << 8, 0, 35 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, 36 arg10); 37} 38 39#define cap_invoke10(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j) \ 40 cap_invoke(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j) 41#define cap_invoke9(to, _a, _b, _c, _d, _e, _f, _g, _h, _i) \ 42 cap_invoke10(to, _a, _b, _c, _d, _e, _f, _g, _h, _i, 0) 43#define cap_invoke8(to, _a, _b, _c, _d, _e, _f, _g, _h) \ 44 cap_invoke9(to, _a, _b, _c, _d, _e, _f, _g, _h, 0) 45#define cap_invoke7(to, _a, _b, _c, _d, _e, _f, _g) \ 46 cap_invoke8(to, _a, _b, _c, _d, _e, _f, _g, 0) 47#define cap_invoke6(to, _a, _b, _c, _d, _e, _f) \ 48 cap_invoke7(to, _a, _b, _c, _d, _e, _f, 0) 49#define cap_invoke5(to, _a, _b, _c, _d, _e) \ 50 cap_invoke6(to, _a, _b, _c, _d, _e, 0) 51#define cap_invoke4(to, _a, _b, _c, _d) \ 52 cap_invoke5(to, _a, _b, _c, _d, 0) 53#define cap_invoke3(to, _a, _b, _c) \ 54 cap_invoke4(to, _a, _b, _c, 0) 55#define cap_invoke2(to, _a, _b) \ 56 cap_invoke3(to, _a, _b, 0) 57#define cap_invoke1(to, _a) \ 58 cap_invoke2(to, _a, 0) 59 60 61/** 62 * \brief Retype (part of) a capability. 63 * 64 * Retypes (part of) CPtr 'cap' into 'objsize'd caps of type 'newtype' and places them 65 * into slots starting at slot 'slot' in the CNode, addressed by 'to', with 66 * 'bits' address bits of 'to' valid. 67 * 68 * See also cap_retype(), which wraps this. 69 * 70 * \param root Capability of the source cspace root CNode to invoke 71 * \param src_cspace Source cspace cap address in our cspace. 72 * \param cap Address of cap to retype in source cspace. 73 * \param offset Offset into cap to retype 74 * \param newtype Kernel object type to retype to. 75 * \param objsize Size of created objects, for variable-sized types 76 * \param count Number of objects to create 77 * \param to_cspace Destination cspace cap address in our cspace 78 * \param to Address of CNode cap in destination cspcae to place 79 * retyped caps into. 80 * \param to_level Level/depth of CNode cap in destination cspace 81 * \param slot Slot in CNode cap to start placement. 82 * 83 * \return Error code 84 */ 85static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t src_cspace, 86 capaddr_t cap, gensize_t offset, 87 enum objtype newtype, gensize_t objsize, 88 size_t count, capaddr_t to_cspace, 89 capaddr_t to, enum cnode_type to_level, 90 capaddr_t slot) 91{ 92 assert(cap != CPTR_NULL); 93 return cap_invoke9(root, CNodeCmd_Retype, 94 ((uint64_t)src_cspace << 32) | (uint64_t)cap, offset, 95 newtype, objsize, count, 96 ((uint64_t)to_cspace << 32) | (uint64_t)to, slot, to_level).error; 97} 98 99static inline errval_t invoke_vnode_map(struct capref ptable, capaddr_t slot, 100 capaddr_t src_root, capaddr_t src, 101 enum cnode_type srclevel, size_t 102 flags, size_t offset, size_t pte_count, 103 capaddr_t mcnroot, capaddr_t mcnaddr, 104 enum cnode_type mcnlevel, cslot_t mapping_slot) 105{ 106 return cap_invoke10(ptable, VNodeCmd_Map, slot, 107 ((uint64_t)src_root << 32) | (uint64_t)src, srclevel, 108 flags, offset, pte_count, 109 ((uint64_t)mcnroot << 32) | (uint64_t)mcnaddr, 110 mcnlevel, mapping_slot).error; 111} 112 113static inline errval_t invoke_iocap_in(struct capref iocap, enum io_cmd cmd, 114 uint16_t port, uint32_t *data) 115{ 116 struct sysret sysret = cap_invoke2(iocap, cmd, port); 117 118 if (err_is_ok(sysret.error)) { 119 assert(data != NULL); 120 *data = sysret.value; 121 } 122 return sysret.error; 123} 124 125static inline errval_t invoke_iocap_out(struct capref iocap, enum io_cmd cmd, 126 uint16_t port, uint32_t data) 127{ 128 return cap_invoke3(iocap, cmd, port, data).error; 129} 130 131/** 132 * \brief Execute vmread on the VMCS of the VM guest DCB 133 * 134 * The VMCS must be current and active. 135 * 136 * \param dcb Dispatcher capability 137 * \param encoding Encoding of the field to read from the VMCS 138 * \param addr The address to write the value of the field to. 139 */ 140static inline errval_t invoke_dispatcher_vmread(struct capref dispatcher, 141 uintptr_t encoding, 142 lvaddr_t *addr) 143{ 144 return cap_invoke3(dispatcher, DispatcherCmd_Vmread, 145 encoding, (uintptr_t)addr).error; 146} 147 148/** 149 * \brief Execute vmwrite on the VMCS of the VM guest DCB 150 * 151 * The VMCS must be current and active. 152 * 153 * \param dcb Dispatcher capability 154 * \param encoding Encoding of the field to write to the VMCS. 155 * \param value Value of the field to write. 156 */ 157 158static inline errval_t invoke_dispatcher_vmwrite(struct capref dispatcher, 159 uintptr_t encoding, 160 uintptr_t value) 161{ 162 return cap_invoke3(dispatcher, DispatcherCmd_Vmwrite, 163 encoding, value).error; 164} 165 166/** 167 * \brief Execute vmptrld on the VMCS of the VM guest DCB 168 * 169 * \param dcb Dispatcher capability 170 */ 171static inline errval_t invoke_dispatcher_vmptrld(struct capref dispatcher) 172{ 173 return cap_invoke1(dispatcher, DispatcherCmd_Vmptrld).error; 174} 175 176/** 177 * \brief Execute vmclear on the VMCS of the VM guest DCB 178 * 179 * \param dcb Dispatcher capability 180 */ 181static inline errval_t invoke_dispatcher_vmclear(struct capref dispatcher) 182{ 183 return cap_invoke1(dispatcher, DispatcherCmd_Vmclear).error; 184} 185 186/** 187 * \brief Setup a VM guest DCB 188 * 189 * \param dcb Dispatcher capability 190 */ 191static inline errval_t 192invoke_dispatcher_setup_guest(struct capref dispatcher, 193 struct capref ep_cap, 194 struct capref vnode, 195 struct capref vmkit_guest, 196 struct capref guest_control_cap) 197{ 198 return cap_invoke5(dispatcher, DispatcherCmd_SetupGuest, 199 get_cap_addr(ep_cap), get_cap_addr(vnode), 200 get_cap_addr(vmkit_guest), 201 get_cap_addr(guest_control_cap)).error; 202} 203 204static inline errval_t invoke_perfmon_activate(struct capref perfmon_cap, 205 uint8_t event, uint8_t perf_umask, 206 bool kernel, uint8_t counter_id, 207 uint64_t counter_value, 208 capaddr_t ep_addr) 209{ 210 return cap_invoke7(perfmon_cap, PerfmonCmd_Activate, 211 event, perf_umask, counter_id, kernel, 212 counter_value, ep_addr).error; 213} 214 215static inline errval_t invoke_perfmon_write(struct capref perfmon_cap, 216 uint8_t counter_id, 217 uint64_t counter_value) 218{ 219 return cap_invoke3(perfmon_cap, PerfmonCmd_Write, counter_id, counter_value).error; 220} 221 222static inline errval_t invoke_perfmon_deactivate(struct capref perfmon_cap) 223{ 224 return cap_invoke1(perfmon_cap, PerfmonCmd_Deactivate).error; 225} 226 227static inline errval_t invoke_ipi_notify_send(struct capref notify_cap) 228{ 229 return cap_invoke1(notify_cap, NotifyCmd_Send).error; 230} 231 232static inline errval_t invoke_send_init_ipi(struct capref ipi_cap, coreid_t core_id) 233{ 234 return cap_invoke2(ipi_cap, IPICmd_Send_Init, 235 core_id).error; 236} 237 238static inline errval_t invoke_send_start_ipi(struct capref ipi_cap, coreid_t core_id, forvaddr_t entry) 239{ 240 return cap_invoke3(ipi_cap, IPICmd_Send_Start, 241 core_id, entry).error; 242} 243 244static inline errval_t invoke_vnode_modify_flags(struct capref cap, 245 size_t entry, size_t num_pages, 246 size_t attr) 247{ 248 return cap_invoke4(cap, VNodeCmd_ModifyFlags, entry, num_pages, attr).error; 249} 250/** 251 * \brief Return the system-wide unique ID of the passed ID capability. 252 * 253 * \param idcap ID capability to invoke. 254 * \param id Filled-in with system-wide unique ID of ID cap. 255 * 256 * \return Error code 257 */ 258static inline errval_t invoke_idcap_identify(struct capref idcap, 259 idcap_id_t *id) 260{ 261 assert(id != NULL); 262 assert(get_croot_addr(idcap) == CPTR_ROOTCN); 263 264 struct sysret sysret = cap_invoke1(idcap, IDCmd_Identify); 265 266 if (err_is_ok(sysret.error)) { 267 *id = sysret.value; 268 } 269 270 return sysret.error; 271} 272 273static inline errval_t invoke_get_global_paddr(struct capref kernel_cap, genpaddr_t* global) 274{ 275 struct sysret sr = cap_invoke1(kernel_cap, KernelCmd_GetGlobalPhys); 276 if (err_is_ok(sr.error)) { 277 *global = sr.value; 278 } 279 280 return sr.error; 281} 282 283#endif 284