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