1183906Skmacy/****************************************************************************** 2183906Skmacy * hypercall.h 3183906Skmacy * 4183906Skmacy * Linux-specific hypervisor handling. 5183906Skmacy * 6183906Skmacy * Copyright (c) 2002-2004, K A Fraser 7183906Skmacy * 8185386Sdfr * 64-bit updates: 9185386Sdfr * Benjamin Liu <benjamin.liu@intel.com> 10185386Sdfr * Jun Nakajima <jun.nakajima@intel.com> 11183906Skmacy * 12185386Sdfr * This program is free software; you can redistribute it and/or 13185386Sdfr * modify it under the terms of the GNU General Public License version 2 14185386Sdfr * as published by the Free Software Foundation; or, when distributed 15185386Sdfr * separately from the Linux kernel or incorporated into other 16185386Sdfr * software packages, subject to the following license: 17185386Sdfr * 18183906Skmacy * Permission is hereby granted, free of charge, to any person obtaining a copy 19183906Skmacy * of this source file (the "Software"), to deal in the Software without 20183906Skmacy * restriction, including without limitation the rights to use, copy, modify, 21183906Skmacy * merge, publish, distribute, sublicense, and/or sell copies of the Software, 22183906Skmacy * and to permit persons to whom the Software is furnished to do so, subject to 23183906Skmacy * the following conditions: 24183906Skmacy * 25183906Skmacy * The above copyright notice and this permission notice shall be included in 26183906Skmacy * all copies or substantial portions of the Software. 27183906Skmacy * 28183906Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29183906Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30183906Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31183906Skmacy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32183906Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 33183906Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 34183906Skmacy * IN THE SOFTWARE. 35183906Skmacy */ 36183906Skmacy 37185637Sdfr#ifndef __MACHINE_XEN_HYPERCALL_H__ 38185637Sdfr#define __MACHINE_XEN_HYPERCALL_H__ 39183906Skmacy 40183906Skmacy#include <sys/systm.h> 41183906Skmacy 42185637Sdfr#ifndef __XEN_HYPERVISOR_H__ 43185386Sdfr# error "please don't include this file directly" 44185386Sdfr#endif 45185386Sdfr 46183906Skmacy#define __STR(x) #x 47183906Skmacy#define STR(x) __STR(x) 48183906Skmacy#define ENOXENSYS 38 49183906Skmacy#define CONFIG_XEN_COMPAT 0x030002 50185386Sdfr#define __must_check 51183906Skmacy 52185386Sdfr#ifdef XEN 53185386Sdfr#define HYPERCALL_STR(name) \ 54185386Sdfr "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 55183906Skmacy#else 56185386Sdfr#define HYPERCALL_STR(name) \ 57185386Sdfr "mov $("STR(__HYPERVISOR_##name)" * 32),%%eax; "\ 58185386Sdfr "add hypercall_stubs(%%rip),%%rax; " \ 59185386Sdfr "call *%%rax" 60183906Skmacy#endif 61183906Skmacy 62185386Sdfr#define _hypercall0(type, name) \ 63185386Sdfr({ \ 64185386Sdfr type __res; \ 65185386Sdfr __asm__ volatile ( \ 66185386Sdfr HYPERCALL_STR(name) \ 67185386Sdfr : "=a" (__res) \ 68185386Sdfr : \ 69185386Sdfr : "memory" ); \ 70185386Sdfr __res; \ 71183906Skmacy}) 72183906Skmacy 73185386Sdfr#define _hypercall1(type, name, a1) \ 74185386Sdfr({ \ 75185386Sdfr type __res; \ 76185386Sdfr long __ign1; \ 77185386Sdfr __asm__ volatile ( \ 78185386Sdfr HYPERCALL_STR(name) \ 79185386Sdfr : "=a" (__res), "=D" (__ign1) \ 80185386Sdfr : "1" ((long)(a1)) \ 81185386Sdfr : "memory" ); \ 82185386Sdfr __res; \ 83183906Skmacy}) 84183906Skmacy 85185386Sdfr#define _hypercall2(type, name, a1, a2) \ 86185386Sdfr({ \ 87185386Sdfr type __res; \ 88185386Sdfr long __ign1, __ign2; \ 89185386Sdfr __asm__ volatile ( \ 90185386Sdfr HYPERCALL_STR(name) \ 91185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ 92185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)) \ 93185386Sdfr : "memory" ); \ 94185386Sdfr __res; \ 95183906Skmacy}) 96183906Skmacy 97185386Sdfr#define _hypercall3(type, name, a1, a2, a3) \ 98185386Sdfr({ \ 99185386Sdfr type __res; \ 100185386Sdfr long __ign1, __ign2, __ign3; \ 101185386Sdfr __asm__ volatile ( \ 102185386Sdfr HYPERCALL_STR(name) \ 103185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 104185386Sdfr "=d" (__ign3) \ 105185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 106185386Sdfr "3" ((long)(a3)) \ 107185386Sdfr : "memory" ); \ 108185386Sdfr __res; \ 109183906Skmacy}) 110183906Skmacy 111185386Sdfr#define _hypercall4(type, name, a1, a2, a3, a4) \ 112185386Sdfr({ \ 113185386Sdfr type __res; \ 114185386Sdfr long __ign1, __ign2, __ign3; \ 115185386Sdfr register long __arg4 __asm__("r10") = (long)(a4); \ 116185386Sdfr __asm__ volatile ( \ 117185386Sdfr HYPERCALL_STR(name) \ 118185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 119185386Sdfr "=d" (__ign3), "+r" (__arg4) \ 120185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 121185386Sdfr "3" ((long)(a3)) \ 122185386Sdfr : "memory" ); \ 123185386Sdfr __res; \ 124183906Skmacy}) 125183906Skmacy 126185386Sdfr#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 127185386Sdfr({ \ 128185386Sdfr type __res; \ 129185386Sdfr long __ign1, __ign2, __ign3; \ 130185386Sdfr register long __arg4 __asm__("r10") = (long)(a4); \ 131185386Sdfr register long __arg5 __asm__("r8") = (long)(a5); \ 132185386Sdfr __asm__ volatile ( \ 133185386Sdfr HYPERCALL_STR(name) \ 134185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 135185386Sdfr "=d" (__ign3), "+r" (__arg4), "+r" (__arg5) \ 136185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 137185386Sdfr "3" ((long)(a3)) \ 138185386Sdfr : "memory" ); \ 139185386Sdfr __res; \ 140185386Sdfr}) 141183906Skmacy 142185386Sdfrstatic inline int __must_check 143183906SkmacyHYPERVISOR_set_trap_table( 144185386Sdfr const trap_info_t *table) 145183906Skmacy{ 146183906Skmacy return _hypercall1(int, set_trap_table, table); 147183906Skmacy} 148183906Skmacy 149185386Sdfrstatic inline int __must_check 150183906SkmacyHYPERVISOR_mmu_update( 151185386Sdfr mmu_update_t *req, unsigned int count, unsigned int *success_count, 152185386Sdfr domid_t domid) 153183906Skmacy{ 154183906Skmacy return _hypercall4(int, mmu_update, req, count, success_count, domid); 155183906Skmacy} 156183906Skmacy 157185386Sdfrstatic inline int __must_check 158183906SkmacyHYPERVISOR_mmuext_op( 159185386Sdfr struct mmuext_op *op, unsigned int count, unsigned int *success_count, 160185386Sdfr domid_t domid) 161183906Skmacy{ 162183906Skmacy return _hypercall4(int, mmuext_op, op, count, success_count, domid); 163183906Skmacy} 164183906Skmacy 165185386Sdfrstatic inline int __must_check 166183906SkmacyHYPERVISOR_set_gdt( 167185386Sdfr unsigned long *frame_list, unsigned int entries) 168183906Skmacy{ 169183906Skmacy return _hypercall2(int, set_gdt, frame_list, entries); 170183906Skmacy} 171183906Skmacy 172185386Sdfrstatic inline int __must_check 173183906SkmacyHYPERVISOR_stack_switch( 174183906Skmacy unsigned long ss, unsigned long esp) 175183906Skmacy{ 176183906Skmacy return _hypercall2(int, stack_switch, ss, esp); 177183906Skmacy} 178183906Skmacy 179185386Sdfrstatic inline int __must_check 180183906SkmacyHYPERVISOR_set_callbacks( 181185386Sdfr unsigned long event_address, unsigned long failsafe_address, 182185386Sdfr unsigned long syscall_address) 183183906Skmacy{ 184185386Sdfr return _hypercall3(int, set_callbacks, 185185386Sdfr event_address, failsafe_address, syscall_address); 186183906Skmacy} 187183906Skmacy 188183906Skmacystatic inline int 189183906SkmacyHYPERVISOR_fpu_taskswitch( 190183906Skmacy int set) 191183906Skmacy{ 192183906Skmacy return _hypercall1(int, fpu_taskswitch, set); 193183906Skmacy} 194183906Skmacy 195185386Sdfrstatic inline int __must_check 196183906SkmacyHYPERVISOR_sched_op_compat( 197183906Skmacy int cmd, unsigned long arg) 198183906Skmacy{ 199183906Skmacy return _hypercall2(int, sched_op_compat, cmd, arg); 200183906Skmacy} 201183906Skmacy 202185386Sdfrstatic inline int __must_check 203183906SkmacyHYPERVISOR_sched_op( 204183906Skmacy int cmd, void *arg) 205183906Skmacy{ 206183906Skmacy return _hypercall2(int, sched_op, cmd, arg); 207183906Skmacy} 208183906Skmacy 209185386Sdfrstatic inline long __must_check 210183906SkmacyHYPERVISOR_set_timer_op( 211183906Skmacy uint64_t timeout) 212183906Skmacy{ 213185386Sdfr return _hypercall1(long, set_timer_op, timeout); 214183906Skmacy} 215185386Sdfr 216185386Sdfrstatic inline int __must_check 217183906SkmacyHYPERVISOR_platform_op( 218185386Sdfr struct xen_platform_op *platform_op) 219183906Skmacy{ 220185386Sdfr platform_op->interface_version = XENPF_INTERFACE_VERSION; 221185386Sdfr return _hypercall1(int, platform_op, platform_op); 222183906Skmacy} 223185386Sdfr 224185386Sdfrstatic inline int __must_check 225183906SkmacyHYPERVISOR_set_debugreg( 226185386Sdfr unsigned int reg, unsigned long value) 227183906Skmacy{ 228183906Skmacy return _hypercall2(int, set_debugreg, reg, value); 229183906Skmacy} 230183906Skmacy 231185386Sdfrstatic inline unsigned long __must_check 232183906SkmacyHYPERVISOR_get_debugreg( 233185386Sdfr unsigned int reg) 234183906Skmacy{ 235183906Skmacy return _hypercall1(unsigned long, get_debugreg, reg); 236183906Skmacy} 237183906Skmacy 238185386Sdfrstatic inline int __must_check 239183906SkmacyHYPERVISOR_update_descriptor( 240185386Sdfr unsigned long ma, unsigned long word) 241183906Skmacy{ 242185386Sdfr return _hypercall2(int, update_descriptor, ma, word); 243183906Skmacy} 244183906Skmacy 245185386Sdfrstatic inline int __must_check 246183906SkmacyHYPERVISOR_memory_op( 247183906Skmacy unsigned int cmd, void *arg) 248183906Skmacy{ 249183906Skmacy return _hypercall2(int, memory_op, cmd, arg); 250183906Skmacy} 251183906Skmacy 252185386Sdfrstatic inline int __must_check 253183906SkmacyHYPERVISOR_multicall( 254185386Sdfr multicall_entry_t *call_list, unsigned int nr_calls) 255183906Skmacy{ 256183906Skmacy return _hypercall2(int, multicall, call_list, nr_calls); 257183906Skmacy} 258183906Skmacy 259185386Sdfrstatic inline int __must_check 260183906SkmacyHYPERVISOR_update_va_mapping( 261183906Skmacy unsigned long va, uint64_t new_val, unsigned long flags) 262183906Skmacy{ 263185386Sdfr return _hypercall3(int, update_va_mapping, va, new_val, flags); 264183906Skmacy} 265183906Skmacy 266185386Sdfrstatic inline int __must_check 267183906SkmacyHYPERVISOR_event_channel_op( 268183906Skmacy int cmd, void *arg) 269183906Skmacy{ 270183906Skmacy int rc = _hypercall2(int, event_channel_op, cmd, arg); 271183906Skmacy 272183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 273185386Sdfr if (unlikely(rc == -ENOXENSYS)) { 274183906Skmacy struct evtchn_op op; 275183906Skmacy op.cmd = cmd; 276183906Skmacy memcpy(&op.u, arg, sizeof(op.u)); 277183906Skmacy rc = _hypercall1(int, event_channel_op_compat, &op); 278183906Skmacy memcpy(arg, &op.u, sizeof(op.u)); 279183906Skmacy } 280183906Skmacy#endif 281185386Sdfr 282185386Sdfr return rc; 283183906Skmacy} 284183906Skmacy 285185386Sdfrstatic inline int __must_check 286183906SkmacyHYPERVISOR_xen_version( 287183906Skmacy int cmd, void *arg) 288183906Skmacy{ 289183906Skmacy return _hypercall2(int, xen_version, cmd, arg); 290183906Skmacy} 291183906Skmacy 292185386Sdfrstatic inline int __must_check 293183906SkmacyHYPERVISOR_console_io( 294185386Sdfr int cmd, unsigned int count, char *str) 295183906Skmacy{ 296183906Skmacy return _hypercall3(int, console_io, cmd, count, str); 297183906Skmacy} 298183906Skmacy 299185386Sdfrstatic inline int __must_check 300183906SkmacyHYPERVISOR_physdev_op( 301183906Skmacy int cmd, void *arg) 302183906Skmacy{ 303183906Skmacy int rc = _hypercall2(int, physdev_op, cmd, arg); 304185386Sdfr 305183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 306185386Sdfr if (unlikely(rc == -ENOXENSYS)) { 307183906Skmacy struct physdev_op op; 308183906Skmacy op.cmd = cmd; 309183906Skmacy memcpy(&op.u, arg, sizeof(op.u)); 310183906Skmacy rc = _hypercall1(int, physdev_op_compat, &op); 311183906Skmacy memcpy(arg, &op.u, sizeof(op.u)); 312183906Skmacy } 313183906Skmacy#endif 314185386Sdfr 315185386Sdfr return rc; 316183906Skmacy} 317183906Skmacy 318185386Sdfrstatic inline int __must_check 319183906SkmacyHYPERVISOR_grant_table_op( 320183906Skmacy unsigned int cmd, void *uop, unsigned int count) 321183906Skmacy{ 322183906Skmacy return _hypercall3(int, grant_table_op, cmd, uop, count); 323183906Skmacy} 324183906Skmacy 325185386Sdfrstatic inline int __must_check 326183906SkmacyHYPERVISOR_update_va_mapping_otherdomain( 327183906Skmacy unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 328183906Skmacy{ 329185386Sdfr return _hypercall4(int, update_va_mapping_otherdomain, va, 330185386Sdfr new_val, flags, domid); 331183906Skmacy} 332183906Skmacy 333185386Sdfrstatic inline int __must_check 334183906SkmacyHYPERVISOR_vm_assist( 335183906Skmacy unsigned int cmd, unsigned int type) 336183906Skmacy{ 337183906Skmacy return _hypercall2(int, vm_assist, cmd, type); 338183906Skmacy} 339183906Skmacy 340185386Sdfrstatic inline int __must_check 341183906SkmacyHYPERVISOR_vcpu_op( 342185386Sdfr int cmd, unsigned int vcpuid, void *extra_args) 343183906Skmacy{ 344183906Skmacy return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 345183906Skmacy} 346183906Skmacy 347185386Sdfrstatic inline int __must_check 348185386SdfrHYPERVISOR_set_segment_base( 349185386Sdfr int reg, unsigned long value) 350185386Sdfr{ 351185386Sdfr return _hypercall2(int, set_segment_base, reg, value); 352185386Sdfr} 353185386Sdfr 354185386Sdfrstatic inline int __must_check 355183906SkmacyHYPERVISOR_suspend( 356183906Skmacy unsigned long srec) 357183906Skmacy{ 358183906Skmacy struct sched_shutdown sched_shutdown = { 359183906Skmacy .reason = SHUTDOWN_suspend 360183906Skmacy }; 361185386Sdfr 362183906Skmacy int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 363185386Sdfr &sched_shutdown, srec); 364185386Sdfr 365183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 366183906Skmacy if (rc == -ENOXENSYS) 367183906Skmacy rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 368183906Skmacy SHUTDOWN_suspend, srec); 369185386Sdfr#endif 370185386Sdfr 371185386Sdfr return rc; 372183906Skmacy} 373183906Skmacy 374183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 375183906Skmacystatic inline int 376183906SkmacyHYPERVISOR_nmi_op( 377185386Sdfr unsigned long op, void *arg) 378183906Skmacy{ 379185386Sdfr return _hypercall2(int, nmi_op, op, arg); 380183906Skmacy} 381183906Skmacy#endif 382183906Skmacy 383183906Skmacy#ifndef CONFIG_XEN 384185386Sdfrstatic inline unsigned long __must_check 385183906SkmacyHYPERVISOR_hvm_op( 386183906Skmacy int op, void *arg) 387183906Skmacy{ 388183906Skmacy return _hypercall2(unsigned long, hvm_op, op, arg); 389183906Skmacy} 390183906Skmacy#endif 391183906Skmacy 392185386Sdfrstatic inline int __must_check 393185386SdfrHYPERVISOR_callback_op( 394185386Sdfr int cmd, const void *arg) 395185386Sdfr{ 396185386Sdfr return _hypercall2(int, callback_op, cmd, arg); 397185386Sdfr} 398185386Sdfr 399185386Sdfrstatic inline int __must_check 400183906SkmacyHYPERVISOR_xenoprof_op( 401185386Sdfr int op, void *arg) 402183906Skmacy{ 403185386Sdfr return _hypercall2(int, xenoprof_op, op, arg); 404183906Skmacy} 405183906Skmacy 406185386Sdfrstatic inline int __must_check 407183906SkmacyHYPERVISOR_kexec_op( 408185386Sdfr unsigned long op, void *args) 409183906Skmacy{ 410185386Sdfr return _hypercall2(int, kexec_op, op, args); 411183906Skmacy} 412185386Sdfr 413185386Sdfr#undef __must_check 414185386Sdfr 415185637Sdfr#endif /* __MACHINE_XEN_HYPERCALL_H__ */ 416