1 /* $NetBSD: hypercalls.h,v 1.2 2020/04/25 15:26:17 bouyer Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Manuel Bouyer. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 /* 29 * 30 * Communication to/from hypervisor. 31 * 32 * Copyright (c) 2002-2004, K A Fraser 33 * 34 * Permission is hereby granted, free of charge, to any person obtaining a copy 35 * of this source file (the "Software"), to deal in the Software without 36 * restriction, including without limitation the rights to use, copy, modify, 37 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 38 * and to permit persons to whom the Software is furnished to do so, subject to 39 * the following conditions: 40 * 41 * The above copyright notice and this permission notice shall be included in 42 * all copies or substantial portions of the Software. 43 * 44 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 49 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 50 * IN THE SOFTWARE. 51 */ 52 53 54 #ifndef _XENI386_HYPERVISOR_H_ 55 #define _XENI386_HYPERVISOR_H_ 56 /* 57 * Assembler stubs for hyper-calls. 58 */ 59 60 #include <machine/pte.h> /* pt_entry_t */ 61 62 /* hypercall via the hypercall call page */ 63 #define __str(x) #x 64 #define _str(x) __str(x) 65 #define _hypercall(name, input_const, output_const) \ 66 __asm volatile ( \ 67 "call hypercall_page + ("_str(name)" * 32)" \ 68 : output_const \ 69 : input_const \ 70 : "memory" ) 71 72 #define _harg(...) __VA_ARGS__ 73 74 75 static __inline int 76 HYPERVISOR_set_trap_table(trap_info_t *table) 77 { 78 int ret; 79 unsigned long ign1; 80 81 _hypercall(__HYPERVISOR_set_trap_table, _harg("1" (table)), 82 _harg("=a" (ret), "=b" (ign1))); 83 84 return ret; 85 } 86 87 static __inline int 88 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) 89 { 90 int ret; 91 unsigned long ign1, ign2; 92 93 _hypercall(__HYPERVISOR_set_gdt, _harg("1" (frame_list), "2" (entries)), 94 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 95 96 return ret; 97 } 98 99 static __inline int 100 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp) 101 { 102 int ret; 103 unsigned long ign1, ign2; 104 105 _hypercall(__HYPERVISOR_stack_switch, _harg("1" (ss), "2" (esp)), 106 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 107 108 return ret; 109 } 110 111 static __inline int 112 HYPERVISOR_set_callbacks( 113 unsigned long event_selector, unsigned long event_address, 114 unsigned long failsafe_selector, unsigned long failsafe_address) 115 { 116 int ret; 117 unsigned long ign1, ign2, ign3, ign4; 118 119 _hypercall(__HYPERVISOR_set_callbacks, 120 _harg("1" (event_selector),"2" (event_address), 121 "3" (failsafe_selector), "4" (failsafe_address)), 122 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4))); 123 124 return ret; 125 } 126 127 #if __XEN_INTERFACE_VERSION__ < 0x00030204 128 static __inline int 129 HYPERVISOR_dom0_op(dom0_op_t *dom0_op) 130 { 131 int ret; 132 unsigned long ign1; 133 134 dom0_op->interface_version = DOM0_INTERFACE_VERSION; 135 _hypercall(__HYPERVISOR_dom0_op, _harg("1" (dom0_op)), 136 _harg("=a" (ret), "=b" (ign1))); 137 138 return ret; 139 } 140 #endif /* __XEN_INTERFACE_VERSION__ */ 141 142 static __inline int 143 HYPERVISOR_set_debugreg(int reg, unsigned long value) 144 { 145 int ret; 146 unsigned long ign1, ign2; 147 148 _hypercall(__HYPERVISOR_set_debugreg, _harg("1" (reg), "2" (value)), 149 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 150 151 return ret; 152 } 153 154 static __inline unsigned long 155 HYPERVISOR_get_debugreg(int reg) 156 { 157 unsigned long ret; 158 unsigned long ign1; 159 160 _hypercall(__HYPERVISOR_get_debugreg, _harg("1" (reg)), 161 _harg("=a" (ret), "=b" (ign1))); 162 163 return ret; 164 } 165 166 #include <xen/include/public/arch-x86/xen-mca.h> 167 168 static __inline int 169 HYPERVISOR_machine_check(struct xen_mc *mc) 170 { 171 int ret; 172 unsigned long ign1; 173 174 mc->interface_version = XEN_MCA_INTERFACE_VERSION; 175 _hypercall(__HYPERVISOR_mca, _harg("1" (mc)), 176 _harg("=a" (ret), "=b" (ign1))); 177 178 return ret; 179 } 180 181 static __inline int 182 HYPERVISOR_hvm_op(int cmd, void *arg) 183 { 184 int ret; 185 unsigned long ign1, ign2; 186 187 _hypercall(__HYPERVISOR_hvm_op, _harg("1" (cmd), "2" (arg)), 188 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 189 190 return ret; 191 } 192 193 static __inline int 194 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count, 195 domid_t domid) 196 { 197 int ret; 198 unsigned long ign1, ign2, ign3, ign4; 199 200 _hypercall(__HYPERVISOR_mmu_update, 201 _harg("1" (req), "2" (count), "3" (success_count), "4" (domid)), 202 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4))); 203 204 return ret; 205 } 206 207 static __inline int 208 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, int *success_count, 209 domid_t domid) 210 { 211 int ret; 212 unsigned long ign1, ign2, ign3, ign4; 213 214 _hypercall(__HYPERVISOR_mmuext_op, 215 _harg("1" (op), "2" (count), "3" (success_count), "4" (domid)), 216 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4))); 217 218 return ret; 219 } 220 221 static __inline int 222 HYPERVISOR_fpu_taskswitch(int set) 223 { 224 long ret; 225 long ign1; 226 227 _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (set)), 228 _harg("=a" (ret), "=b" (ign1))); 229 230 return ret; 231 } 232 233 static __inline int 234 HYPERVISOR_update_descriptor(uint64_t ma, uint32_t word1, uint32_t word2) 235 { 236 int ret; 237 unsigned long ign1, ign2, ign3, ign4; 238 int ma1 = ma & 0xffffffff; 239 int ma2 = (ma >> 32) & 0xffffffff; 240 241 _hypercall(__HYPERVISOR_update_descriptor, 242 _harg("1" (ma1), "2" (ma2), "3" (word1), "4" (word2)), 243 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4))); 244 245 return ret; 246 } 247 248 static __inline int 249 HYPERVISOR_memory_op(unsigned int cmd, void *arg) 250 { 251 int ret; 252 unsigned long ign1, ign2; 253 254 _hypercall(__HYPERVISOR_memory_op, _harg("1" (cmd), "2" (arg)), 255 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 256 257 return ret; 258 } 259 260 #ifdef XENPV 261 static __inline int 262 HYPERVISOR_update_va_mapping(unsigned long page_nr, pt_entry_t new_val, 263 unsigned long flags) 264 { 265 int ret; 266 unsigned long ign1, ign2, ign3, ign4; 267 unsigned long pte_low, pte_hi; 268 269 pte_low = new_val & 0xffffffff; 270 pte_hi = new_val >> 32; 271 272 _hypercall(__HYPERVISOR_update_va_mapping, 273 _harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags)), 274 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4))); 275 276 #ifdef notdef 277 if (__predict_false(ret < 0)) 278 panic("Failed update VA mapping: %08lx, %08lx, %08lx", 279 page_nr, new_val, flags); 280 #endif 281 282 return ret; 283 } 284 285 static __inline int 286 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr, 287 pt_entry_t new_val, unsigned long flags, domid_t domid) 288 { 289 int ret; 290 unsigned long ign1, ign2, ign3, ign4, ign5; 291 unsigned long pte_low, pte_hi; 292 293 pte_low = new_val & 0xffffffff; 294 pte_hi = new_val >> 32; 295 296 _hypercall(__HYPERVISOR_update_va_mapping_otherdomain, 297 _harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags), "5" (domid)), 298 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4), 299 "=D" (ign5))); 300 301 return ret; 302 } 303 #endif /* XENPV */ 304 305 static __inline int 306 HYPERVISOR_xen_version(int cmd, void *arg) 307 { 308 int ret; 309 unsigned long ign1, ign2; 310 311 _hypercall(__HYPERVISOR_xen_version, _harg("1" (cmd), "2" (arg)), 312 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 313 314 return ret; 315 } 316 317 static __inline int 318 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) 319 { 320 int ret; 321 unsigned long ign1, ign2, ign3; 322 323 _hypercall(__HYPERVISOR_grant_table_op, 324 _harg("1" (cmd), "2" (uop), "3" (count)), 325 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3))); 326 327 return ret; 328 } 329 330 331 static __inline int 332 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args) 333 { 334 long ret; 335 unsigned long ign1, ign2, ign3; 336 337 _hypercall(__HYPERVISOR_vcpu_op, 338 _harg("1" (cmd), "2" (vcpuid), "3" (extra_args)), 339 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3))); 340 341 return ret; 342 } 343 344 static __inline long 345 HYPERVISOR_yield(void) 346 { 347 long ret; 348 unsigned long ign1, ign2; 349 350 _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_yield), "2" (0)), 351 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 352 353 return ret; 354 } 355 356 static __inline long 357 HYPERVISOR_block(void) 358 { 359 long ret; 360 unsigned long ign1, ign2; 361 362 _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_block), "2" (0)), 363 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 364 365 return ret; 366 } 367 368 static __inline long 369 HYPERVISOR_shutdown(void) 370 { 371 long ret; 372 unsigned long ign1, ign2; 373 374 #if __XEN_INTERFACE_VERSION__ >= 0x00030201 375 376 struct sched_shutdown shutdown_reason = { 377 .reason = SHUTDOWN_poweroff 378 }; 379 380 _hypercall(__HYPERVISOR_sched_op, 381 _harg("1" (SCHEDOP_shutdown), "2" (&shutdown_reason)), 382 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 383 #else 384 _hypercall(__HYPERVISOR_sched_op, 385 _harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_poweroff)), 386 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 387 388 #endif 389 390 return ret; 391 } 392 393 static __inline long 394 HYPERVISOR_crash(void) 395 { 396 long ret; 397 unsigned long ign1, ign2; 398 399 #if __XEN_INTERFACE_VERSION__ >= 0x00030201 400 401 struct sched_shutdown shutdown_reason = { 402 .reason = SHUTDOWN_crash 403 }; 404 405 _hypercall(__HYPERVISOR_sched_op, 406 _harg("1" (SCHEDOP_shutdown), "2" (&shutdown_reason)), 407 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 408 #else 409 _hypercall(__HYPERVISOR_sched_op, 410 _harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_crash)), 411 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 412 #endif 413 414 return ret; 415 } 416 417 static __inline long 418 HYPERVISOR_reboot(void) 419 { 420 long ret; 421 unsigned long ign1, ign2; 422 423 #if __XEN_INTERFACE_VERSION__ >= 0x00030201 424 425 struct sched_shutdown shutdown_reason = { 426 .reason = SHUTDOWN_reboot 427 }; 428 429 _hypercall(__HYPERVISOR_sched_op, 430 _harg("1" (SCHEDOP_shutdown), "2" (&shutdown_reason)), 431 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 432 #else 433 _hypercall(__HYPERVISOR_sched_op, 434 _harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_reboot)), 435 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 436 #endif 437 438 return ret; 439 } 440 441 static __inline long 442 HYPERVISOR_suspend(unsigned long srec) 443 { 444 long ret; 445 unsigned long ign1, ign2, ign3; 446 447 #if __XEN_INTERFACE_VERSION__ >= 0x00030201 448 449 struct sched_shutdown shutdown_reason = { 450 .reason = SHUTDOWN_suspend 451 }; 452 453 _hypercall(__HYPERVISOR_sched_op, 454 _harg("1" (SCHEDOP_shutdown), "2" (&shutdown_reason), "3" (srec)), 455 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3))); 456 #else 457 _hypercall(__HYPERVISOR_sched_op, 458 _harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_suspend), "3" (srec)), 459 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3))); 460 #endif 461 462 return ret; 463 } 464 465 static __inline long 466 HYPERVISOR_set_timer_op(uint64_t timeout) 467 { 468 long ret; 469 unsigned long timeout_hi = (unsigned long)(timeout>>32); 470 unsigned long timeout_lo = (unsigned long)timeout; 471 unsigned long ign1, ign2; 472 473 _hypercall(__HYPERVISOR_set_timer_op, 474 _harg("1" (timeout_lo), "2" (timeout_hi)), 475 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 476 477 return ret; 478 } 479 480 static __inline int 481 HYPERVISOR_platform_op(struct xen_platform_op *platform_op) 482 { 483 int ret; 484 unsigned long ign1; 485 486 platform_op->interface_version = XENPF_INTERFACE_VERSION; 487 _hypercall(__HYPERVISOR_platform_op, _harg("1" (platform_op)), 488 _harg("=a" (ret), "=b" (ign1))); 489 490 return ret; 491 } 492 493 static __inline int 494 HYPERVISOR_multicall(void *call_list, int nr_calls) 495 { 496 int ret; 497 unsigned long ign1, ign2; 498 499 _hypercall(__HYPERVISOR_multicall, 500 _harg("1" (call_list), "2" (nr_calls)), 501 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 502 503 return ret; 504 } 505 506 507 static __inline int 508 HYPERVISOR_event_channel_op(evtchn_op_t *op) 509 { 510 int ret; 511 unsigned long ign1; 512 513 #if __XEN_INTERFACE_VERSION__ < 0x00030202 514 _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op)), 515 _harg("=a" (ret), "=b" (ign1))); 516 #else 517 unsigned long ign2; 518 519 _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op->cmd), "2" (&op->u)), 520 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 521 #endif 522 return ret; 523 } 524 525 static __inline int 526 HYPERVISOR_console_io(int cmd, int count, char *str) 527 { 528 int ret; 529 unsigned long ign1, ign2, ign3; 530 531 _hypercall(__HYPERVISOR_console_io, 532 _harg("1" (cmd), "2" (count), "3" (str)), 533 _harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3))); 534 535 return ret; 536 } 537 538 static __inline int 539 HYPERVISOR_physdev_op(int cmd, void *physdev_op) 540 { 541 int ret; 542 unsigned long ign1, ign2; 543 544 _hypercall(__HYPERVISOR_physdev_op, _harg("1" (cmd), "2" (physdev_op)), 545 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 546 547 return ret; 548 } 549 550 static __inline int 551 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type) 552 { 553 int ret; 554 unsigned long ign1, ign2; 555 556 _hypercall(__HYPERVISOR_vm_assist, _harg("1" (cmd), "2" (type)), 557 _harg("=a" (ret), "=b" (ign1), "=c" (ign2))); 558 559 return ret; 560 } 561 562 static __inline int 563 HYPERVISOR_sysctl(void *sysctl) 564 { 565 int ret; 566 unsigned long ign1; 567 568 _hypercall(__HYPERVISOR_sysctl, _harg("1" (sysctl)), 569 _harg("=a" (ret), "=b" (ign1))); 570 571 return ret; 572 } 573 #endif /* _XENI386_HYPERVISOR_H_ */ 574