hypercall.h revision 263010
1/****************************************************************************** 2 * hypercall.h 3 * 4 * Linux-specific hypervisor handling. 5 * 6 * Copyright (c) 2002-2004, K A Fraser 7 * 8 * This file may be distributed separately from the Linux kernel, or 9 * incorporated into other software packages, subject to the following license: 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining a copy 12 * of this source file (the "Software"), to deal in the Software without 13 * restriction, including without limitation the rights to use, copy, modify, 14 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 15 * and to permit persons to whom the Software is furnished to do so, subject to 16 * the following conditions: 17 * 18 * The above copyright notice and this permission notice shall be included in 19 * all copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 27 * IN THE SOFTWARE. 28 */ 29 30#ifndef __HYPERCALL_H__ 31#define __HYPERCALL_H__ 32 33#include <sys/systm.h> 34#include <xen/interface/xen.h> 35#include <xen/interface/sched.h> 36 37#define __STR(x) #x 38#define STR(x) __STR(x) 39#define ENOXENSYS 38 40#define CONFIG_XEN_COMPAT 0x030002 41 42#define HYPERCALL_STR(name) \ 43 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 44 45#define _hypercall0(type, name) \ 46({ \ 47 long __res; \ 48 __asm__ volatile ( \ 49 HYPERCALL_STR(name) \ 50 : "=a" (__res) \ 51 : \ 52 : "memory" ); \ 53 (type)__res; \ 54}) 55 56#define _hypercall1(type, name, a1) \ 57({ \ 58 long __res, __ign1; \ 59 __asm__ volatile ( \ 60 HYPERCALL_STR(name) \ 61 : "=a" (__res), "=b" (__ign1) \ 62 : "1" ((long)(a1)) \ 63 : "memory" ); \ 64 (type)__res; \ 65}) 66 67#define _hypercall2(type, name, a1, a2) \ 68({ \ 69 long __res, __ign1, __ign2; \ 70 __asm__ volatile ( \ 71 HYPERCALL_STR(name) \ 72 : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ 73 : "1" ((long)(a1)), "2" ((long)(a2)) \ 74 : "memory" ); \ 75 (type)__res; \ 76}) 77 78#define _hypercall3(type, name, a1, a2, a3) \ 79({ \ 80 long __res, __ign1, __ign2, __ign3; \ 81 __asm__ volatile ( \ 82 HYPERCALL_STR(name) \ 83 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 84 "=d" (__ign3) \ 85 : "1" ((long)(a1)), "2" ((long)(a2)), \ 86 "3" ((long)(a3)) \ 87 : "memory" ); \ 88 (type)__res; \ 89}) 90 91#define _hypercall4(type, name, a1, a2, a3, a4) \ 92({ \ 93 long __res, __ign1, __ign2, __ign3, __ign4; \ 94 __asm__ volatile ( \ 95 HYPERCALL_STR(name) \ 96 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 97 "=d" (__ign3), "=S" (__ign4) \ 98 : "1" ((long)(a1)), "2" ((long)(a2)), \ 99 "3" ((long)(a3)), "4" ((long)(a4)) \ 100 : "memory" ); \ 101 (type)__res; \ 102}) 103 104#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 105({ \ 106 long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \ 107 __asm__ volatile ( \ 108 HYPERCALL_STR(name) \ 109 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 110 "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \ 111 : "1" ((long)(a1)), "2" ((long)(a2)), \ 112 "3" ((long)(a3)), "4" ((long)(a4)), \ 113 "5" ((long)(a5)) \ 114 : "memory" ); \ 115 (type)__res; \ 116}) 117 118static inline int 119HYPERVISOR_set_trap_table( 120 trap_info_t *table) 121{ 122 return _hypercall1(int, set_trap_table, table); 123} 124 125static inline int 126HYPERVISOR_mmu_update( 127 mmu_update_t *req, int count, int *success_count, domid_t domid) 128{ 129 return _hypercall4(int, mmu_update, req, count, success_count, domid); 130} 131 132static inline int 133HYPERVISOR_mmuext_op( 134 mmuext_op_t *op, int count, int *success_count, domid_t domid) 135{ 136 return _hypercall4(int, mmuext_op, op, count, success_count, domid); 137} 138 139static inline int 140HYPERVISOR_set_gdt( 141 unsigned long *frame_list, int entries) 142{ 143 return _hypercall2(int, set_gdt, frame_list, entries); 144} 145 146static inline int 147HYPERVISOR_stack_switch( 148 unsigned long ss, unsigned long esp) 149{ 150 return _hypercall2(int, stack_switch, ss, esp); 151} 152 153static inline int 154HYPERVISOR_set_callbacks( 155 unsigned long event_selector, unsigned long event_address, 156 unsigned long failsafe_selector, unsigned long failsafe_address) 157{ 158 return _hypercall4(int, set_callbacks, 159 event_selector, event_address, 160 failsafe_selector, failsafe_address); 161} 162 163static inline int 164HYPERVISOR_fpu_taskswitch( 165 int set) 166{ 167 return _hypercall1(int, fpu_taskswitch, set); 168} 169 170static inline int 171HYPERVISOR_sched_op_compat( 172 int cmd, unsigned long arg) 173{ 174 return _hypercall2(int, sched_op_compat, cmd, arg); 175} 176 177static inline int 178HYPERVISOR_sched_op( 179 int cmd, void *arg) 180{ 181 return _hypercall2(int, sched_op, cmd, arg); 182} 183 184static inline long 185HYPERVISOR_set_timer_op( 186 uint64_t timeout) 187{ 188 unsigned long timeout_hi = (unsigned long)(timeout>>32); 189 unsigned long timeout_lo = (unsigned long)timeout; 190 return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); 191} 192#if 0 193static inline int 194HYPERVISOR_platform_op( 195 struct xen_platform_op *platform_op) 196{ 197 platform_op->interface_version = XENPF_INTERFACE_VERSION; 198 return _hypercall1(int, platform_op, platform_op); 199} 200#endif 201static inline int 202HYPERVISOR_set_debugreg( 203 int reg, unsigned long value) 204{ 205 return _hypercall2(int, set_debugreg, reg, value); 206} 207 208static inline unsigned long 209HYPERVISOR_get_debugreg( 210 int reg) 211{ 212 return _hypercall1(unsigned long, get_debugreg, reg); 213} 214 215static inline int 216HYPERVISOR_update_descriptor( 217 uint64_t ma, uint64_t desc) 218{ 219 return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32); 220} 221 222static inline int 223HYPERVISOR_memory_op( 224 unsigned int cmd, void *arg) 225{ 226 return _hypercall2(int, memory_op, cmd, arg); 227} 228 229#if defined(XEN) 230int HYPERVISOR_multicall(multicall_entry_t *, int); 231static inline int 232_HYPERVISOR_multicall( 233#else /* XENHVM */ 234static inline int 235HYPERVISOR_multicall( 236#endif 237 void *call_list, int nr_calls) 238{ 239 return _hypercall2(int, multicall, call_list, nr_calls); 240} 241 242static inline int 243HYPERVISOR_update_va_mapping( 244 unsigned long va, uint64_t new_val, unsigned long flags) 245{ 246 uint32_t hi, lo; 247 248 lo = (uint32_t)(new_val & 0xffffffff); 249 hi = (uint32_t)(new_val >> 32); 250 251 return _hypercall4(int, update_va_mapping, va, 252 lo, hi, flags); 253} 254 255static inline int 256HYPERVISOR_event_channel_op( 257 int cmd, void *arg) 258{ 259 int rc = _hypercall2(int, event_channel_op, cmd, arg); 260 261#if CONFIG_XEN_COMPAT <= 0x030002 262 if (__predict_false(rc == -ENOXENSYS)) { 263 struct evtchn_op op; 264 op.cmd = cmd; 265 memcpy(&op.u, arg, sizeof(op.u)); 266 rc = _hypercall1(int, event_channel_op_compat, &op); 267 memcpy(arg, &op.u, sizeof(op.u)); 268 } 269#endif 270 return (rc); 271} 272 273static inline int 274HYPERVISOR_xen_version( 275 int cmd, void *arg) 276{ 277 return _hypercall2(int, xen_version, cmd, arg); 278} 279 280static inline int 281HYPERVISOR_console_io( 282 int cmd, int count, char *str) 283{ 284 return _hypercall3(int, console_io, cmd, count, str); 285} 286 287static inline int 288HYPERVISOR_physdev_op( 289 int cmd, void *arg) 290{ 291 int rc = _hypercall2(int, physdev_op, cmd, arg); 292#if CONFIG_XEN_COMPAT <= 0x030002 293 if (__predict_false(rc == -ENOXENSYS)) { 294 struct physdev_op op; 295 op.cmd = cmd; 296 memcpy(&op.u, arg, sizeof(op.u)); 297 rc = _hypercall1(int, physdev_op_compat, &op); 298 memcpy(arg, &op.u, sizeof(op.u)); 299 } 300#endif 301 return (rc); 302} 303 304static inline int 305HYPERVISOR_grant_table_op( 306 unsigned int cmd, void *uop, unsigned int count) 307{ 308 return _hypercall3(int, grant_table_op, cmd, uop, count); 309} 310 311static inline int 312HYPERVISOR_update_va_mapping_otherdomain( 313 unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 314{ 315 uint32_t hi, lo; 316 317 lo = (uint32_t)(new_val & 0xffffffff); 318 hi = (uint32_t)(new_val >> 32); 319 320 return _hypercall5(int, update_va_mapping_otherdomain, va, 321 lo, hi, flags, domid); 322} 323 324static inline int 325HYPERVISOR_vm_assist( 326 unsigned int cmd, unsigned int type) 327{ 328 return _hypercall2(int, vm_assist, cmd, type); 329} 330 331static inline int 332HYPERVISOR_vcpu_op( 333 int cmd, int vcpuid, void *extra_args) 334{ 335 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 336} 337 338static inline int 339HYPERVISOR_suspend( 340 unsigned long srec) 341{ 342 struct sched_shutdown sched_shutdown = { 343 .reason = SHUTDOWN_suspend 344 }; 345 int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 346 &sched_shutdown, srec); 347#if CONFIG_XEN_COMPAT <= 0x030002 348 if (rc == -ENOXENSYS) 349 rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 350 SHUTDOWN_suspend, srec); 351#endif 352 return (rc); 353} 354 355#if CONFIG_XEN_COMPAT <= 0x030002 356static inline int 357HYPERVISOR_nmi_op( 358 unsigned long op, void *arg) 359{ 360 return _hypercall2(int, nmi_op, op, arg); 361} 362#endif 363 364static inline int 365HYPERVISOR_callback_op( 366 int cmd, void *arg) 367{ 368 return _hypercall2(int, callback_op, cmd, arg); 369} 370 371#ifndef CONFIG_XEN 372static inline unsigned long 373HYPERVISOR_hvm_op( 374 int op, void *arg) 375{ 376 return _hypercall2(unsigned long, hvm_op, op, arg); 377} 378#endif 379 380static inline int 381HYPERVISOR_xenoprof_op( 382 int op, void *arg) 383{ 384 return _hypercall2(int, xenoprof_op, op, arg); 385} 386 387static inline int 388HYPERVISOR_kexec_op( 389 unsigned long op, void *args) 390{ 391 return _hypercall2(int, kexec_op, op, args); 392} 393#endif /* __HYPERCALL_H__ */ 394 395/* 396 * Local variables: 397 * c-file-style: "linux" 398 * indent-tabs-mode: t 399 * c-indent-level: 8 400 * c-basic-offset: 8 401 * tab-width: 8 402 * End: 403 */ 404