1 /****************************************************************************** 2 * hypercall.h 3 * 4 * Linux-specific hypervisor handling. 5 * 6 * Copyright (c) 2002-2004, K A Fraser 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License version 2 10 * as published by the Free Software Foundation; or, when distributed 11 * separately from the Linux kernel or incorporated into other 12 * software packages, subject to the following license: 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a copy 15 * of this source file (the "Software"), to deal in the Software without 16 * restriction, including without limitation the rights to use, copy, modify, 17 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 18 * and to permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 30 * IN THE SOFTWARE. 31 */ 32 33 #ifndef _ASM_X86_XEN_HYPERCALL_H 34 #define _ASM_X86_XEN_HYPERCALL_H 35 36 #include <linux/errno.h> 37 #include <linux/string.h> 38 39 #include <xen/interface/xen.h> 40 #include <xen/interface/sched.h> 41 #include <xen/interface/physdev.h> 42 43 /* 44 * The hypercall asms have to meet several constraints: 45 * - Work on 32- and 64-bit. 46 * The two architectures put their arguments in different sets of 47 * registers. 48 * 49 * - Work around asm syntax quirks 50 * It isn't possible to specify one of the rNN registers in a 51 * constraint, so we use explicit register variables to get the 52 * args into the right place. 53 * 54 * - Mark all registers as potentially clobbered 55 * Even unused parameters can be clobbered by the hypervisor, so we 56 * need to make sure gcc knows it. 57 * 58 * - Avoid compiler bugs. 59 * This is the tricky part. Because x86_32 has such a constrained 60 * register set, gcc versions below 4.3 have trouble generating 61 * code when all the arg registers and memory are trashed by the 62 * asm. There are syntactically simpler ways of achieving the 63 * semantics below, but they cause the compiler to crash. 64 * 65 * The only combination I found which works is: 66 * - assign the __argX variables first 67 * - list all actually used parameters as "+r" (__argX) 68 * - clobber the rest 69 * 70 * The result certainly isn't pretty, and it really shows up cpp's 71 * weakness as as macro language. Sorry. (But let's just give thanks 72 * there aren't more than 5 arguments...) 73 */ 74 75 extern struct { char _entry[32]; } hypercall_page[]; 76 77 #define __HYPERCALL "call hypercall_page+%c[offset]" 78 #define __HYPERCALL_ENTRY(x) \ 79 [offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0])) 80 81 #ifdef CONFIG_X86_32 82 #define __HYPERCALL_RETREG "eax" 83 #define __HYPERCALL_ARG1REG "ebx" 84 #define __HYPERCALL_ARG2REG "ecx" 85 #define __HYPERCALL_ARG3REG "edx" 86 #define __HYPERCALL_ARG4REG "esi" 87 #define __HYPERCALL_ARG5REG "edi" 88 #else 89 #define __HYPERCALL_RETREG "rax" 90 #define __HYPERCALL_ARG1REG "rdi" 91 #define __HYPERCALL_ARG2REG "rsi" 92 #define __HYPERCALL_ARG3REG "rdx" 93 #define __HYPERCALL_ARG4REG "r10" 94 #define __HYPERCALL_ARG5REG "r8" 95 #endif 96 97 #define __HYPERCALL_DECLS \ 98 register unsigned long __res asm(__HYPERCALL_RETREG); \ 99 register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \ 100 register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \ 101 register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \ 102 register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \ 103 register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; 104 105 #define __HYPERCALL_0PARAM "=r" (__res) 106 #define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1) 107 #define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2) 108 #define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3) 109 #define __HYPERCALL_4PARAM __HYPERCALL_3PARAM, "+r" (__arg4) 110 #define __HYPERCALL_5PARAM __HYPERCALL_4PARAM, "+r" (__arg5) 111 112 #define __HYPERCALL_0ARG() 113 #define __HYPERCALL_1ARG(a1) \ 114 __HYPERCALL_0ARG() __arg1 = (unsigned long)(a1); 115 #define __HYPERCALL_2ARG(a1,a2) \ 116 __HYPERCALL_1ARG(a1) __arg2 = (unsigned long)(a2); 117 #define __HYPERCALL_3ARG(a1,a2,a3) \ 118 __HYPERCALL_2ARG(a1,a2) __arg3 = (unsigned long)(a3); 119 #define __HYPERCALL_4ARG(a1,a2,a3,a4) \ 120 __HYPERCALL_3ARG(a1,a2,a3) __arg4 = (unsigned long)(a4); 121 #define __HYPERCALL_5ARG(a1,a2,a3,a4,a5) \ 122 __HYPERCALL_4ARG(a1,a2,a3,a4) __arg5 = (unsigned long)(a5); 123 124 #define __HYPERCALL_CLOBBER5 "memory" 125 #define __HYPERCALL_CLOBBER4 __HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG 126 #define __HYPERCALL_CLOBBER3 __HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG 127 #define __HYPERCALL_CLOBBER2 __HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG 128 #define __HYPERCALL_CLOBBER1 __HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG 129 #define __HYPERCALL_CLOBBER0 __HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG 130 131 #define _hypercall0(type, name) \ 132 ({ \ 133 __HYPERCALL_DECLS; \ 134 __HYPERCALL_0ARG(); \ 135 asm volatile (__HYPERCALL \ 136 : __HYPERCALL_0PARAM \ 137 : __HYPERCALL_ENTRY(name) \ 138 : __HYPERCALL_CLOBBER0); \ 139 (type)__res; \ 140 }) 141 142 #define _hypercall1(type, name, a1) \ 143 ({ \ 144 __HYPERCALL_DECLS; \ 145 __HYPERCALL_1ARG(a1); \ 146 asm volatile (__HYPERCALL \ 147 : __HYPERCALL_1PARAM \ 148 : __HYPERCALL_ENTRY(name) \ 149 : __HYPERCALL_CLOBBER1); \ 150 (type)__res; \ 151 }) 152 153 #define _hypercall2(type, name, a1, a2) \ 154 ({ \ 155 __HYPERCALL_DECLS; \ 156 __HYPERCALL_2ARG(a1, a2); \ 157 asm volatile (__HYPERCALL \ 158 : __HYPERCALL_2PARAM \ 159 : __HYPERCALL_ENTRY(name) \ 160 : __HYPERCALL_CLOBBER2); \ 161 (type)__res; \ 162 }) 163 164 #define _hypercall3(type, name, a1, a2, a3) \ 165 ({ \ 166 __HYPERCALL_DECLS; \ 167 __HYPERCALL_3ARG(a1, a2, a3); \ 168 asm volatile (__HYPERCALL \ 169 : __HYPERCALL_3PARAM \ 170 : __HYPERCALL_ENTRY(name) \ 171 : __HYPERCALL_CLOBBER3); \ 172 (type)__res; \ 173 }) 174 175 #define _hypercall4(type, name, a1, a2, a3, a4) \ 176 ({ \ 177 __HYPERCALL_DECLS; \ 178 __HYPERCALL_4ARG(a1, a2, a3, a4); \ 179 asm volatile (__HYPERCALL \ 180 : __HYPERCALL_4PARAM \ 181 : __HYPERCALL_ENTRY(name) \ 182 : __HYPERCALL_CLOBBER4); \ 183 (type)__res; \ 184 }) 185 186 #define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 187 ({ \ 188 __HYPERCALL_DECLS; \ 189 __HYPERCALL_5ARG(a1, a2, a3, a4, a5); \ 190 asm volatile (__HYPERCALL \ 191 : __HYPERCALL_5PARAM \ 192 : __HYPERCALL_ENTRY(name) \ 193 : __HYPERCALL_CLOBBER5); \ 194 (type)__res; \ 195 }) 196 197 static inline int 198 HYPERVISOR_set_trap_table(struct trap_info *table) 199 { 200 return _hypercall1(int, set_trap_table, table); 201 } 202 203 static inline int 204 HYPERVISOR_mmu_update(struct mmu_update *req, int count, 205 int *success_count, domid_t domid) 206 { 207 return _hypercall4(int, mmu_update, req, count, success_count, domid); 208 } 209 210 static inline int 211 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, 212 int *success_count, domid_t domid) 213 { 214 return _hypercall4(int, mmuext_op, op, count, success_count, domid); 215 } 216 217 static inline int 218 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) 219 { 220 return _hypercall2(int, set_gdt, frame_list, entries); 221 } 222 223 static inline int 224 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp) 225 { 226 return _hypercall2(int, stack_switch, ss, esp); 227 } 228 229 #ifdef CONFIG_X86_32 230 static inline int 231 HYPERVISOR_set_callbacks(unsigned long event_selector, 232 unsigned long event_address, 233 unsigned long failsafe_selector, 234 unsigned long failsafe_address) 235 { 236 return _hypercall4(int, set_callbacks, 237 event_selector, event_address, 238 failsafe_selector, failsafe_address); 239 } 240 #else /* CONFIG_X86_64 */ 241 static inline int 242 HYPERVISOR_set_callbacks(unsigned long event_address, 243 unsigned long failsafe_address, 244 unsigned long syscall_address) 245 { 246 return _hypercall3(int, set_callbacks, 247 event_address, failsafe_address, 248 syscall_address); 249 } 250 #endif /* CONFIG_X86_{32,64} */ 251 252 static inline int 253 HYPERVISOR_callback_op(int cmd, void *arg) 254 { 255 return _hypercall2(int, callback_op, cmd, arg); 256 } 257 258 static inline int 259 HYPERVISOR_fpu_taskswitch(int set) 260 { 261 return _hypercall1(int, fpu_taskswitch, set); 262 } 263 264 static inline int 265 HYPERVISOR_sched_op(int cmd, void *arg) 266 { 267 return _hypercall2(int, sched_op_new, cmd, arg); 268 } 269 270 static inline long 271 HYPERVISOR_set_timer_op(u64 timeout) 272 { 273 unsigned long timeout_hi = (unsigned long)(timeout>>32); 274 unsigned long timeout_lo = (unsigned long)timeout; 275 return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); 276 } 277 278 static inline int 279 HYPERVISOR_set_debugreg(int reg, unsigned long value) 280 { 281 return _hypercall2(int, set_debugreg, reg, value); 282 } 283 284 static inline unsigned long 285 HYPERVISOR_get_debugreg(int reg) 286 { 287 return _hypercall1(unsigned long, get_debugreg, reg); 288 } 289 290 static inline int 291 HYPERVISOR_update_descriptor(u64 ma, u64 desc) 292 { 293 return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32); 294 } 295 296 static inline int 297 HYPERVISOR_memory_op(unsigned int cmd, void *arg) 298 { 299 return _hypercall2(int, memory_op, cmd, arg); 300 } 301 302 static inline int 303 HYPERVISOR_multicall(void *call_list, int nr_calls) 304 { 305 return _hypercall2(int, multicall, call_list, nr_calls); 306 } 307 308 static inline int 309 HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val, 310 unsigned long flags) 311 { 312 if (sizeof(new_val) == sizeof(long)) 313 return _hypercall3(int, update_va_mapping, va, 314 new_val.pte, flags); 315 else 316 return _hypercall4(int, update_va_mapping, va, 317 new_val.pte, new_val.pte >> 32, flags); 318 } 319 320 static inline int 321 HYPERVISOR_event_channel_op(int cmd, void *arg) 322 { 323 int rc = _hypercall2(int, event_channel_op, cmd, arg); 324 if (unlikely(rc == -ENOSYS)) { 325 struct evtchn_op op; 326 op.cmd = cmd; 327 memcpy(&op.u, arg, sizeof(op.u)); 328 rc = _hypercall1(int, event_channel_op_compat, &op); 329 memcpy(arg, &op.u, sizeof(op.u)); 330 } 331 return rc; 332 } 333 334 static inline int 335 HYPERVISOR_xen_version(int cmd, void *arg) 336 { 337 return _hypercall2(int, xen_version, cmd, arg); 338 } 339 340 static inline int 341 HYPERVISOR_console_io(int cmd, int count, char *str) 342 { 343 return _hypercall3(int, console_io, cmd, count, str); 344 } 345 346 static inline int 347 HYPERVISOR_physdev_op(int cmd, void *arg) 348 { 349 int rc = _hypercall2(int, physdev_op, cmd, arg); 350 if (unlikely(rc == -ENOSYS)) { 351 struct physdev_op op; 352 op.cmd = cmd; 353 memcpy(&op.u, arg, sizeof(op.u)); 354 rc = _hypercall1(int, physdev_op_compat, &op); 355 memcpy(arg, &op.u, sizeof(op.u)); 356 } 357 return rc; 358 } 359 360 static inline int 361 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) 362 { 363 return _hypercall3(int, grant_table_op, cmd, uop, count); 364 } 365 366 static inline int 367 HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val, 368 unsigned long flags, domid_t domid) 369 { 370 if (sizeof(new_val) == sizeof(long)) 371 return _hypercall4(int, update_va_mapping_otherdomain, va, 372 new_val.pte, flags, domid); 373 else 374 return _hypercall5(int, update_va_mapping_otherdomain, va, 375 new_val.pte, new_val.pte >> 32, 376 flags, domid); 377 } 378 379 static inline int 380 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type) 381 { 382 return _hypercall2(int, vm_assist, cmd, type); 383 } 384 385 static inline int 386 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args) 387 { 388 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 389 } 390 391 #ifdef CONFIG_X86_64 392 static inline int 393 HYPERVISOR_set_segment_base(int reg, unsigned long value) 394 { 395 return _hypercall2(int, set_segment_base, reg, value); 396 } 397 #endif 398 399 static inline int 400 HYPERVISOR_suspend(unsigned long srec) 401 { 402 return _hypercall3(int, sched_op, SCHEDOP_shutdown, 403 SHUTDOWN_suspend, srec); 404 } 405 406 static inline int 407 HYPERVISOR_nmi_op(unsigned long op, unsigned long arg) 408 { 409 return _hypercall2(int, nmi_op, op, arg); 410 } 411 412 static inline void 413 MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set) 414 { 415 mcl->op = __HYPERVISOR_fpu_taskswitch; 416 mcl->args[0] = set; 417 } 418 419 static inline void 420 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va, 421 pte_t new_val, unsigned long flags) 422 { 423 mcl->op = __HYPERVISOR_update_va_mapping; 424 mcl->args[0] = va; 425 if (sizeof(new_val) == sizeof(long)) { 426 mcl->args[1] = new_val.pte; 427 mcl->args[2] = flags; 428 } else { 429 mcl->args[1] = new_val.pte; 430 mcl->args[2] = new_val.pte >> 32; 431 mcl->args[3] = flags; 432 } 433 } 434 435 static inline void 436 MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd, 437 void *uop, unsigned int count) 438 { 439 mcl->op = __HYPERVISOR_grant_table_op; 440 mcl->args[0] = cmd; 441 mcl->args[1] = (unsigned long)uop; 442 mcl->args[2] = count; 443 } 444 445 static inline void 446 MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va, 447 pte_t new_val, unsigned long flags, 448 domid_t domid) 449 { 450 mcl->op = __HYPERVISOR_update_va_mapping_otherdomain; 451 mcl->args[0] = va; 452 if (sizeof(new_val) == sizeof(long)) { 453 mcl->args[1] = new_val.pte; 454 mcl->args[2] = flags; 455 mcl->args[3] = domid; 456 } else { 457 mcl->args[1] = new_val.pte; 458 mcl->args[2] = new_val.pte >> 32; 459 mcl->args[3] = flags; 460 mcl->args[4] = domid; 461 } 462 } 463 464 static inline void 465 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr, 466 struct desc_struct desc) 467 { 468 mcl->op = __HYPERVISOR_update_descriptor; 469 if (sizeof(maddr) == sizeof(long)) { 470 mcl->args[0] = maddr; 471 mcl->args[1] = *(unsigned long *)&desc; 472 } else { 473 mcl->args[0] = maddr; 474 mcl->args[1] = maddr >> 32; 475 mcl->args[2] = desc.a; 476 mcl->args[3] = desc.b; 477 } 478 } 479 480 static inline void 481 MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg) 482 { 483 mcl->op = __HYPERVISOR_memory_op; 484 mcl->args[0] = cmd; 485 mcl->args[1] = (unsigned long)arg; 486 } 487 488 static inline void 489 MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req, 490 int count, int *success_count, domid_t domid) 491 { 492 mcl->op = __HYPERVISOR_mmu_update; 493 mcl->args[0] = (unsigned long)req; 494 mcl->args[1] = count; 495 mcl->args[2] = (unsigned long)success_count; 496 mcl->args[3] = domid; 497 } 498 499 static inline void 500 MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count, 501 int *success_count, domid_t domid) 502 { 503 mcl->op = __HYPERVISOR_mmuext_op; 504 mcl->args[0] = (unsigned long)op; 505 mcl->args[1] = count; 506 mcl->args[2] = (unsigned long)success_count; 507 mcl->args[3] = domid; 508 } 509 510 static inline void 511 MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries) 512 { 513 mcl->op = __HYPERVISOR_set_gdt; 514 mcl->args[0] = (unsigned long)frames; 515 mcl->args[1] = entries; 516 } 517 518 static inline void 519 MULTI_stack_switch(struct multicall_entry *mcl, 520 unsigned long ss, unsigned long esp) 521 { 522 mcl->op = __HYPERVISOR_stack_switch; 523 mcl->args[0] = ss; 524 mcl->args[1] = esp; 525 } 526 527 #endif /* _ASM_X86_XEN_HYPERCALL_H */ 528