hypercall.h revision 289033
1/****************************************************************************** 2 * hypercall.h 3 * 4 * FreeBSD-specific hypervisor handling. 5 * 6 * Copyright (c) 2002-2004, K A Fraser 7 * 8 * 64-bit updates: 9 * Benjamin Liu <benjamin.liu@intel.com> 10 * Jun Nakajima <jun.nakajima@intel.com> 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License version 2 14 * as published by the Free Software Foundation; or, when distributed 15 * separately from the Linux kernel or incorporated into other 16 * software packages, subject to the following license: 17 * 18 * Permission is hereby granted, free of charge, to any person obtaining a copy 19 * of this source file (the "Software"), to deal in the Software without 20 * restriction, including without limitation the rights to use, copy, modify, 21 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 22 * and to permit persons to whom the Software is furnished to do so, subject to 23 * the following conditions: 24 * 25 * The above copyright notice and this permission notice shall be included in 26 * all copies or substantial portions of the Software. 27 * 28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 33 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 34 * IN THE SOFTWARE. 35 * 36 * $FreeBSD: head/sys/amd64/include/xen/hypercall.h 289033 2015-10-08 16:39:43Z royger $ 37 */ 38 39#ifndef __MACHINE_XEN_HYPERCALL_H__ 40#define __MACHINE_XEN_HYPERCALL_H__ 41 42#include <sys/systm.h> 43 44#ifndef __XEN_HYPERVISOR_H__ 45# error "please don't include this file directly" 46#endif 47 48extern char *hypercall_page; 49 50#define __STR(x) #x 51#define STR(x) __STR(x) 52#define ENOXENSYS 38 53#define CONFIG_XEN_COMPAT 0x030002 54#define __must_check 55 56#define HYPERCALL_STR(name) \ 57 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 58 59#define _hypercall0(type, name) \ 60({ \ 61 type __res; \ 62 __asm__ volatile ( \ 63 HYPERCALL_STR(name) \ 64 : "=a" (__res) \ 65 : \ 66 : "memory" ); \ 67 __res; \ 68}) 69 70#define _hypercall1(type, name, a1) \ 71({ \ 72 type __res; \ 73 long __ign1; \ 74 __asm__ volatile ( \ 75 HYPERCALL_STR(name) \ 76 : "=a" (__res), "=D" (__ign1) \ 77 : "1" ((long)(a1)) \ 78 : "memory" ); \ 79 __res; \ 80}) 81 82#define _hypercall2(type, name, a1, a2) \ 83({ \ 84 type __res; \ 85 long __ign1, __ign2; \ 86 __asm__ volatile ( \ 87 HYPERCALL_STR(name) \ 88 : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ 89 : "1" ((long)(a1)), "2" ((long)(a2)) \ 90 : "memory" ); \ 91 __res; \ 92}) 93 94#define _hypercall3(type, name, a1, a2, a3) \ 95({ \ 96 type __res; \ 97 long __ign1, __ign2, __ign3; \ 98 __asm__ volatile ( \ 99 HYPERCALL_STR(name) \ 100 : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 101 "=d" (__ign3) \ 102 : "1" ((long)(a1)), "2" ((long)(a2)), \ 103 "3" ((long)(a3)) \ 104 : "memory" ); \ 105 __res; \ 106}) 107 108#define _hypercall4(type, name, a1, a2, a3, a4) \ 109({ \ 110 type __res; \ 111 long __ign1, __ign2, __ign3; \ 112 register long __arg4 __asm__("r10") = (long)(a4); \ 113 __asm__ volatile ( \ 114 HYPERCALL_STR(name) \ 115 : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 116 "=d" (__ign3), "+r" (__arg4) \ 117 : "1" ((long)(a1)), "2" ((long)(a2)), \ 118 "3" ((long)(a3)) \ 119 : "memory" ); \ 120 __res; \ 121}) 122 123#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 124({ \ 125 type __res; \ 126 long __ign1, __ign2, __ign3; \ 127 register long __arg4 __asm__("r10") = (long)(a4); \ 128 register long __arg5 __asm__("r8") = (long)(a5); \ 129 __asm__ volatile ( \ 130 HYPERCALL_STR(name) \ 131 : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 132 "=d" (__ign3), "+r" (__arg4), "+r" (__arg5) \ 133 : "1" ((long)(a1)), "2" ((long)(a2)), \ 134 "3" ((long)(a3)) \ 135 : "memory" ); \ 136 __res; \ 137}) 138 139static inline int 140privcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5) 141{ 142 int __res; 143 long __ign1, __ign2, __ign3; 144 register long __arg4 __asm__("r10") = (long)(a4); 145 register long __arg5 __asm__("r8") = (long)(a5); 146 long __call = (long)&hypercall_page + (op * 32); 147 148 __asm__ volatile ( 149 "call *%[call]" 150 : "=a" (__res), "=D" (__ign1), "=S" (__ign2), 151 "=d" (__ign3), "+r" (__arg4), "+r" (__arg5) 152 : "1" ((long)(a1)), "2" ((long)(a2)), 153 "3" ((long)(a3)), [call] "a" (__call) 154 : "memory" ); 155 156 return (__res); 157} 158 159static inline int __must_check 160HYPERVISOR_set_trap_table( 161 const trap_info_t *table) 162{ 163 return _hypercall1(int, set_trap_table, table); 164} 165 166static inline int __must_check 167HYPERVISOR_mmu_update( 168 mmu_update_t *req, unsigned int count, unsigned int *success_count, 169 domid_t domid) 170{ 171 return _hypercall4(int, mmu_update, req, count, success_count, domid); 172} 173 174static inline int __must_check 175HYPERVISOR_mmuext_op( 176 struct mmuext_op *op, unsigned int count, unsigned int *success_count, 177 domid_t domid) 178{ 179 return _hypercall4(int, mmuext_op, op, count, success_count, domid); 180} 181 182static inline int __must_check 183HYPERVISOR_set_gdt( 184 unsigned long *frame_list, unsigned int entries) 185{ 186 return _hypercall2(int, set_gdt, frame_list, entries); 187} 188 189static inline int __must_check 190HYPERVISOR_stack_switch( 191 unsigned long ss, unsigned long esp) 192{ 193 return _hypercall2(int, stack_switch, ss, esp); 194} 195 196static inline int __must_check 197HYPERVISOR_set_callbacks( 198 unsigned long event_address, unsigned long failsafe_address, 199 unsigned long syscall_address) 200{ 201 return _hypercall3(int, set_callbacks, 202 event_address, failsafe_address, syscall_address); 203} 204 205static inline int 206HYPERVISOR_fpu_taskswitch( 207 int set) 208{ 209 return _hypercall1(int, fpu_taskswitch, set); 210} 211 212static inline int __must_check 213HYPERVISOR_sched_op_compat( 214 int cmd, unsigned long arg) 215{ 216 return _hypercall2(int, sched_op_compat, cmd, arg); 217} 218 219static inline int __must_check 220HYPERVISOR_sched_op( 221 int cmd, void *arg) 222{ 223 return _hypercall2(int, sched_op, cmd, arg); 224} 225 226static inline long __must_check 227HYPERVISOR_set_timer_op( 228 uint64_t timeout) 229{ 230 return _hypercall1(long, set_timer_op, timeout); 231} 232 233static inline int __must_check 234HYPERVISOR_platform_op( 235 struct xen_platform_op *platform_op) 236{ 237 platform_op->interface_version = XENPF_INTERFACE_VERSION; 238 return _hypercall1(int, platform_op, platform_op); 239} 240 241static inline int __must_check 242HYPERVISOR_set_debugreg( 243 unsigned int reg, unsigned long value) 244{ 245 return _hypercall2(int, set_debugreg, reg, value); 246} 247 248static inline unsigned long __must_check 249HYPERVISOR_get_debugreg( 250 unsigned int reg) 251{ 252 return _hypercall1(unsigned long, get_debugreg, reg); 253} 254 255static inline int __must_check 256HYPERVISOR_update_descriptor( 257 unsigned long ma, unsigned long word) 258{ 259 return _hypercall2(int, update_descriptor, ma, word); 260} 261 262static inline int __must_check 263HYPERVISOR_memory_op( 264 unsigned int cmd, void *arg) 265{ 266 return _hypercall2(int, memory_op, cmd, arg); 267} 268 269static inline int __must_check 270HYPERVISOR_multicall( 271 multicall_entry_t *call_list, unsigned int nr_calls) 272{ 273 return _hypercall2(int, multicall, call_list, nr_calls); 274} 275 276static inline int __must_check 277HYPERVISOR_update_va_mapping( 278 unsigned long va, uint64_t new_val, unsigned long flags) 279{ 280 return _hypercall3(int, update_va_mapping, va, new_val, flags); 281} 282 283static inline int __must_check 284HYPERVISOR_event_channel_op( 285 int cmd, void *arg) 286{ 287 int rc = _hypercall2(int, event_channel_op, cmd, arg); 288 289#if CONFIG_XEN_COMPAT <= 0x030002 290 if (__predict_false(rc == -ENOXENSYS)) { 291 struct evtchn_op op; 292 op.cmd = cmd; 293 memcpy(&op.u, arg, sizeof(op.u)); 294 rc = _hypercall1(int, event_channel_op_compat, &op); 295 memcpy(arg, &op.u, sizeof(op.u)); 296 } 297#endif 298 299 return rc; 300} 301 302static inline int __must_check 303HYPERVISOR_xen_version( 304 int cmd, void *arg) 305{ 306 return _hypercall2(int, xen_version, cmd, arg); 307} 308 309static inline int __must_check 310HYPERVISOR_console_io( 311 int cmd, unsigned int count, const char *str) 312{ 313 return _hypercall3(int, console_io, cmd, count, str); 314} 315 316static inline int __must_check 317HYPERVISOR_physdev_op( 318 int cmd, void *arg) 319{ 320 int rc = _hypercall2(int, physdev_op, cmd, arg); 321 322#if CONFIG_XEN_COMPAT <= 0x030002 323 if (__predict_false(rc == -ENOXENSYS)) { 324 struct physdev_op op; 325 op.cmd = cmd; 326 memcpy(&op.u, arg, sizeof(op.u)); 327 rc = _hypercall1(int, physdev_op_compat, &op); 328 memcpy(arg, &op.u, sizeof(op.u)); 329 } 330#endif 331 332 return rc; 333} 334 335static inline int __must_check 336HYPERVISOR_grant_table_op( 337 unsigned int cmd, void *uop, unsigned int count) 338{ 339 return _hypercall3(int, grant_table_op, cmd, uop, count); 340} 341 342static inline int __must_check 343HYPERVISOR_update_va_mapping_otherdomain( 344 unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 345{ 346 return _hypercall4(int, update_va_mapping_otherdomain, va, 347 new_val, flags, domid); 348} 349 350static inline int __must_check 351HYPERVISOR_vm_assist( 352 unsigned int cmd, unsigned int type) 353{ 354 return _hypercall2(int, vm_assist, cmd, type); 355} 356 357static inline int __must_check 358HYPERVISOR_vcpu_op( 359 int cmd, unsigned int vcpuid, void *extra_args) 360{ 361 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 362} 363 364static inline int __must_check 365HYPERVISOR_set_segment_base( 366 int reg, unsigned long value) 367{ 368 return _hypercall2(int, set_segment_base, reg, value); 369} 370 371static inline int __must_check 372HYPERVISOR_suspend( 373 unsigned long srec) 374{ 375 struct sched_shutdown sched_shutdown = { 376 .reason = SHUTDOWN_suspend 377 }; 378 379 int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 380 &sched_shutdown, srec); 381 382#if CONFIG_XEN_COMPAT <= 0x030002 383 if (rc == -ENOXENSYS) 384 rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 385 SHUTDOWN_suspend, srec); 386#endif 387 388 return rc; 389} 390 391#if CONFIG_XEN_COMPAT <= 0x030002 392static inline int 393HYPERVISOR_nmi_op( 394 unsigned long op, void *arg) 395{ 396 return _hypercall2(int, nmi_op, op, arg); 397} 398#endif 399 400#ifndef CONFIG_XEN 401static inline unsigned long __must_check 402HYPERVISOR_hvm_op( 403 int op, void *arg) 404{ 405 return _hypercall2(unsigned long, hvm_op, op, arg); 406} 407#endif 408 409static inline int __must_check 410HYPERVISOR_callback_op( 411 int cmd, const void *arg) 412{ 413 return _hypercall2(int, callback_op, cmd, arg); 414} 415 416static inline int __must_check 417HYPERVISOR_xenoprof_op( 418 int op, void *arg) 419{ 420 return _hypercall2(int, xenoprof_op, op, arg); 421} 422 423static inline int __must_check 424HYPERVISOR_kexec_op( 425 unsigned long op, void *args) 426{ 427 return _hypercall2(int, kexec_op, op, args); 428} 429 430#undef __must_check 431 432#endif /* __MACHINE_XEN_HYPERCALL_H__ */ 433