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