1/****************************************************************************** 2 * hypercall.h 3 * 4 * Linux-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 37#ifndef __MACHINE_XEN_HYPERCALL_H__ 38#define __MACHINE_XEN_HYPERCALL_H__ 39 40#include <sys/systm.h> 41 42#ifndef __XEN_HYPERVISOR_H__ 43# error "please don't include this file directly" 44#endif 45 46#define __STR(x) #x 47#define STR(x) __STR(x) 48#define ENOXENSYS 38 49#define CONFIG_XEN_COMPAT 0x030002 50#define __must_check 51 52#ifdef XEN 53#define HYPERCALL_STR(name) \ 54 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 55#else 56#define HYPERCALL_STR(name) \ 57 "mov $("STR(__HYPERVISOR_##name)" * 32),%%eax; "\ 58 "add hypercall_stubs(%%rip),%%rax; " \ 59 "call *%%rax" 60#endif 61 62#define _hypercall0(type, name) \ 63({ \ 64 type __res; \ 65 __asm__ volatile ( \ 66 HYPERCALL_STR(name) \ 67 : "=a" (__res) \ 68 : \ 69 : "memory" ); \ 70 __res; \ 71}) 72 73#define _hypercall1(type, name, a1) \ 74({ \ 75 type __res; \ 76 long __ign1; \ 77 __asm__ volatile ( \ 78 HYPERCALL_STR(name) \ 79 : "=a" (__res), "=D" (__ign1) \ 80 : "1" ((long)(a1)) \ 81 : "memory" ); \ 82 __res; \ 83}) 84 85#define _hypercall2(type, name, a1, a2) \ 86({ \ 87 type __res; \ 88 long __ign1, __ign2; \ 89 __asm__ volatile ( \ 90 HYPERCALL_STR(name) \ 91 : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ 92 : "1" ((long)(a1)), "2" ((long)(a2)) \ 93 : "memory" ); \ 94 __res; \ 95}) 96 97#define _hypercall3(type, name, a1, a2, a3) \ 98({ \ 99 type __res; \ 100 long __ign1, __ign2, __ign3; \ 101 __asm__ volatile ( \ 102 HYPERCALL_STR(name) \ 103 : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 104 "=d" (__ign3) \ 105 : "1" ((long)(a1)), "2" ((long)(a2)), \ 106 "3" ((long)(a3)) \ 107 : "memory" ); \ 108 __res; \ 109}) 110 111#define _hypercall4(type, name, a1, a2, a3, a4) \ 112({ \ 113 type __res; \ 114 long __ign1, __ign2, __ign3; \ 115 register long __arg4 __asm__("r10") = (long)(a4); \ 116 __asm__ volatile ( \ 117 HYPERCALL_STR(name) \ 118 : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 119 "=d" (__ign3), "+r" (__arg4) \ 120 : "1" ((long)(a1)), "2" ((long)(a2)), \ 121 "3" ((long)(a3)) \ 122 : "memory" ); \ 123 __res; \ 124}) 125 126#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 127({ \ 128 type __res; \ 129 long __ign1, __ign2, __ign3; \ 130 register long __arg4 __asm__("r10") = (long)(a4); \ 131 register long __arg5 __asm__("r8") = (long)(a5); \ 132 __asm__ volatile ( \ 133 HYPERCALL_STR(name) \ 134 : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 135 "=d" (__ign3), "+r" (__arg4), "+r" (__arg5) \ 136 : "1" ((long)(a1)), "2" ((long)(a2)), \ 137 "3" ((long)(a3)) \ 138 : "memory" ); \ 139 __res; \ 140}) 141 142static inline int __must_check 143HYPERVISOR_set_trap_table( 144 const trap_info_t *table) 145{ 146 return _hypercall1(int, set_trap_table, table); 147} 148 149static inline int __must_check 150HYPERVISOR_mmu_update( 151 mmu_update_t *req, unsigned int count, unsigned int *success_count, 152 domid_t domid) 153{ 154 return _hypercall4(int, mmu_update, req, count, success_count, domid); 155} 156 157static inline int __must_check 158HYPERVISOR_mmuext_op( 159 struct mmuext_op *op, unsigned int count, unsigned int *success_count, 160 domid_t domid) 161{ 162 return _hypercall4(int, mmuext_op, op, count, success_count, domid); 163} 164 165static inline int __must_check 166HYPERVISOR_set_gdt( 167 unsigned long *frame_list, unsigned int entries) 168{ 169 return _hypercall2(int, set_gdt, frame_list, entries); 170} 171 172static inline int __must_check 173HYPERVISOR_stack_switch( 174 unsigned long ss, unsigned long esp) 175{ 176 return _hypercall2(int, stack_switch, ss, esp); 177} 178 179static inline int __must_check 180HYPERVISOR_set_callbacks( 181 unsigned long event_address, unsigned long failsafe_address, 182 unsigned long syscall_address) 183{ 184 return _hypercall3(int, set_callbacks, 185 event_address, failsafe_address, syscall_address); 186} 187 188static inline int 189HYPERVISOR_fpu_taskswitch( 190 int set) 191{ 192 return _hypercall1(int, fpu_taskswitch, set); 193} 194 195static inline int __must_check 196HYPERVISOR_sched_op_compat( 197 int cmd, unsigned long arg) 198{ 199 return _hypercall2(int, sched_op_compat, cmd, arg); 200} 201 202static inline int __must_check 203HYPERVISOR_sched_op( 204 int cmd, void *arg) 205{ 206 return _hypercall2(int, sched_op, cmd, arg); 207} 208 209static inline long __must_check 210HYPERVISOR_set_timer_op( 211 uint64_t timeout) 212{ 213 return _hypercall1(long, set_timer_op, timeout); 214} 215 216static inline int __must_check 217HYPERVISOR_platform_op( 218 struct xen_platform_op *platform_op) 219{ 220 platform_op->interface_version = XENPF_INTERFACE_VERSION; 221 return _hypercall1(int, platform_op, platform_op); 222} 223 224static inline int __must_check 225HYPERVISOR_set_debugreg( 226 unsigned int reg, unsigned long value) 227{ 228 return _hypercall2(int, set_debugreg, reg, value); 229} 230 231static inline unsigned long __must_check 232HYPERVISOR_get_debugreg( 233 unsigned int reg) 234{ 235 return _hypercall1(unsigned long, get_debugreg, reg); 236} 237 238static inline int __must_check 239HYPERVISOR_update_descriptor( 240 unsigned long ma, unsigned long word) 241{ 242 return _hypercall2(int, update_descriptor, ma, word); 243} 244 245static inline int __must_check 246HYPERVISOR_memory_op( 247 unsigned int cmd, void *arg) 248{ 249 return _hypercall2(int, memory_op, cmd, arg); 250} 251 252static inline int __must_check 253HYPERVISOR_multicall( 254 multicall_entry_t *call_list, unsigned int nr_calls) 255{ 256 return _hypercall2(int, multicall, call_list, nr_calls); 257} 258 259static inline int __must_check 260HYPERVISOR_update_va_mapping( 261 unsigned long va, uint64_t new_val, unsigned long flags) 262{ 263 return _hypercall3(int, update_va_mapping, va, new_val, flags); 264} 265 266static inline int __must_check 267HYPERVISOR_event_channel_op( 268 int cmd, void *arg) 269{ 270 int rc = _hypercall2(int, event_channel_op, cmd, arg); 271 272#if CONFIG_XEN_COMPAT <= 0x030002 273 if (unlikely(rc == -ENOXENSYS)) { 274 struct evtchn_op op; 275 op.cmd = cmd; 276 memcpy(&op.u, arg, sizeof(op.u)); 277 rc = _hypercall1(int, event_channel_op_compat, &op); 278 memcpy(arg, &op.u, sizeof(op.u)); 279 } 280#endif 281 282 return rc; 283} 284 285static inline int __must_check 286HYPERVISOR_xen_version( 287 int cmd, void *arg) 288{ 289 return _hypercall2(int, xen_version, cmd, arg); 290} 291 292static inline int __must_check 293HYPERVISOR_console_io( 294 int cmd, unsigned int count, char *str) 295{ 296 return _hypercall3(int, console_io, cmd, count, str); 297} 298 299static inline int __must_check 300HYPERVISOR_physdev_op( 301 int cmd, void *arg) 302{ 303 int rc = _hypercall2(int, physdev_op, cmd, arg); 304 305#if CONFIG_XEN_COMPAT <= 0x030002 306 if (unlikely(rc == -ENOXENSYS)) { 307 struct physdev_op op; 308 op.cmd = cmd; 309 memcpy(&op.u, arg, sizeof(op.u)); 310 rc = _hypercall1(int, physdev_op_compat, &op); 311 memcpy(arg, &op.u, sizeof(op.u)); 312 } 313#endif 314 315 return rc; 316} 317 318static inline int __must_check 319HYPERVISOR_grant_table_op( 320 unsigned int cmd, void *uop, unsigned int count) 321{ 322 return _hypercall3(int, grant_table_op, cmd, uop, count); 323} 324 325static inline int __must_check 326HYPERVISOR_update_va_mapping_otherdomain( 327 unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 328{ 329 return _hypercall4(int, update_va_mapping_otherdomain, va, 330 new_val, flags, domid); 331} 332 333static inline int __must_check 334HYPERVISOR_vm_assist( 335 unsigned int cmd, unsigned int type) 336{ 337 return _hypercall2(int, vm_assist, cmd, type); 338} 339 340static inline int __must_check 341HYPERVISOR_vcpu_op( 342 int cmd, unsigned int vcpuid, void *extra_args) 343{ 344 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 345} 346 347static inline int __must_check 348HYPERVISOR_set_segment_base( 349 int reg, unsigned long value) 350{ 351 return _hypercall2(int, set_segment_base, reg, value); 352} 353 354static inline int __must_check 355HYPERVISOR_suspend( 356 unsigned long srec) 357{ 358 struct sched_shutdown sched_shutdown = { 359 .reason = SHUTDOWN_suspend 360 }; 361 362 int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 363 &sched_shutdown, srec); 364 365#if CONFIG_XEN_COMPAT <= 0x030002 366 if (rc == -ENOXENSYS) 367 rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 368 SHUTDOWN_suspend, srec); 369#endif 370 371 return rc; 372} 373 374#if CONFIG_XEN_COMPAT <= 0x030002 375static inline int 376HYPERVISOR_nmi_op( 377 unsigned long op, void *arg) 378{ 379 return _hypercall2(int, nmi_op, op, arg); 380} 381#endif 382 383#ifndef CONFIG_XEN 384static inline unsigned long __must_check 385HYPERVISOR_hvm_op( 386 int op, void *arg) 387{ 388 return _hypercall2(unsigned long, hvm_op, op, arg); 389} 390#endif 391 392static inline int __must_check 393HYPERVISOR_callback_op( 394 int cmd, const void *arg) 395{ 396 return _hypercall2(int, callback_op, cmd, arg); 397} 398 399static inline int __must_check 400HYPERVISOR_xenoprof_op( 401 int op, void *arg) 402{ 403 return _hypercall2(int, xenoprof_op, op, arg); 404} 405 406static inline int __must_check 407HYPERVISOR_kexec_op( 408 unsigned long op, void *args) 409{ 410 return _hypercall2(int, kexec_op, op, args); 411} 412 413#undef __must_check 414 415#endif /* __MACHINE_XEN_HYPERCALL_H__ */ 416