1181638Skmacy/****************************************************************************** 2181638Skmacy * hypercall.h 3181638Skmacy * 4181638Skmacy * Linux-specific hypervisor handling. 5181638Skmacy * 6181638Skmacy * Copyright (c) 2002-2004, K A Fraser 7181638Skmacy * 8181638Skmacy * This file may be distributed separately from the Linux kernel, or 9181638Skmacy * incorporated into other software packages, subject to the following license: 10181638Skmacy * 11181638Skmacy * Permission is hereby granted, free of charge, to any person obtaining a copy 12181638Skmacy * of this source file (the "Software"), to deal in the Software without 13181638Skmacy * restriction, including without limitation the rights to use, copy, modify, 14181638Skmacy * merge, publish, distribute, sublicense, and/or sell copies of the Software, 15181638Skmacy * and to permit persons to whom the Software is furnished to do so, subject to 16181638Skmacy * the following conditions: 17181638Skmacy * 18181638Skmacy * The above copyright notice and this permission notice shall be included in 19181638Skmacy * all copies or substantial portions of the Software. 20181638Skmacy * 21181638Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22181638Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23181638Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24181638Skmacy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25181638Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26181638Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 27181638Skmacy * IN THE SOFTWARE. 28181638Skmacy */ 29181638Skmacy 30181638Skmacy#ifndef __HYPERCALL_H__ 31181638Skmacy#define __HYPERCALL_H__ 32181638Skmacy 33181638Skmacy#include <sys/systm.h> 34181638Skmacy#include <xen/interface/xen.h> 35181638Skmacy#include <xen/interface/sched.h> 36181638Skmacy 37181638Skmacy#define __STR(x) #x 38181638Skmacy#define STR(x) __STR(x) 39181638Skmacy#define ENOXENSYS 38 40181638Skmacy#define CONFIG_XEN_COMPAT 0x030002 41181638Skmacy 42181638Skmacy 43181638Skmacy#if defined(XEN) 44181638Skmacy#define HYPERCALL_STR(name) \ 45181638Skmacy "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 46181638Skmacy#else 47181638Skmacy#define HYPERCALL_STR(name) \ 48181638Skmacy "mov hypercall_stubs,%%eax; " \ 49181638Skmacy "add $("STR(__HYPERVISOR_##name)" * 32),%%eax; " \ 50181638Skmacy "call *%%eax" 51181638Skmacy#endif 52181638Skmacy 53181638Skmacy#define _hypercall0(type, name) \ 54181638Skmacy({ \ 55181638Skmacy long __res; \ 56181638Skmacy __asm__ volatile ( \ 57181638Skmacy HYPERCALL_STR(name) \ 58181638Skmacy : "=a" (__res) \ 59181638Skmacy : \ 60181638Skmacy : "memory" ); \ 61181638Skmacy (type)__res; \ 62181638Skmacy}) 63181638Skmacy 64181638Skmacy#define _hypercall1(type, name, a1) \ 65181638Skmacy({ \ 66181638Skmacy long __res, __ign1; \ 67181638Skmacy __asm__ volatile ( \ 68181638Skmacy HYPERCALL_STR(name) \ 69181638Skmacy : "=a" (__res), "=b" (__ign1) \ 70181638Skmacy : "1" ((long)(a1)) \ 71181638Skmacy : "memory" ); \ 72181638Skmacy (type)__res; \ 73181638Skmacy}) 74181638Skmacy 75181638Skmacy#define _hypercall2(type, name, a1, a2) \ 76181638Skmacy({ \ 77181638Skmacy long __res, __ign1, __ign2; \ 78181638Skmacy __asm__ volatile ( \ 79181638Skmacy HYPERCALL_STR(name) \ 80181638Skmacy : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ 81181638Skmacy : "1" ((long)(a1)), "2" ((long)(a2)) \ 82181638Skmacy : "memory" ); \ 83181638Skmacy (type)__res; \ 84181638Skmacy}) 85181638Skmacy 86181638Skmacy#define _hypercall3(type, name, a1, a2, a3) \ 87181638Skmacy({ \ 88181638Skmacy long __res, __ign1, __ign2, __ign3; \ 89181638Skmacy __asm__ volatile ( \ 90181638Skmacy HYPERCALL_STR(name) \ 91181638Skmacy : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 92181638Skmacy "=d" (__ign3) \ 93181638Skmacy : "1" ((long)(a1)), "2" ((long)(a2)), \ 94181638Skmacy "3" ((long)(a3)) \ 95181638Skmacy : "memory" ); \ 96181638Skmacy (type)__res; \ 97181638Skmacy}) 98181638Skmacy 99181638Skmacy#define _hypercall4(type, name, a1, a2, a3, a4) \ 100181638Skmacy({ \ 101181638Skmacy long __res, __ign1, __ign2, __ign3, __ign4; \ 102181638Skmacy __asm__ volatile ( \ 103181638Skmacy HYPERCALL_STR(name) \ 104181638Skmacy : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 105181638Skmacy "=d" (__ign3), "=S" (__ign4) \ 106181638Skmacy : "1" ((long)(a1)), "2" ((long)(a2)), \ 107181638Skmacy "3" ((long)(a3)), "4" ((long)(a4)) \ 108181638Skmacy : "memory" ); \ 109181638Skmacy (type)__res; \ 110181638Skmacy}) 111181638Skmacy 112181638Skmacy#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 113181638Skmacy({ \ 114181638Skmacy long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \ 115181638Skmacy __asm__ volatile ( \ 116181638Skmacy HYPERCALL_STR(name) \ 117181638Skmacy : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 118181638Skmacy "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \ 119181638Skmacy : "1" ((long)(a1)), "2" ((long)(a2)), \ 120181638Skmacy "3" ((long)(a3)), "4" ((long)(a4)), \ 121181638Skmacy "5" ((long)(a5)) \ 122181638Skmacy : "memory" ); \ 123181638Skmacy (type)__res; \ 124181638Skmacy}) 125181638Skmacy 126181638Skmacystatic inline int 127181638SkmacyHYPERVISOR_set_trap_table( 128181638Skmacy trap_info_t *table) 129181638Skmacy{ 130181638Skmacy return _hypercall1(int, set_trap_table, table); 131181638Skmacy} 132181638Skmacy 133181638Skmacystatic inline int 134181638SkmacyHYPERVISOR_mmu_update( 135181638Skmacy mmu_update_t *req, int count, int *success_count, domid_t domid) 136181638Skmacy{ 137181638Skmacy return _hypercall4(int, mmu_update, req, count, success_count, domid); 138181638Skmacy} 139181638Skmacy 140181638Skmacystatic inline int 141181638SkmacyHYPERVISOR_mmuext_op( 142181638Skmacy mmuext_op_t *op, int count, int *success_count, domid_t domid) 143181638Skmacy{ 144181638Skmacy return _hypercall4(int, mmuext_op, op, count, success_count, domid); 145181638Skmacy} 146181638Skmacy 147181638Skmacystatic inline int 148181638SkmacyHYPERVISOR_set_gdt( 149181638Skmacy unsigned long *frame_list, int entries) 150181638Skmacy{ 151181638Skmacy return _hypercall2(int, set_gdt, frame_list, entries); 152181638Skmacy} 153181638Skmacy 154181638Skmacystatic inline int 155181638SkmacyHYPERVISOR_stack_switch( 156181638Skmacy unsigned long ss, unsigned long esp) 157181638Skmacy{ 158181638Skmacy return _hypercall2(int, stack_switch, ss, esp); 159181638Skmacy} 160181638Skmacy 161181638Skmacystatic inline int 162181638SkmacyHYPERVISOR_set_callbacks( 163181638Skmacy unsigned long event_selector, unsigned long event_address, 164181638Skmacy unsigned long failsafe_selector, unsigned long failsafe_address) 165181638Skmacy{ 166181638Skmacy return _hypercall4(int, set_callbacks, 167181638Skmacy event_selector, event_address, 168181638Skmacy failsafe_selector, failsafe_address); 169181638Skmacy} 170181638Skmacy 171181638Skmacystatic inline int 172181638SkmacyHYPERVISOR_fpu_taskswitch( 173181638Skmacy int set) 174181638Skmacy{ 175181638Skmacy return _hypercall1(int, fpu_taskswitch, set); 176181638Skmacy} 177181638Skmacy 178181638Skmacystatic inline int 179181638SkmacyHYPERVISOR_sched_op_compat( 180181638Skmacy int cmd, unsigned long arg) 181181638Skmacy{ 182181638Skmacy return _hypercall2(int, sched_op_compat, cmd, arg); 183181638Skmacy} 184181638Skmacy 185181638Skmacystatic inline int 186181638SkmacyHYPERVISOR_sched_op( 187181638Skmacy int cmd, void *arg) 188181638Skmacy{ 189181638Skmacy return _hypercall2(int, sched_op, cmd, arg); 190181638Skmacy} 191181638Skmacy 192181638Skmacystatic inline long 193181638SkmacyHYPERVISOR_set_timer_op( 194181638Skmacy uint64_t timeout) 195181638Skmacy{ 196181638Skmacy unsigned long timeout_hi = (unsigned long)(timeout>>32); 197181638Skmacy unsigned long timeout_lo = (unsigned long)timeout; 198181638Skmacy return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); 199181638Skmacy} 200181638Skmacy#if 0 201181638Skmacystatic inline int 202181638SkmacyHYPERVISOR_platform_op( 203181638Skmacy struct xen_platform_op *platform_op) 204181638Skmacy{ 205181638Skmacy platform_op->interface_version = XENPF_INTERFACE_VERSION; 206181638Skmacy return _hypercall1(int, platform_op, platform_op); 207181638Skmacy} 208181638Skmacy#endif 209181638Skmacystatic inline int 210181638SkmacyHYPERVISOR_set_debugreg( 211181638Skmacy int reg, unsigned long value) 212181638Skmacy{ 213181638Skmacy return _hypercall2(int, set_debugreg, reg, value); 214181638Skmacy} 215181638Skmacy 216181638Skmacystatic inline unsigned long 217181638SkmacyHYPERVISOR_get_debugreg( 218181638Skmacy int reg) 219181638Skmacy{ 220181638Skmacy return _hypercall1(unsigned long, get_debugreg, reg); 221181638Skmacy} 222181638Skmacy 223181638Skmacystatic inline int 224181638SkmacyHYPERVISOR_update_descriptor( 225181638Skmacy uint64_t ma, uint64_t desc) 226181638Skmacy{ 227181638Skmacy return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32); 228181638Skmacy} 229181638Skmacy 230181638Skmacystatic inline int 231181638SkmacyHYPERVISOR_memory_op( 232181638Skmacy unsigned int cmd, void *arg) 233181638Skmacy{ 234181638Skmacy return _hypercall2(int, memory_op, cmd, arg); 235181638Skmacy} 236181638Skmacy 237216956Srwatson#if defined(XEN) 238215818Scpercivaint HYPERVISOR_multicall(multicall_entry_t *, int); 239181638Skmacystatic inline int 240215818Scperciva_HYPERVISOR_multicall( 241216956Srwatson#else /* XENHVM */ 242216956Srwatsonstatic inline int 243216956SrwatsonHYPERVISOR_multicall( 244216956Srwatson#endif 245181638Skmacy void *call_list, int nr_calls) 246181638Skmacy{ 247181638Skmacy return _hypercall2(int, multicall, call_list, nr_calls); 248181638Skmacy} 249181638Skmacy 250181638Skmacystatic inline int 251181638SkmacyHYPERVISOR_update_va_mapping( 252181638Skmacy unsigned long va, uint64_t new_val, unsigned long flags) 253181638Skmacy{ 254181638Skmacy uint32_t hi, lo; 255181638Skmacy 256181638Skmacy lo = (uint32_t)(new_val & 0xffffffff); 257181638Skmacy hi = (uint32_t)(new_val >> 32); 258181638Skmacy 259181638Skmacy return _hypercall4(int, update_va_mapping, va, 260181638Skmacy lo, hi, flags); 261181638Skmacy} 262181638Skmacy 263181638Skmacystatic inline int 264181638SkmacyHYPERVISOR_event_channel_op( 265181638Skmacy int cmd, void *arg) 266181638Skmacy{ 267181638Skmacy int rc = _hypercall2(int, event_channel_op, cmd, arg); 268181638Skmacy 269181638Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 270181638Skmacy if (__predict_false(rc == -ENOXENSYS)) { 271181638Skmacy struct evtchn_op op; 272181638Skmacy op.cmd = cmd; 273181638Skmacy memcpy(&op.u, arg, sizeof(op.u)); 274181638Skmacy rc = _hypercall1(int, event_channel_op_compat, &op); 275181638Skmacy memcpy(arg, &op.u, sizeof(op.u)); 276181638Skmacy } 277181638Skmacy#endif 278181638Skmacy return (rc); 279181638Skmacy} 280181638Skmacy 281181638Skmacystatic inline int 282181638SkmacyHYPERVISOR_xen_version( 283181638Skmacy int cmd, void *arg) 284181638Skmacy{ 285181638Skmacy return _hypercall2(int, xen_version, cmd, arg); 286181638Skmacy} 287181638Skmacy 288181638Skmacystatic inline int 289181638SkmacyHYPERVISOR_console_io( 290181638Skmacy int cmd, int count, char *str) 291181638Skmacy{ 292181638Skmacy return _hypercall3(int, console_io, cmd, count, str); 293181638Skmacy} 294181638Skmacy 295181638Skmacystatic inline int 296181638SkmacyHYPERVISOR_physdev_op( 297181638Skmacy int cmd, void *arg) 298181638Skmacy{ 299181638Skmacy int rc = _hypercall2(int, physdev_op, cmd, arg); 300181638Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 301181638Skmacy if (__predict_false(rc == -ENOXENSYS)) { 302181638Skmacy struct physdev_op op; 303181638Skmacy op.cmd = cmd; 304181638Skmacy memcpy(&op.u, arg, sizeof(op.u)); 305181638Skmacy rc = _hypercall1(int, physdev_op_compat, &op); 306181638Skmacy memcpy(arg, &op.u, sizeof(op.u)); 307181638Skmacy } 308181638Skmacy#endif 309181638Skmacy return (rc); 310181638Skmacy} 311181638Skmacy 312181638Skmacystatic inline int 313181638SkmacyHYPERVISOR_grant_table_op( 314181638Skmacy unsigned int cmd, void *uop, unsigned int count) 315181638Skmacy{ 316181638Skmacy return _hypercall3(int, grant_table_op, cmd, uop, count); 317181638Skmacy} 318181638Skmacy 319181638Skmacystatic inline int 320181638SkmacyHYPERVISOR_update_va_mapping_otherdomain( 321181638Skmacy unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 322181638Skmacy{ 323181638Skmacy uint32_t hi, lo; 324181638Skmacy 325181638Skmacy lo = (uint32_t)(new_val & 0xffffffff); 326181638Skmacy hi = (uint32_t)(new_val >> 32); 327181638Skmacy 328181638Skmacy return _hypercall5(int, update_va_mapping_otherdomain, va, 329181638Skmacy lo, hi, flags, domid); 330181638Skmacy} 331181638Skmacy 332181638Skmacystatic inline int 333181638SkmacyHYPERVISOR_vm_assist( 334181638Skmacy unsigned int cmd, unsigned int type) 335181638Skmacy{ 336181638Skmacy return _hypercall2(int, vm_assist, cmd, type); 337181638Skmacy} 338181638Skmacy 339181638Skmacystatic inline int 340181638SkmacyHYPERVISOR_vcpu_op( 341181638Skmacy int cmd, int vcpuid, void *extra_args) 342181638Skmacy{ 343181638Skmacy return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 344181638Skmacy} 345181638Skmacy 346181638Skmacystatic inline int 347181638SkmacyHYPERVISOR_suspend( 348181638Skmacy unsigned long srec) 349181638Skmacy{ 350181638Skmacy struct sched_shutdown sched_shutdown = { 351181638Skmacy .reason = SHUTDOWN_suspend 352181638Skmacy }; 353181638Skmacy int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 354181638Skmacy &sched_shutdown, srec); 355181638Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 356181638Skmacy if (rc == -ENOXENSYS) 357181638Skmacy rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 358181638Skmacy SHUTDOWN_suspend, srec); 359181638Skmacy#endif 360181638Skmacy return (rc); 361181638Skmacy} 362181638Skmacy 363181638Skmacy#if CONFIG_XEN_COMPAT <= 0x030002 364181638Skmacystatic inline int 365181638SkmacyHYPERVISOR_nmi_op( 366181638Skmacy unsigned long op, void *arg) 367181638Skmacy{ 368181638Skmacy return _hypercall2(int, nmi_op, op, arg); 369181638Skmacy} 370181638Skmacy#endif 371181638Skmacy 372181638Skmacystatic inline int 373181638SkmacyHYPERVISOR_callback_op( 374181638Skmacy int cmd, void *arg) 375181638Skmacy{ 376181638Skmacy return _hypercall2(int, callback_op, cmd, arg); 377181638Skmacy} 378181638Skmacy 379181638Skmacy#ifndef CONFIG_XEN 380181638Skmacystatic inline unsigned long 381181638SkmacyHYPERVISOR_hvm_op( 382181638Skmacy int op, void *arg) 383181638Skmacy{ 384181638Skmacy return _hypercall2(unsigned long, hvm_op, op, arg); 385181638Skmacy} 386181638Skmacy#endif 387181638Skmacy 388181638Skmacystatic inline int 389181638SkmacyHYPERVISOR_xenoprof_op( 390181638Skmacy int op, void *arg) 391181638Skmacy{ 392181638Skmacy return _hypercall2(int, xenoprof_op, op, arg); 393181638Skmacy} 394181638Skmacy 395181638Skmacystatic inline int 396181638SkmacyHYPERVISOR_kexec_op( 397181638Skmacy unsigned long op, void *args) 398181638Skmacy{ 399181638Skmacy return _hypercall2(int, kexec_op, op, args); 400181638Skmacy} 401181638Skmacy#endif /* __HYPERCALL_H__ */ 402181638Skmacy 403181638Skmacy/* 404181638Skmacy * Local variables: 405181638Skmacy * c-file-style: "linux" 406181638Skmacy * indent-tabs-mode: t 407181638Skmacy * c-indent-level: 8 408181638Skmacy * c-basic-offset: 8 409181638Skmacy * tab-width: 8 410181638Skmacy * End: 411181638Skmacy */ 412