1183906Skmacy/****************************************************************************** 2183906Skmacy * hypercall.h 3183906Skmacy * 4255040Sgibbs * FreeBSD-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. 35255040Sgibbs * 36255040Sgibbs * $FreeBSD$ 37183906Skmacy */ 38183906Skmacy 39185637Sdfr#ifndef __MACHINE_XEN_HYPERCALL_H__ 40185637Sdfr#define __MACHINE_XEN_HYPERCALL_H__ 41183906Skmacy 42183906Skmacy#include <sys/systm.h> 43183906Skmacy 44185637Sdfr#ifndef __XEN_HYPERVISOR_H__ 45185386Sdfr# error "please don't include this file directly" 46185386Sdfr#endif 47185386Sdfr 48183906Skmacy#define __STR(x) #x 49183906Skmacy#define STR(x) __STR(x) 50183906Skmacy#define ENOXENSYS 38 51183906Skmacy#define CONFIG_XEN_COMPAT 0x030002 52185386Sdfr#define __must_check 53183906Skmacy 54185386Sdfr#ifdef XEN 55185386Sdfr#define HYPERCALL_STR(name) \ 56185386Sdfr "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 57183906Skmacy#else 58185386Sdfr#define HYPERCALL_STR(name) \ 59185386Sdfr "mov $("STR(__HYPERVISOR_##name)" * 32),%%eax; "\ 60185386Sdfr "add hypercall_stubs(%%rip),%%rax; " \ 61185386Sdfr "call *%%rax" 62183906Skmacy#endif 63183906Skmacy 64185386Sdfr#define _hypercall0(type, name) \ 65185386Sdfr({ \ 66185386Sdfr type __res; \ 67185386Sdfr __asm__ volatile ( \ 68185386Sdfr HYPERCALL_STR(name) \ 69185386Sdfr : "=a" (__res) \ 70185386Sdfr : \ 71185386Sdfr : "memory" ); \ 72185386Sdfr __res; \ 73183906Skmacy}) 74183906Skmacy 75185386Sdfr#define _hypercall1(type, name, a1) \ 76185386Sdfr({ \ 77185386Sdfr type __res; \ 78185386Sdfr long __ign1; \ 79185386Sdfr __asm__ volatile ( \ 80185386Sdfr HYPERCALL_STR(name) \ 81185386Sdfr : "=a" (__res), "=D" (__ign1) \ 82185386Sdfr : "1" ((long)(a1)) \ 83185386Sdfr : "memory" ); \ 84185386Sdfr __res; \ 85183906Skmacy}) 86183906Skmacy 87185386Sdfr#define _hypercall2(type, name, a1, a2) \ 88185386Sdfr({ \ 89185386Sdfr type __res; \ 90185386Sdfr long __ign1, __ign2; \ 91185386Sdfr __asm__ volatile ( \ 92185386Sdfr HYPERCALL_STR(name) \ 93185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ 94185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)) \ 95185386Sdfr : "memory" ); \ 96185386Sdfr __res; \ 97183906Skmacy}) 98183906Skmacy 99185386Sdfr#define _hypercall3(type, name, a1, a2, a3) \ 100185386Sdfr({ \ 101185386Sdfr type __res; \ 102185386Sdfr long __ign1, __ign2, __ign3; \ 103185386Sdfr __asm__ volatile ( \ 104185386Sdfr HYPERCALL_STR(name) \ 105185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 106185386Sdfr "=d" (__ign3) \ 107185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 108185386Sdfr "3" ((long)(a3)) \ 109185386Sdfr : "memory" ); \ 110185386Sdfr __res; \ 111183906Skmacy}) 112183906Skmacy 113185386Sdfr#define _hypercall4(type, name, a1, a2, a3, a4) \ 114185386Sdfr({ \ 115185386Sdfr type __res; \ 116185386Sdfr long __ign1, __ign2, __ign3; \ 117185386Sdfr register long __arg4 __asm__("r10") = (long)(a4); \ 118185386Sdfr __asm__ volatile ( \ 119185386Sdfr HYPERCALL_STR(name) \ 120185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 121185386Sdfr "=d" (__ign3), "+r" (__arg4) \ 122185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 123185386Sdfr "3" ((long)(a3)) \ 124185386Sdfr : "memory" ); \ 125185386Sdfr __res; \ 126183906Skmacy}) 127183906Skmacy 128185386Sdfr#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 129185386Sdfr({ \ 130185386Sdfr type __res; \ 131185386Sdfr long __ign1, __ign2, __ign3; \ 132185386Sdfr register long __arg4 __asm__("r10") = (long)(a4); \ 133185386Sdfr register long __arg5 __asm__("r8") = (long)(a5); \ 134185386Sdfr __asm__ volatile ( \ 135185386Sdfr HYPERCALL_STR(name) \ 136185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 137185386Sdfr "=d" (__ign3), "+r" (__arg4), "+r" (__arg5) \ 138185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 139185386Sdfr "3" ((long)(a3)) \ 140185386Sdfr : "memory" ); \ 141185386Sdfr __res; \ 142185386Sdfr}) 143183906Skmacy 144185386Sdfrstatic inline int __must_check 145183906SkmacyHYPERVISOR_set_trap_table( 146185386Sdfr const trap_info_t *table) 147183906Skmacy{ 148183906Skmacy return _hypercall1(int, set_trap_table, table); 149183906Skmacy} 150183906Skmacy 151185386Sdfrstatic inline int __must_check 152183906SkmacyHYPERVISOR_mmu_update( 153185386Sdfr mmu_update_t *req, unsigned int count, unsigned int *success_count, 154185386Sdfr domid_t domid) 155183906Skmacy{ 156183906Skmacy return _hypercall4(int, mmu_update, req, count, success_count, domid); 157183906Skmacy} 158183906Skmacy 159185386Sdfrstatic inline int __must_check 160183906SkmacyHYPERVISOR_mmuext_op( 161185386Sdfr struct mmuext_op *op, unsigned int count, unsigned int *success_count, 162185386Sdfr domid_t domid) 163183906Skmacy{ 164183906Skmacy return _hypercall4(int, mmuext_op, op, count, success_count, domid); 165183906Skmacy} 166183906Skmacy 167185386Sdfrstatic inline int __must_check 168183906SkmacyHYPERVISOR_set_gdt( 169185386Sdfr unsigned long *frame_list, unsigned int entries) 170183906Skmacy{ 171183906Skmacy return _hypercall2(int, set_gdt, frame_list, entries); 172183906Skmacy} 173183906Skmacy 174185386Sdfrstatic inline int __must_check 175183906SkmacyHYPERVISOR_stack_switch( 176183906Skmacy unsigned long ss, unsigned long esp) 177183906Skmacy{ 178183906Skmacy return _hypercall2(int, stack_switch, ss, esp); 179183906Skmacy} 180183906Skmacy 181185386Sdfrstatic inline int __must_check 182183906SkmacyHYPERVISOR_set_callbacks( 183185386Sdfr unsigned long event_address, unsigned long failsafe_address, 184185386Sdfr unsigned long syscall_address) 185183906Skmacy{ 186185386Sdfr return _hypercall3(int, set_callbacks, 187185386Sdfr event_address, failsafe_address, syscall_address); 188183906Skmacy} 189183906Skmacy 190183906Skmacystatic inline int 191183906SkmacyHYPERVISOR_fpu_taskswitch( 192183906Skmacy int set) 193183906Skmacy{ 194183906Skmacy return _hypercall1(int, fpu_taskswitch, set); 195183906Skmacy} 196183906Skmacy 197185386Sdfrstatic inline int __must_check 198183906SkmacyHYPERVISOR_sched_op_compat( 199183906Skmacy int cmd, unsigned long arg) 200183906Skmacy{ 201183906Skmacy return _hypercall2(int, sched_op_compat, cmd, arg); 202183906Skmacy} 203183906Skmacy 204185386Sdfrstatic inline int __must_check 205183906SkmacyHYPERVISOR_sched_op( 206183906Skmacy int cmd, void *arg) 207183906Skmacy{ 208183906Skmacy return _hypercall2(int, sched_op, cmd, arg); 209183906Skmacy} 210183906Skmacy 211185386Sdfrstatic inline long __must_check 212183906SkmacyHYPERVISOR_set_timer_op( 213183906Skmacy uint64_t timeout) 214183906Skmacy{ 215185386Sdfr return _hypercall1(long, set_timer_op, timeout); 216183906Skmacy} 217185386Sdfr 218185386Sdfrstatic inline int __must_check 219183906SkmacyHYPERVISOR_platform_op( 220185386Sdfr struct xen_platform_op *platform_op) 221183906Skmacy{ 222185386Sdfr platform_op->interface_version = XENPF_INTERFACE_VERSION; 223185386Sdfr return _hypercall1(int, platform_op, platform_op); 224183906Skmacy} 225185386Sdfr 226185386Sdfrstatic inline int __must_check 227183906SkmacyHYPERVISOR_set_debugreg( 228185386Sdfr unsigned int reg, unsigned long value) 229183906Skmacy{ 230183906Skmacy return _hypercall2(int, set_debugreg, reg, value); 231183906Skmacy} 232183906Skmacy 233185386Sdfrstatic inline unsigned long __must_check 234183906SkmacyHYPERVISOR_get_debugreg( 235185386Sdfr unsigned int reg) 236183906Skmacy{ 237183906Skmacy return _hypercall1(unsigned long, get_debugreg, reg); 238183906Skmacy} 239183906Skmacy 240185386Sdfrstatic inline int __must_check 241183906SkmacyHYPERVISOR_update_descriptor( 242185386Sdfr unsigned long ma, unsigned long word) 243183906Skmacy{ 244185386Sdfr return _hypercall2(int, update_descriptor, ma, word); 245183906Skmacy} 246183906Skmacy 247185386Sdfrstatic inline int __must_check 248183906SkmacyHYPERVISOR_memory_op( 249183906Skmacy unsigned int cmd, void *arg) 250183906Skmacy{ 251183906Skmacy return _hypercall2(int, memory_op, cmd, arg); 252183906Skmacy} 253183906Skmacy 254185386Sdfrstatic inline int __must_check 255183906SkmacyHYPERVISOR_multicall( 256185386Sdfr multicall_entry_t *call_list, unsigned int nr_calls) 257183906Skmacy{ 258183906Skmacy return _hypercall2(int, multicall, call_list, nr_calls); 259183906Skmacy} 260183906Skmacy 261185386Sdfrstatic inline int __must_check 262183906SkmacyHYPERVISOR_update_va_mapping( 263183906Skmacy unsigned long va, uint64_t new_val, unsigned long flags) 264183906Skmacy{ 265185386Sdfr return _hypercall3(int, update_va_mapping, va, new_val, flags); 266183906Skmacy} 267183906Skmacy 268185386Sdfrstatic inline int __must_check 269183906SkmacyHYPERVISOR_event_channel_op( 270183906Skmacy int cmd, void *arg) 271183906Skmacy{ 272183906Skmacy int rc = _hypercall2(int, event_channel_op, cmd, arg); 273183906Skmacy 274183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 275255040Sgibbs if (__predict_false(rc == -ENOXENSYS)) { 276183906Skmacy struct evtchn_op op; 277183906Skmacy op.cmd = cmd; 278183906Skmacy memcpy(&op.u, arg, sizeof(op.u)); 279183906Skmacy rc = _hypercall1(int, event_channel_op_compat, &op); 280183906Skmacy memcpy(arg, &op.u, sizeof(op.u)); 281183906Skmacy } 282183906Skmacy#endif 283185386Sdfr 284185386Sdfr return rc; 285183906Skmacy} 286183906Skmacy 287185386Sdfrstatic inline int __must_check 288183906SkmacyHYPERVISOR_xen_version( 289183906Skmacy int cmd, void *arg) 290183906Skmacy{ 291183906Skmacy return _hypercall2(int, xen_version, cmd, arg); 292183906Skmacy} 293183906Skmacy 294185386Sdfrstatic inline int __must_check 295183906SkmacyHYPERVISOR_console_io( 296185386Sdfr int cmd, unsigned int count, char *str) 297183906Skmacy{ 298183906Skmacy return _hypercall3(int, console_io, cmd, count, str); 299183906Skmacy} 300183906Skmacy 301185386Sdfrstatic inline int __must_check 302183906SkmacyHYPERVISOR_physdev_op( 303183906Skmacy int cmd, void *arg) 304183906Skmacy{ 305183906Skmacy int rc = _hypercall2(int, physdev_op, cmd, arg); 306185386Sdfr 307183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 308255040Sgibbs if (__predict_false(rc == -ENOXENSYS)) { 309183906Skmacy struct physdev_op op; 310183906Skmacy op.cmd = cmd; 311183906Skmacy memcpy(&op.u, arg, sizeof(op.u)); 312183906Skmacy rc = _hypercall1(int, physdev_op_compat, &op); 313183906Skmacy memcpy(arg, &op.u, sizeof(op.u)); 314183906Skmacy } 315183906Skmacy#endif 316185386Sdfr 317185386Sdfr return rc; 318183906Skmacy} 319183906Skmacy 320185386Sdfrstatic inline int __must_check 321183906SkmacyHYPERVISOR_grant_table_op( 322183906Skmacy unsigned int cmd, void *uop, unsigned int count) 323183906Skmacy{ 324183906Skmacy return _hypercall3(int, grant_table_op, cmd, uop, count); 325183906Skmacy} 326183906Skmacy 327185386Sdfrstatic inline int __must_check 328183906SkmacyHYPERVISOR_update_va_mapping_otherdomain( 329183906Skmacy unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 330183906Skmacy{ 331185386Sdfr return _hypercall4(int, update_va_mapping_otherdomain, va, 332185386Sdfr new_val, flags, domid); 333183906Skmacy} 334183906Skmacy 335185386Sdfrstatic inline int __must_check 336183906SkmacyHYPERVISOR_vm_assist( 337183906Skmacy unsigned int cmd, unsigned int type) 338183906Skmacy{ 339183906Skmacy return _hypercall2(int, vm_assist, cmd, type); 340183906Skmacy} 341183906Skmacy 342185386Sdfrstatic inline int __must_check 343183906SkmacyHYPERVISOR_vcpu_op( 344185386Sdfr int cmd, unsigned int vcpuid, void *extra_args) 345183906Skmacy{ 346183906Skmacy return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 347183906Skmacy} 348183906Skmacy 349185386Sdfrstatic inline int __must_check 350185386SdfrHYPERVISOR_set_segment_base( 351185386Sdfr int reg, unsigned long value) 352185386Sdfr{ 353185386Sdfr return _hypercall2(int, set_segment_base, reg, value); 354185386Sdfr} 355185386Sdfr 356185386Sdfrstatic inline int __must_check 357183906SkmacyHYPERVISOR_suspend( 358183906Skmacy unsigned long srec) 359183906Skmacy{ 360183906Skmacy struct sched_shutdown sched_shutdown = { 361183906Skmacy .reason = SHUTDOWN_suspend 362183906Skmacy }; 363185386Sdfr 364183906Skmacy int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 365185386Sdfr &sched_shutdown, srec); 366185386Sdfr 367183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 368183906Skmacy if (rc == -ENOXENSYS) 369183906Skmacy rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 370183906Skmacy SHUTDOWN_suspend, srec); 371185386Sdfr#endif 372185386Sdfr 373185386Sdfr return rc; 374183906Skmacy} 375183906Skmacy 376183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 377183906Skmacystatic inline int 378183906SkmacyHYPERVISOR_nmi_op( 379185386Sdfr unsigned long op, void *arg) 380183906Skmacy{ 381185386Sdfr return _hypercall2(int, nmi_op, op, arg); 382183906Skmacy} 383183906Skmacy#endif 384183906Skmacy 385183906Skmacy#ifndef CONFIG_XEN 386185386Sdfrstatic inline unsigned long __must_check 387183906SkmacyHYPERVISOR_hvm_op( 388183906Skmacy int op, void *arg) 389183906Skmacy{ 390183906Skmacy return _hypercall2(unsigned long, hvm_op, op, arg); 391183906Skmacy} 392183906Skmacy#endif 393183906Skmacy 394185386Sdfrstatic inline int __must_check 395185386SdfrHYPERVISOR_callback_op( 396185386Sdfr int cmd, const void *arg) 397185386Sdfr{ 398185386Sdfr return _hypercall2(int, callback_op, cmd, arg); 399185386Sdfr} 400185386Sdfr 401185386Sdfrstatic inline int __must_check 402183906SkmacyHYPERVISOR_xenoprof_op( 403185386Sdfr int op, void *arg) 404183906Skmacy{ 405185386Sdfr return _hypercall2(int, xenoprof_op, op, arg); 406183906Skmacy} 407183906Skmacy 408185386Sdfrstatic inline int __must_check 409183906SkmacyHYPERVISOR_kexec_op( 410185386Sdfr unsigned long op, void *args) 411183906Skmacy{ 412185386Sdfr return _hypercall2(int, kexec_op, op, args); 413183906Skmacy} 414185386Sdfr 415185386Sdfr#undef __must_check 416185386Sdfr 417185637Sdfr#endif /* __MACHINE_XEN_HYPERCALL_H__ */ 418