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 48273476Sroygerextern char *hypercall_page; 49273476Sroyger 50183906Skmacy#define __STR(x) #x 51183906Skmacy#define STR(x) __STR(x) 52183906Skmacy#define ENOXENSYS 38 53183906Skmacy#define CONFIG_XEN_COMPAT 0x030002 54185386Sdfr#define __must_check 55183906Skmacy 56185386Sdfr#define HYPERCALL_STR(name) \ 57185386Sdfr "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 58183906Skmacy 59185386Sdfr#define _hypercall0(type, name) \ 60185386Sdfr({ \ 61185386Sdfr type __res; \ 62185386Sdfr __asm__ volatile ( \ 63185386Sdfr HYPERCALL_STR(name) \ 64185386Sdfr : "=a" (__res) \ 65185386Sdfr : \ 66185386Sdfr : "memory" ); \ 67185386Sdfr __res; \ 68183906Skmacy}) 69183906Skmacy 70185386Sdfr#define _hypercall1(type, name, a1) \ 71185386Sdfr({ \ 72185386Sdfr type __res; \ 73185386Sdfr long __ign1; \ 74185386Sdfr __asm__ volatile ( \ 75185386Sdfr HYPERCALL_STR(name) \ 76185386Sdfr : "=a" (__res), "=D" (__ign1) \ 77185386Sdfr : "1" ((long)(a1)) \ 78185386Sdfr : "memory" ); \ 79185386Sdfr __res; \ 80183906Skmacy}) 81183906Skmacy 82185386Sdfr#define _hypercall2(type, name, a1, a2) \ 83185386Sdfr({ \ 84185386Sdfr type __res; \ 85185386Sdfr long __ign1, __ign2; \ 86185386Sdfr __asm__ volatile ( \ 87185386Sdfr HYPERCALL_STR(name) \ 88185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ 89185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)) \ 90185386Sdfr : "memory" ); \ 91185386Sdfr __res; \ 92183906Skmacy}) 93183906Skmacy 94185386Sdfr#define _hypercall3(type, name, a1, a2, a3) \ 95185386Sdfr({ \ 96185386Sdfr type __res; \ 97185386Sdfr long __ign1, __ign2, __ign3; \ 98185386Sdfr __asm__ volatile ( \ 99185386Sdfr HYPERCALL_STR(name) \ 100185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 101185386Sdfr "=d" (__ign3) \ 102185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 103185386Sdfr "3" ((long)(a3)) \ 104185386Sdfr : "memory" ); \ 105185386Sdfr __res; \ 106183906Skmacy}) 107183906Skmacy 108185386Sdfr#define _hypercall4(type, name, a1, a2, a3, a4) \ 109185386Sdfr({ \ 110185386Sdfr type __res; \ 111185386Sdfr long __ign1, __ign2, __ign3; \ 112185386Sdfr register long __arg4 __asm__("r10") = (long)(a4); \ 113185386Sdfr __asm__ volatile ( \ 114185386Sdfr HYPERCALL_STR(name) \ 115185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 116185386Sdfr "=d" (__ign3), "+r" (__arg4) \ 117185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 118185386Sdfr "3" ((long)(a3)) \ 119185386Sdfr : "memory" ); \ 120185386Sdfr __res; \ 121183906Skmacy}) 122183906Skmacy 123185386Sdfr#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 124185386Sdfr({ \ 125185386Sdfr type __res; \ 126185386Sdfr long __ign1, __ign2, __ign3; \ 127185386Sdfr register long __arg4 __asm__("r10") = (long)(a4); \ 128185386Sdfr register long __arg5 __asm__("r8") = (long)(a5); \ 129185386Sdfr __asm__ volatile ( \ 130185386Sdfr HYPERCALL_STR(name) \ 131185386Sdfr : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ 132185386Sdfr "=d" (__ign3), "+r" (__arg4), "+r" (__arg5) \ 133185386Sdfr : "1" ((long)(a1)), "2" ((long)(a2)), \ 134185386Sdfr "3" ((long)(a3)) \ 135185386Sdfr : "memory" ); \ 136185386Sdfr __res; \ 137185386Sdfr}) 138183906Skmacy 139273476Sroygerstatic inline int 140273476Sroygerprivcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5) 141273476Sroyger{ 142273476Sroyger int __res; 143273476Sroyger long __ign1, __ign2, __ign3; 144273476Sroyger register long __arg4 __asm__("r10") = (long)(a4); 145273476Sroyger register long __arg5 __asm__("r8") = (long)(a5); 146273476Sroyger long __call = (long)&hypercall_page + (op * 32); 147273476Sroyger 148273476Sroyger __asm__ volatile ( 149273476Sroyger "call *%[call]" 150273476Sroyger : "=a" (__res), "=D" (__ign1), "=S" (__ign2), 151273476Sroyger "=d" (__ign3), "+r" (__arg4), "+r" (__arg5) 152273476Sroyger : "1" ((long)(a1)), "2" ((long)(a2)), 153273476Sroyger "3" ((long)(a3)), [call] "a" (__call) 154273476Sroyger : "memory" ); 155273476Sroyger 156273476Sroyger return (__res); 157273476Sroyger} 158273476Sroyger 159185386Sdfrstatic inline int __must_check 160183906SkmacyHYPERVISOR_set_trap_table( 161185386Sdfr const trap_info_t *table) 162183906Skmacy{ 163183906Skmacy return _hypercall1(int, set_trap_table, table); 164183906Skmacy} 165183906Skmacy 166185386Sdfrstatic inline int __must_check 167183906SkmacyHYPERVISOR_mmu_update( 168185386Sdfr mmu_update_t *req, unsigned int count, unsigned int *success_count, 169185386Sdfr domid_t domid) 170183906Skmacy{ 171183906Skmacy return _hypercall4(int, mmu_update, req, count, success_count, domid); 172183906Skmacy} 173183906Skmacy 174185386Sdfrstatic inline int __must_check 175183906SkmacyHYPERVISOR_mmuext_op( 176185386Sdfr struct mmuext_op *op, unsigned int count, unsigned int *success_count, 177185386Sdfr domid_t domid) 178183906Skmacy{ 179183906Skmacy return _hypercall4(int, mmuext_op, op, count, success_count, domid); 180183906Skmacy} 181183906Skmacy 182185386Sdfrstatic inline int __must_check 183183906SkmacyHYPERVISOR_set_gdt( 184185386Sdfr unsigned long *frame_list, unsigned int entries) 185183906Skmacy{ 186183906Skmacy return _hypercall2(int, set_gdt, frame_list, entries); 187183906Skmacy} 188183906Skmacy 189185386Sdfrstatic inline int __must_check 190183906SkmacyHYPERVISOR_stack_switch( 191183906Skmacy unsigned long ss, unsigned long esp) 192183906Skmacy{ 193183906Skmacy return _hypercall2(int, stack_switch, ss, esp); 194183906Skmacy} 195183906Skmacy 196185386Sdfrstatic inline int __must_check 197183906SkmacyHYPERVISOR_set_callbacks( 198185386Sdfr unsigned long event_address, unsigned long failsafe_address, 199185386Sdfr unsigned long syscall_address) 200183906Skmacy{ 201185386Sdfr return _hypercall3(int, set_callbacks, 202185386Sdfr event_address, failsafe_address, syscall_address); 203183906Skmacy} 204183906Skmacy 205183906Skmacystatic inline int 206183906SkmacyHYPERVISOR_fpu_taskswitch( 207183906Skmacy int set) 208183906Skmacy{ 209183906Skmacy return _hypercall1(int, fpu_taskswitch, set); 210183906Skmacy} 211183906Skmacy 212185386Sdfrstatic inline int __must_check 213183906SkmacyHYPERVISOR_sched_op_compat( 214183906Skmacy int cmd, unsigned long arg) 215183906Skmacy{ 216183906Skmacy return _hypercall2(int, sched_op_compat, cmd, arg); 217183906Skmacy} 218183906Skmacy 219185386Sdfrstatic inline int __must_check 220183906SkmacyHYPERVISOR_sched_op( 221183906Skmacy int cmd, void *arg) 222183906Skmacy{ 223183906Skmacy return _hypercall2(int, sched_op, cmd, arg); 224183906Skmacy} 225183906Skmacy 226185386Sdfrstatic inline long __must_check 227183906SkmacyHYPERVISOR_set_timer_op( 228183906Skmacy uint64_t timeout) 229183906Skmacy{ 230185386Sdfr return _hypercall1(long, set_timer_op, timeout); 231183906Skmacy} 232185386Sdfr 233185386Sdfrstatic inline int __must_check 234183906SkmacyHYPERVISOR_platform_op( 235185386Sdfr struct xen_platform_op *platform_op) 236183906Skmacy{ 237185386Sdfr platform_op->interface_version = XENPF_INTERFACE_VERSION; 238185386Sdfr return _hypercall1(int, platform_op, platform_op); 239183906Skmacy} 240185386Sdfr 241185386Sdfrstatic inline int __must_check 242183906SkmacyHYPERVISOR_set_debugreg( 243185386Sdfr unsigned int reg, unsigned long value) 244183906Skmacy{ 245183906Skmacy return _hypercall2(int, set_debugreg, reg, value); 246183906Skmacy} 247183906Skmacy 248185386Sdfrstatic inline unsigned long __must_check 249183906SkmacyHYPERVISOR_get_debugreg( 250185386Sdfr unsigned int reg) 251183906Skmacy{ 252183906Skmacy return _hypercall1(unsigned long, get_debugreg, reg); 253183906Skmacy} 254183906Skmacy 255185386Sdfrstatic inline int __must_check 256183906SkmacyHYPERVISOR_update_descriptor( 257185386Sdfr unsigned long ma, unsigned long word) 258183906Skmacy{ 259185386Sdfr return _hypercall2(int, update_descriptor, ma, word); 260183906Skmacy} 261183906Skmacy 262185386Sdfrstatic inline int __must_check 263183906SkmacyHYPERVISOR_memory_op( 264183906Skmacy unsigned int cmd, void *arg) 265183906Skmacy{ 266183906Skmacy return _hypercall2(int, memory_op, cmd, arg); 267183906Skmacy} 268183906Skmacy 269185386Sdfrstatic inline int __must_check 270183906SkmacyHYPERVISOR_multicall( 271185386Sdfr multicall_entry_t *call_list, unsigned int nr_calls) 272183906Skmacy{ 273183906Skmacy return _hypercall2(int, multicall, call_list, nr_calls); 274183906Skmacy} 275183906Skmacy 276185386Sdfrstatic inline int __must_check 277183906SkmacyHYPERVISOR_update_va_mapping( 278183906Skmacy unsigned long va, uint64_t new_val, unsigned long flags) 279183906Skmacy{ 280185386Sdfr return _hypercall3(int, update_va_mapping, va, new_val, flags); 281183906Skmacy} 282183906Skmacy 283185386Sdfrstatic inline int __must_check 284183906SkmacyHYPERVISOR_event_channel_op( 285183906Skmacy int cmd, void *arg) 286183906Skmacy{ 287183906Skmacy int rc = _hypercall2(int, event_channel_op, cmd, arg); 288183906Skmacy 289183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 290255040Sgibbs if (__predict_false(rc == -ENOXENSYS)) { 291183906Skmacy struct evtchn_op op; 292183906Skmacy op.cmd = cmd; 293183906Skmacy memcpy(&op.u, arg, sizeof(op.u)); 294183906Skmacy rc = _hypercall1(int, event_channel_op_compat, &op); 295183906Skmacy memcpy(arg, &op.u, sizeof(op.u)); 296183906Skmacy } 297183906Skmacy#endif 298185386Sdfr 299185386Sdfr return rc; 300183906Skmacy} 301183906Skmacy 302185386Sdfrstatic inline int __must_check 303183906SkmacyHYPERVISOR_xen_version( 304183906Skmacy int cmd, void *arg) 305183906Skmacy{ 306183906Skmacy return _hypercall2(int, xen_version, cmd, arg); 307183906Skmacy} 308183906Skmacy 309185386Sdfrstatic inline int __must_check 310183906SkmacyHYPERVISOR_console_io( 311289033Sroyger int cmd, unsigned int count, const char *str) 312183906Skmacy{ 313183906Skmacy return _hypercall3(int, console_io, cmd, count, str); 314183906Skmacy} 315183906Skmacy 316185386Sdfrstatic inline int __must_check 317183906SkmacyHYPERVISOR_physdev_op( 318183906Skmacy int cmd, void *arg) 319183906Skmacy{ 320183906Skmacy int rc = _hypercall2(int, physdev_op, cmd, arg); 321185386Sdfr 322183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 323255040Sgibbs if (__predict_false(rc == -ENOXENSYS)) { 324183906Skmacy struct physdev_op op; 325183906Skmacy op.cmd = cmd; 326183906Skmacy memcpy(&op.u, arg, sizeof(op.u)); 327183906Skmacy rc = _hypercall1(int, physdev_op_compat, &op); 328183906Skmacy memcpy(arg, &op.u, sizeof(op.u)); 329183906Skmacy } 330183906Skmacy#endif 331185386Sdfr 332185386Sdfr return rc; 333183906Skmacy} 334183906Skmacy 335185386Sdfrstatic inline int __must_check 336183906SkmacyHYPERVISOR_grant_table_op( 337183906Skmacy unsigned int cmd, void *uop, unsigned int count) 338183906Skmacy{ 339183906Skmacy return _hypercall3(int, grant_table_op, cmd, uop, count); 340183906Skmacy} 341183906Skmacy 342185386Sdfrstatic inline int __must_check 343183906SkmacyHYPERVISOR_update_va_mapping_otherdomain( 344183906Skmacy unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 345183906Skmacy{ 346185386Sdfr return _hypercall4(int, update_va_mapping_otherdomain, va, 347185386Sdfr new_val, flags, domid); 348183906Skmacy} 349183906Skmacy 350185386Sdfrstatic inline int __must_check 351183906SkmacyHYPERVISOR_vm_assist( 352183906Skmacy unsigned int cmd, unsigned int type) 353183906Skmacy{ 354183906Skmacy return _hypercall2(int, vm_assist, cmd, type); 355183906Skmacy} 356183906Skmacy 357185386Sdfrstatic inline int __must_check 358183906SkmacyHYPERVISOR_vcpu_op( 359185386Sdfr int cmd, unsigned int vcpuid, void *extra_args) 360183906Skmacy{ 361183906Skmacy return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 362183906Skmacy} 363183906Skmacy 364185386Sdfrstatic inline int __must_check 365185386SdfrHYPERVISOR_set_segment_base( 366185386Sdfr int reg, unsigned long value) 367185386Sdfr{ 368185386Sdfr return _hypercall2(int, set_segment_base, reg, value); 369185386Sdfr} 370185386Sdfr 371185386Sdfrstatic inline int __must_check 372183906SkmacyHYPERVISOR_suspend( 373183906Skmacy unsigned long srec) 374183906Skmacy{ 375183906Skmacy struct sched_shutdown sched_shutdown = { 376183906Skmacy .reason = SHUTDOWN_suspend 377183906Skmacy }; 378185386Sdfr 379183906Skmacy int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 380185386Sdfr &sched_shutdown, srec); 381185386Sdfr 382183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 383183906Skmacy if (rc == -ENOXENSYS) 384183906Skmacy rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 385183906Skmacy SHUTDOWN_suspend, srec); 386185386Sdfr#endif 387185386Sdfr 388185386Sdfr return rc; 389183906Skmacy} 390183906Skmacy 391183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 392183906Skmacystatic inline int 393183906SkmacyHYPERVISOR_nmi_op( 394185386Sdfr unsigned long op, void *arg) 395183906Skmacy{ 396185386Sdfr return _hypercall2(int, nmi_op, op, arg); 397183906Skmacy} 398183906Skmacy#endif 399183906Skmacy 400183906Skmacy#ifndef CONFIG_XEN 401185386Sdfrstatic inline unsigned long __must_check 402183906SkmacyHYPERVISOR_hvm_op( 403183906Skmacy int op, void *arg) 404183906Skmacy{ 405183906Skmacy return _hypercall2(unsigned long, hvm_op, op, arg); 406183906Skmacy} 407183906Skmacy#endif 408183906Skmacy 409185386Sdfrstatic inline int __must_check 410185386SdfrHYPERVISOR_callback_op( 411185386Sdfr int cmd, const void *arg) 412185386Sdfr{ 413185386Sdfr return _hypercall2(int, callback_op, cmd, arg); 414185386Sdfr} 415185386Sdfr 416185386Sdfrstatic inline int __must_check 417183906SkmacyHYPERVISOR_xenoprof_op( 418185386Sdfr int op, void *arg) 419183906Skmacy{ 420185386Sdfr return _hypercall2(int, xenoprof_op, op, arg); 421183906Skmacy} 422183906Skmacy 423185386Sdfrstatic inline int __must_check 424183906SkmacyHYPERVISOR_kexec_op( 425185386Sdfr unsigned long op, void *args) 426183906Skmacy{ 427185386Sdfr return _hypercall2(int, kexec_op, op, args); 428183906Skmacy} 429185386Sdfr 430185386Sdfr#undef __must_check 431185386Sdfr 432185637Sdfr#endif /* __MACHINE_XEN_HYPERCALL_H__ */ 433