1 /* $NetBSD: hypervisor.h,v 1.16 2005/12/11 12:19:48 christos Exp $ */ 2 3 /* 4 * 5 * Communication to/from hypervisor. 6 * 7 * Copyright (c) 2002-2004, K A Fraser 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a copy 10 * of this source file (the "Software"), to deal in the Software without 11 * restriction, including without limitation the rights to use, copy, modify, 12 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 13 * and to permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 * IN THE SOFTWARE. 26 */ 27 28 29 #ifndef _XEN_HYPERVISOR_H_ 30 #define _XEN_HYPERVISOR_H_ 31 32 33 struct hypervisor_attach_args { 34 const char *haa_busname; 35 }; 36 37 struct xencons_attach_args { 38 const char *xa_device; 39 }; 40 41 struct xen_npx_attach_args { 42 const char *xa_device; 43 }; 44 45 46 #define u8 uint8_t 47 #define u16 uint16_t 48 #define u32 uint32_t 49 #define u64 uint64_t 50 #define s8 int8_t 51 #define s16 int16_t 52 #define s32 int32_t 53 #define s64 int64_t 54 55 #include <machine/xen-public/xen.h> 56 #include <machine/xen-public/dom0_ops.h> 57 #include <machine/xen-public/event_channel.h> 58 #include <machine/xen-public/physdev.h> 59 #include <machine/xen-public/io/domain_controller.h> 60 #include <machine/xen-public/io/netif.h> 61 #include <machine/xen-public/io/blkif.h> 62 63 #undef u8 64 #undef u16 65 #undef u32 66 #undef u64 67 #undef s8 68 #undef s16 69 #undef s32 70 #undef s64 71 72 73 /* 74 * a placeholder for the start of day information passed up from the hypervisor 75 */ 76 union start_info_union 77 { 78 start_info_t start_info; 79 char padding[512]; 80 }; 81 extern union start_info_union start_info_union; 82 #define xen_start_info (start_info_union.start_info) 83 84 85 /* hypervisor.c */ 86 struct intrframe; 87 void do_hypervisor_callback(struct intrframe *regs); 88 void hypervisor_enable_event(unsigned int); 89 90 /* hypervisor_machdep.c */ 91 void hypervisor_unmask_event(unsigned int); 92 void hypervisor_mask_event(unsigned int); 93 void hypervisor_clear_event(unsigned int); 94 void hypervisor_enable_ipl(unsigned int); 95 void hypervisor_set_ipending(u_int32_t, int, int); 96 97 /* 98 * Assembler stubs for hyper-calls. 99 */ 100 101 static inline int 102 HYPERVISOR_set_trap_table(trap_info_t *table) 103 { 104 int ret; 105 unsigned long ign1; 106 107 __asm__ __volatile__ ( 108 TRAP_INSTR 109 : "=a" (ret), "=b" (ign1) 110 : "0" (__HYPERVISOR_set_trap_table), "1" (table) 111 : "memory" ); 112 113 return ret; 114 } 115 116 static inline int 117 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count) 118 { 119 int ret; 120 unsigned long ign1, ign2, ign3; 121 122 __asm__ __volatile__ ( 123 TRAP_INSTR 124 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) 125 : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count), 126 "3" (success_count) 127 : "memory" ); 128 129 return ret; 130 } 131 132 static inline int 133 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) 134 { 135 int ret; 136 unsigned long ign1, ign2; 137 138 __asm__ __volatile__ ( 139 TRAP_INSTR 140 : "=a" (ret), "=b" (ign1), "=c" (ign2) 141 : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries) 142 : "memory" ); 143 144 return ret; 145 } 146 147 static inline int 148 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp) 149 { 150 int ret; 151 unsigned long ign1, ign2; 152 153 __asm__ __volatile__ ( 154 TRAP_INSTR 155 : "=a" (ret), "=b" (ign1), "=c" (ign2) 156 : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp) 157 : "memory" ); 158 159 return ret; 160 } 161 162 static inline int 163 HYPERVISOR_set_callbacks( 164 unsigned long event_selector, unsigned long event_address, 165 unsigned long failsafe_selector, unsigned long failsafe_address) 166 { 167 int ret; 168 unsigned long ign1, ign2, ign3, ign4; 169 170 __asm__ __volatile__ ( 171 TRAP_INSTR 172 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) 173 : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector), 174 "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address) 175 : "memory" ); 176 177 return ret; 178 } 179 180 static inline int 181 HYPERVISOR_fpu_taskswitch(void) 182 { 183 int ret; 184 __asm__ __volatile__ ( 185 TRAP_INSTR 186 : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" ); 187 188 return ret; 189 } 190 191 static inline int 192 HYPERVISOR_yield(void) 193 { 194 int ret; 195 unsigned long ign1; 196 197 __asm__ __volatile__ ( 198 TRAP_INSTR 199 : "=a" (ret), "=b" (ign1) 200 : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield) 201 : "memory" ); 202 203 return ret; 204 } 205 206 static inline int 207 HYPERVISOR_block(void) 208 { 209 int ret; 210 unsigned long ign1; 211 212 __asm__ __volatile__ ( 213 TRAP_INSTR 214 : "=a" (ret), "=b" (ign1) 215 : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block) 216 : "memory" ); 217 218 return ret; 219 } 220 221 static inline int 222 HYPERVISOR_shutdown(void) 223 { 224 int ret; 225 unsigned long ign1; 226 227 __asm__ __volatile__ ( 228 TRAP_INSTR 229 : "=a" (ret), "=b" (ign1) 230 : "0" (__HYPERVISOR_sched_op), 231 "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift)) 232 : "memory" ); 233 234 return ret; 235 } 236 237 static inline int 238 HYPERVISOR_reboot(void) 239 { 240 int ret; 241 unsigned long ign1; 242 243 __asm__ __volatile__ ( 244 TRAP_INSTR 245 : "=a" (ret), "=b" (ign1) 246 : "0" (__HYPERVISOR_sched_op), 247 "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift)) 248 : "memory" ); 249 250 return ret; 251 } 252 253 static inline int 254 HYPERVISOR_suspend(unsigned long srec) 255 { 256 int ret; 257 unsigned long ign1, ign2; 258 259 /* NB. On suspend, control software expects a suspend record in %esi. */ 260 __asm__ __volatile__ ( 261 TRAP_INSTR 262 : "=a" (ret), "=b" (ign1), "=S" (ign2) 263 : "0" (__HYPERVISOR_sched_op), 264 "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), 265 "S" (srec) : "memory"); 266 267 return ret; 268 } 269 270 static inline long 271 HYPERVISOR_set_timer_op(uint64_t timeout) 272 { 273 int ret; 274 unsigned long timeout_hi = (unsigned long)(timeout>>32); 275 unsigned long timeout_lo = (unsigned long)timeout; 276 unsigned long ign1, ign2; 277 278 __asm__ __volatile__ ( 279 TRAP_INSTR 280 : "=a" (ret), "=b" (ign1), "=c" (ign2) 281 : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_hi), "c" (timeout_lo) 282 : "memory"); 283 284 return ret; 285 } 286 287 static inline int 288 HYPERVISOR_dom0_op(dom0_op_t *dom0_op) 289 { 290 int ret; 291 unsigned long ign1; 292 293 dom0_op->interface_version = DOM0_INTERFACE_VERSION; 294 __asm__ __volatile__ ( 295 TRAP_INSTR 296 : "=a" (ret), "=b" (ign1) 297 : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op) 298 : "memory"); 299 300 return ret; 301 } 302 303 static inline int 304 HYPERVISOR_set_debugreg(int reg, unsigned long value) 305 { 306 int ret; 307 unsigned long ign1, ign2; 308 309 __asm__ __volatile__ ( 310 TRAP_INSTR 311 : "=a" (ret), "=b" (ign1), "=c" (ign2) 312 : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value) 313 : "memory" ); 314 315 return ret; 316 } 317 318 static inline unsigned long 319 HYPERVISOR_get_debugreg(int reg) 320 { 321 unsigned long ret; 322 unsigned long ign1; 323 324 __asm__ __volatile__ ( 325 TRAP_INSTR 326 : "=a" (ret), "=b" (ign1) 327 : "0" (__HYPERVISOR_get_debugreg), "1" (reg) 328 : "memory" ); 329 330 return ret; 331 } 332 333 static inline int 334 HYPERVISOR_update_descriptor(unsigned long pa, unsigned long word1, 335 unsigned long word2) 336 { 337 int ret; 338 unsigned long ign1, ign2, ign3; 339 340 __asm__ __volatile__ ( 341 TRAP_INSTR 342 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) 343 : "0" (__HYPERVISOR_update_descriptor), "1" (pa), "2" (word1), 344 "3" (word2) 345 : "memory" ); 346 347 return ret; 348 } 349 350 static inline int 351 HYPERVISOR_set_fast_trap(int idx) 352 { 353 int ret; 354 unsigned long ign1; 355 356 __asm__ __volatile__ ( 357 TRAP_INSTR 358 : "=a" (ret), "=b" (ign1) 359 : "0" (__HYPERVISOR_set_fast_trap), "1" (idx) 360 : "memory" ); 361 362 return ret; 363 } 364 365 static inline int 366 HYPERVISOR_dom_mem_op(unsigned int op, unsigned long *extent_list, 367 unsigned long nr_extents, unsigned int extent_order) 368 { 369 int ret; 370 unsigned long ign1, ign2, ign3, ign4, ign5; 371 372 __asm__ __volatile__ ( 373 TRAP_INSTR 374 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4), 375 "=D" (ign5) 376 : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list), 377 "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF) 378 : "memory" ); 379 380 return ret; 381 } 382 383 static inline int 384 HYPERVISOR_multicall(void *call_list, int nr_calls) 385 { 386 int ret; 387 unsigned long ign1, ign2; 388 389 __asm__ __volatile__ ( 390 TRAP_INSTR 391 : "=a" (ret), "=b" (ign1), "=c" (ign2) 392 : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls) 393 : "memory" ); 394 395 return ret; 396 } 397 398 static inline int 399 HYPERVISOR_update_va_mapping(unsigned long page_nr, unsigned long new_val, 400 unsigned long flags) 401 { 402 int ret; 403 unsigned long ign1, ign2, ign3; 404 405 __asm__ __volatile__ ( 406 TRAP_INSTR 407 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) 408 : "0" (__HYPERVISOR_update_va_mapping), 409 "1" (page_nr), "2" (new_val), "3" (flags) 410 : "memory" ); 411 412 #ifdef notdef 413 if (__predict_false(ret < 0)) 414 panic("Failed update VA mapping: %08lx, %08lx, %08lx", 415 page_nr, new_val, flags); 416 #endif 417 418 return ret; 419 } 420 421 static inline int 422 HYPERVISOR_event_channel_op(void *op) 423 { 424 int ret; 425 unsigned long ign1; 426 427 __asm__ __volatile__ ( 428 TRAP_INSTR 429 : "=a" (ret), "=b" (ign1) 430 : "0" (__HYPERVISOR_event_channel_op), "1" (op) 431 : "memory" ); 432 433 return ret; 434 } 435 436 static inline int 437 HYPERVISOR_xen_version(int cmd) 438 { 439 int ret; 440 unsigned long ign1; 441 442 __asm__ __volatile__ ( 443 TRAP_INSTR 444 : "=a" (ret), "=b" (ign1) 445 : "0" (__HYPERVISOR_xen_version), "1" (cmd) 446 : "memory" ); 447 448 return ret; 449 } 450 451 static inline int 452 HYPERVISOR_console_io(int cmd, int count, char *str) 453 { 454 int ret; 455 unsigned long ign1, ign2, ign3; 456 457 __asm__ __volatile__ ( 458 TRAP_INSTR 459 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) 460 : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str) 461 : "memory" ); 462 463 return ret; 464 } 465 466 static inline int 467 HYPERVISOR_physdev_op(void *physdev_op) 468 { 469 int ret; 470 unsigned long ign1; 471 472 __asm__ __volatile__ ( 473 TRAP_INSTR 474 : "=a" (ret), "=b" (ign1) 475 : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op) 476 : "memory" ); 477 478 return ret; 479 } 480 481 static inline int 482 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) 483 { 484 int ret; 485 unsigned long ign1, ign2, ign3; 486 487 __asm__ __volatile__ ( 488 TRAP_INSTR 489 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) 490 : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (count), "3" (uop) 491 : "memory" ); 492 493 return ret; 494 } 495 496 static inline int 497 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr, 498 unsigned long new_val, unsigned long flags, domid_t domid) 499 { 500 int ret; 501 unsigned long ign1, ign2, ign3, ign4; 502 503 __asm__ __volatile__ ( 504 TRAP_INSTR 505 : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) 506 : "0" (__HYPERVISOR_update_va_mapping_otherdomain), 507 "1" (page_nr), "2" (new_val), "3" (flags), "4" (domid) : 508 "memory" ); 509 510 return ret; 511 } 512 513 static inline int 514 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type) 515 { 516 int ret; 517 unsigned long ign1, ign2; 518 519 __asm__ __volatile__ ( 520 TRAP_INSTR 521 : "=a" (ret), "=b" (ign1), "=c" (ign2) 522 : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type) 523 : "memory" ); 524 525 return ret; 526 } 527 528 /* 529 * Force a proper event-channel callback from Xen after clearing the 530 * callback mask. We do this in a very simple manner, by making a call 531 * down into Xen. The pending flag will be checked by Xen on return. 532 */ 533 static inline void hypervisor_force_callback(void) 534 { 535 (void)HYPERVISOR_xen_version(0); 536 } __attribute__((no_instrument_function)) /* used by mcount */ 537 538 static inline void 539 hypervisor_notify_via_evtchn(unsigned int port) 540 { 541 evtchn_op_t op; 542 543 op.cmd = EVTCHNOP_send; 544 op.u.send.local_port = port; 545 (void)HYPERVISOR_event_channel_op(&op); 546 } 547 548 #endif /* _XEN_HYPERVISOR_H_ */ 549