Home | History | Annotate | Line # | Download | only in include
hypervisor.h revision 1.21
      1 /*	$NetBSD: hypervisor.h,v 1.21 2006/09/24 15:30:14 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  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed by Manuel Bouyer.
     17  * 4. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  *
     31  */
     32 
     33 /*
     34  *
     35  * Communication to/from hypervisor.
     36  *
     37  * Copyright (c) 2002-2004, K A Fraser
     38  *
     39  * Permission is hereby granted, free of charge, to any person obtaining a copy
     40  * of this source file (the "Software"), to deal in the Software without
     41  * restriction, including without limitation the rights to use, copy, modify,
     42  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
     43  * and to permit persons to whom the Software is furnished to do so, subject to
     44  * the following conditions:
     45  *
     46  * The above copyright notice and this permission notice shall be included in
     47  * all copies or substantial portions of the Software.
     48  *
     49  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     50  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     51  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     52  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     53  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     54  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     55  * IN THE SOFTWARE.
     56  */
     57 
     58 
     59 #ifndef _XEN_HYPERVISOR_H_
     60 #define _XEN_HYPERVISOR_H_
     61 
     62 #include "opt_xen.h"
     63 
     64 
     65 struct hypervisor_attach_args {
     66 	const char 		*haa_busname;
     67 };
     68 
     69 struct xencons_attach_args {
     70 	const char 		*xa_device;
     71 };
     72 
     73 struct xen_npx_attach_args {
     74 	const char 		*xa_device;
     75 };
     76 
     77 
     78 #define	u8 uint8_t
     79 #define	u16 uint16_t
     80 #define	u32 uint32_t
     81 #define	u64 uint64_t
     82 #define	s8 int8_t
     83 #define	s16 int16_t
     84 #define	s32 int32_t
     85 #define	s64 int64_t
     86 
     87 #ifdef XEN3
     88 #include <machine/xen3-public/xen.h>
     89 #include <machine/xen3-public/sched.h>
     90 #include <machine/xen3-public/dom0_ops.h>
     91 #include <machine/xen3-public/event_channel.h>
     92 #include <machine/xen3-public/physdev.h>
     93 #include <machine/xen3-public/memory.h>
     94 #include <machine/xen3-public/io/netif.h>
     95 #include <machine/xen3-public/io/blkif.h>
     96 #else
     97 #include <machine/xen-public/xen.h>
     98 #include <machine/xen-public/dom0_ops.h>
     99 #include <machine/xen-public/event_channel.h>
    100 #include <machine/xen-public/physdev.h>
    101 #include <machine/xen-public/io/domain_controller.h>
    102 #include <machine/xen-public/io/netif.h>
    103 #include <machine/xen-public/io/blkif.h>
    104 #endif
    105 
    106 #undef u8
    107 #undef u16
    108 #undef u32
    109 #undef u64
    110 #undef s8
    111 #undef s16
    112 #undef s32
    113 #undef s64
    114 
    115 
    116 /*
    117  * a placeholder for the start of day information passed up from the hypervisor
    118  */
    119 union start_info_union
    120 {
    121     start_info_t start_info;
    122     char padding[512];
    123 };
    124 extern union start_info_union start_info_union;
    125 #define xen_start_info (start_info_union.start_info)
    126 
    127 /* For use in guest OSes. */
    128 volatile extern shared_info_t *HYPERVISOR_shared_info;
    129 
    130 /* hypervisor.c */
    131 struct intrframe;
    132 void do_hypervisor_callback(struct intrframe *regs);
    133 void hypervisor_enable_event(unsigned int);
    134 
    135 /* hypervisor_machdep.c */
    136 void hypervisor_unmask_event(unsigned int);
    137 void hypervisor_mask_event(unsigned int);
    138 void hypervisor_clear_event(unsigned int);
    139 void hypervisor_enable_ipl(unsigned int);
    140 void hypervisor_set_ipending(u_int32_t, int, int);
    141 
    142 /*
    143  * Assembler stubs for hyper-calls.
    144  */
    145 
    146 #define _hypercall(name, input_const, output_const) \
    147 	__asm volatile ( \
    148 	    TRAP_INSTR \
    149 	    : output_const \
    150 	    : "0" (name), input_const \
    151 	    : "memory" )
    152 
    153 #define _harg(...) __VA_ARGS__
    154 
    155 
    156 static __inline int
    157 HYPERVISOR_set_trap_table(trap_info_t *table)
    158 {
    159     int ret;
    160     unsigned long ign1;
    161 
    162 	_hypercall(__HYPERVISOR_set_trap_table, _harg("1" (table)),
    163 	    _harg("=a" (ret), "=b" (ign1)));
    164 
    165     return ret;
    166 }
    167 
    168 static __inline int
    169 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
    170 {
    171     int ret;
    172     unsigned long ign1, ign2;
    173 
    174     _hypercall(__HYPERVISOR_set_gdt, _harg("1" (frame_list), "2" (entries)),
    175 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    176 
    177     return ret;
    178 }
    179 
    180 static __inline int
    181 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
    182 {
    183     int ret;
    184     unsigned long ign1, ign2;
    185 
    186     _hypercall(__HYPERVISOR_stack_switch, _harg("1" (ss), "2" (esp)),
    187 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    188 
    189     return ret;
    190 }
    191 
    192 static __inline int
    193 HYPERVISOR_set_callbacks(
    194     unsigned long event_selector, unsigned long event_address,
    195     unsigned long failsafe_selector, unsigned long failsafe_address)
    196 {
    197     int ret;
    198     unsigned long ign1, ign2, ign3, ign4;
    199 
    200     _hypercall(__HYPERVISOR_set_callbacks,
    201 	_harg("1" (event_selector),"2" (event_address),
    202 	    "3" (failsafe_selector), "4" (failsafe_address)),
    203 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    204 
    205     return ret;
    206 }
    207 
    208 static __inline int
    209 HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
    210 {
    211     int ret;
    212     unsigned long ign1;
    213 
    214     dom0_op->interface_version = DOM0_INTERFACE_VERSION;
    215     _hypercall(__HYPERVISOR_dom0_op, _harg("1" (dom0_op)),
    216 	_harg("=a" (ret), "=b" (ign1)));
    217 
    218     return ret;
    219 }
    220 
    221 static __inline int
    222 HYPERVISOR_set_debugreg(int reg, unsigned long value)
    223 {
    224     int ret;
    225     unsigned long ign1, ign2;
    226 
    227     _hypercall(__HYPERVISOR_set_debugreg, _harg("1" (reg), "2" (value)),
    228 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    229 
    230     return ret;
    231 }
    232 
    233 static __inline unsigned long
    234 HYPERVISOR_get_debugreg(int reg)
    235 {
    236     unsigned long ret;
    237     unsigned long ign1;
    238 
    239     _hypercall(__HYPERVISOR_get_debugreg, _harg("1" (reg)),
    240 	_harg("=a" (ret), "=b" (ign1)));
    241 
    242     return ret;
    243 }
    244 
    245 #ifdef XEN3
    246 static __inline int
    247 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count,
    248     domid_t domid)
    249 {
    250     int ret;
    251     unsigned long ign1, ign2, ign3, ign4;
    252 
    253     _hypercall(__HYPERVISOR_mmu_update,
    254 	_harg("1" (req), "2" (count), "3" (success_count), "4" (domid)),
    255 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    256 
    257     return ret;
    258 }
    259 
    260 static __inline int
    261 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, int *success_count,
    262     domid_t domid)
    263 {
    264     int ret;
    265     unsigned long ign1, ign2, ign3, ign4;
    266 
    267     _hypercall(__HYPERVISOR_mmuext_op,
    268 	_harg("1" (op), "2" (count), "3" (success_count), "4" (domid)),
    269 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    270 
    271     return ret;
    272 }
    273 
    274 #if 0
    275 static __inline int
    276 HYPERVISOR_fpu_taskswitch(int set)
    277 {
    278     long ret;
    279     long ign1;
    280 
    281     _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (set)),
    282 	_harg("=a" (ret), "=b" (ign1)));
    283 
    284     return ret;
    285 }
    286 #else /* 0 */
    287 /* Xen2 compat: always i38HYPERVISOR_fpu_taskswitch(1) */
    288 static __inline int
    289 HYPERVISOR_fpu_taskswitch(void)
    290 {
    291     long ret;
    292     long ign1;
    293     _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (1)),
    294 	_harg("=a" (ret), "=b" (ign1)));
    295 
    296     return ret;
    297 }
    298 #endif /* 0 */
    299 
    300 static __inline int
    301 HYPERVISOR_update_descriptor(uint64_t ma, uint32_t word1, uint32_t word2)
    302 {
    303     int ret;
    304     unsigned long ign1, ign2, ign3, ign4;
    305     int ma1 = ma & 0xffffffff;
    306     int ma2 = (ma >> 32) & 0xffffffff;
    307 
    308     _hypercall(__HYPERVISOR_update_descriptor,
    309 	_harg("1" (ma1), "2" (ma2), "3" (word1), "4" (word2)),
    310 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    311 
    312     return ret;
    313 }
    314 
    315 static __inline int
    316 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
    317 {
    318     int ret;
    319     unsigned long ign1, ign2;
    320 
    321     _hypercall(__HYPERVISOR_memory_op, _harg("1" (cmd), "2" (arg)),
    322 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    323 
    324     return ret;
    325 }
    326 
    327 static __inline int
    328 HYPERVISOR_update_va_mapping(unsigned long page_nr, unsigned long new_val,
    329     unsigned long flags)
    330 {
    331     int ret;
    332     unsigned long ign1, ign2, ign3, ign4;
    333 
    334     _hypercall(__HYPERVISOR_update_va_mapping,
    335 	_harg("1" (page_nr), "2" (new_val), "3" (0), "4" (flags)),
    336 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    337 
    338 #ifdef notdef
    339     if (__predict_false(ret < 0))
    340         panic("Failed update VA mapping: %08lx, %08lx, %08lx",
    341               page_nr, new_val, flags);
    342 #endif
    343 
    344     return ret;
    345 }
    346 
    347 static __inline int
    348 HYPERVISOR_xen_version(int cmd, void *arg)
    349 {
    350     int ret;
    351     unsigned long ign1, ign2;
    352 
    353     _hypercall(__HYPERVISOR_xen_version, _harg("1" (cmd), "2" (arg)),
    354 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    355 
    356     return ret;
    357 }
    358 
    359 static __inline int
    360 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
    361 {
    362     int ret;
    363     unsigned long ign1, ign2, ign3;
    364 
    365     _hypercall(__HYPERVISOR_grant_table_op,
    366 	_harg("1" (cmd), "2" (uop), "3" (count)),
    367 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    368 
    369     return ret;
    370 }
    371 
    372 static __inline int
    373 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
    374     unsigned long new_val, unsigned long flags, domid_t domid)
    375 {
    376     int ret;
    377     unsigned long ign1, ign2, ign3, ign4, ign5;
    378 
    379     _hypercall(__HYPERVISOR_update_va_mapping_otherdomain,
    380 	_harg("1" (page_nr), "2" (new_val), "3" (0), "4" (flags), "5" (domid)),
    381 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
    382 	    "=D" (ign5)));
    383 
    384     return ret;
    385 }
    386 
    387 static __inline int
    388 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
    389 {
    390     long ret;
    391     unsigned long ign1, ign2, ign3;
    392 
    393     _hypercall(__HYPERVISOR_vcpu_op,
    394 	_harg("1" (cmd), "2" (vcpuid), "3" (extra_args)),
    395 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    396 
    397     return ret;
    398 }
    399 
    400 static __inline long
    401 HYPERVISOR_yield(void)
    402 {
    403     long ret;
    404     unsigned long ign1, ign2;
    405 
    406     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_yield), "2" (0)),
    407 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    408 
    409     return ret;
    410 }
    411 
    412 static __inline long
    413 HYPERVISOR_block(void)
    414 {
    415     long ret;
    416     unsigned long ign1, ign2;
    417 
    418     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_block), "2" (0)),
    419 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    420 
    421     return ret;
    422 }
    423 
    424 static __inline long
    425 HYPERVISOR_shutdown(void)
    426 {
    427     long ret;
    428     unsigned long ign1, ign2;
    429 
    430     _hypercall(__HYPERVISOR_sched_op,
    431 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_poweroff)),
    432 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    433 
    434     return ret;
    435 }
    436 
    437 static __inline long
    438 HYPERVISOR_reboot(void)
    439 {
    440     long ret;
    441     unsigned long ign1, ign2;
    442 
    443     _hypercall(__HYPERVISOR_sched_op,
    444 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_reboot)),
    445 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    446 
    447     return ret;
    448 }
    449 
    450 static __inline long
    451 HYPERVISOR_suspend(unsigned long srec)
    452 {
    453     long ret;
    454     unsigned long ign1, ign2, ign3;
    455 
    456     _hypercall(__HYPERVISOR_sched_op,
    457 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_suspend), "3" (srec)),
    458 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    459 
    460     return ret;
    461 }
    462 
    463 static __inline long
    464 HYPERVISOR_set_timer_op(uint64_t timeout)
    465 {
    466     long ret;
    467     unsigned long timeout_hi = (unsigned long)(timeout>>32);
    468     unsigned long timeout_lo = (unsigned long)timeout;
    469     unsigned long ign1, ign2;
    470 
    471     _hypercall(__HYPERVISOR_set_timer_op,
    472 	 _harg("1" (timeout_lo), "2" (timeout_hi)),
    473 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    474 
    475     return ret;
    476 }
    477 #else /* !XEN3 */
    478 static __inline int
    479 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count)
    480 {
    481     int ret;
    482     unsigned long ign1, ign2, ign3;
    483 
    484     __asm__ __volatile__ (
    485         TRAP_INSTR
    486         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    487 	: "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
    488 	  "3" (success_count)
    489 	: "memory" );
    490 
    491     return ret;
    492 }
    493 
    494 static __inline int
    495 HYPERVISOR_fpu_taskswitch(void)
    496 {
    497     int ret;
    498     __asm volatile (
    499         TRAP_INSTR
    500         : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" );
    501 
    502     return ret;
    503 }
    504 
    505 static __inline int
    506 HYPERVISOR_update_descriptor(unsigned long pa, unsigned long word1,
    507     unsigned long word2)
    508 {
    509     int ret;
    510     unsigned long ign1, ign2, ign3;
    511 
    512     __asm volatile (
    513         TRAP_INSTR
    514         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    515 	: "0" (__HYPERVISOR_update_descriptor), "1" (pa), "2" (word1),
    516 	  "3" (word2)
    517 	: "memory" );
    518 
    519     return ret;
    520 }
    521 
    522 static __inline int
    523 HYPERVISOR_yield(void)
    524 {
    525     int ret;
    526     unsigned long ign1;
    527 
    528     __asm__ __volatile__ (
    529         TRAP_INSTR
    530         : "=a" (ret), "=b" (ign1)
    531 	: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
    532 	: "memory" );
    533 
    534     return ret;
    535 }
    536 
    537 static __inline int
    538 HYPERVISOR_block(void)
    539 {
    540     int ret;
    541     unsigned long ign1;
    542 
    543     __asm__ __volatile__ (
    544         TRAP_INSTR
    545         : "=a" (ret), "=b" (ign1)
    546 	: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
    547 	: "memory" );
    548 
    549     return ret;
    550 }
    551 
    552 static __inline int
    553 HYPERVISOR_shutdown(void)
    554 {
    555     int ret;
    556     unsigned long ign1;
    557 
    558     __asm__ __volatile__ (
    559         TRAP_INSTR
    560         : "=a" (ret), "=b" (ign1)
    561 	: "0" (__HYPERVISOR_sched_op),
    562 	  "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
    563         : "memory" );
    564 
    565     return ret;
    566 }
    567 
    568 static __inline int
    569 HYPERVISOR_reboot(void)
    570 {
    571     int ret;
    572     unsigned long ign1;
    573 
    574     __asm__ __volatile__ (
    575         TRAP_INSTR
    576         : "=a" (ret), "=b" (ign1)
    577 	: "0" (__HYPERVISOR_sched_op),
    578 	  "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
    579         : "memory" );
    580 
    581     return ret;
    582 }
    583 
    584 static __inline int
    585 HYPERVISOR_suspend(unsigned long srec)
    586 {
    587     int ret;
    588     unsigned long ign1, ign2;
    589 
    590     /* NB. On suspend, control software expects a suspend record in %esi. */
    591     __asm__ __volatile__ (
    592         TRAP_INSTR
    593         : "=a" (ret), "=b" (ign1), "=S" (ign2)
    594 	: "0" (__HYPERVISOR_sched_op),
    595         "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
    596         "S" (srec) : "memory");
    597 
    598     return ret;
    599 }
    600 
    601 static __inline int
    602 HYPERVISOR_set_fast_trap(int idx)
    603 {
    604     int ret;
    605     unsigned long ign1;
    606 
    607     __asm volatile (
    608         TRAP_INSTR
    609         : "=a" (ret), "=b" (ign1)
    610 	: "0" (__HYPERVISOR_set_fast_trap), "1" (idx)
    611 	: "memory" );
    612 
    613     return ret;
    614 }
    615 
    616 static __inline int
    617 HYPERVISOR_dom_mem_op(unsigned int op, unsigned long *extent_list,
    618     unsigned long nr_extents, unsigned int extent_order)
    619 {
    620     int ret;
    621     unsigned long ign1, ign2, ign3, ign4, ign5;
    622 
    623     __asm volatile (
    624         TRAP_INSTR
    625         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
    626 	  "=D" (ign5)
    627 	: "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
    628 	  "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
    629         : "memory" );
    630 
    631     return ret;
    632 }
    633 
    634 static __inline int
    635 HYPERVISOR_update_va_mapping(unsigned long page_nr, unsigned long new_val,
    636     unsigned long flags)
    637 {
    638     int ret;
    639     unsigned long ign1, ign2, ign3;
    640 
    641     __asm volatile (
    642         TRAP_INSTR
    643         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    644 	: "0" (__HYPERVISOR_update_va_mapping),
    645           "1" (page_nr), "2" (new_val), "3" (flags)
    646 	: "memory" );
    647 
    648 #ifdef notdef
    649     if (__predict_false(ret < 0))
    650         panic("Failed update VA mapping: %08lx, %08lx, %08lx",
    651               page_nr, new_val, flags);
    652 #endif
    653 
    654     return ret;
    655 }
    656 
    657 static __inline int
    658 HYPERVISOR_xen_version(int cmd)
    659 {
    660     int ret;
    661     unsigned long ign1;
    662 
    663     __asm volatile (
    664         TRAP_INSTR
    665         : "=a" (ret), "=b" (ign1)
    666 	: "0" (__HYPERVISOR_xen_version), "1" (cmd)
    667 	: "memory" );
    668 
    669     return ret;
    670 }
    671 
    672 static __inline int
    673 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
    674 {
    675     int ret;
    676     unsigned long ign1, ign2, ign3;
    677 
    678     __asm volatile (
    679         TRAP_INSTR
    680         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    681 	: "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (count), "3" (uop)
    682 	: "memory" );
    683 
    684     return ret;
    685 }
    686 
    687 static __inline int
    688 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
    689     unsigned long new_val, unsigned long flags, domid_t domid)
    690 {
    691     int ret;
    692     unsigned long ign1, ign2, ign3, ign4;
    693 
    694     __asm volatile (
    695         TRAP_INSTR
    696         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
    697 	: "0" (__HYPERVISOR_update_va_mapping_otherdomain),
    698           "1" (page_nr), "2" (new_val), "3" (flags), "4" (domid) :
    699         "memory" );
    700 
    701     return ret;
    702 }
    703 
    704 static __inline long
    705 HYPERVISOR_set_timer_op(uint64_t timeout)
    706 {
    707     long ret;
    708     unsigned long timeout_hi = (unsigned long)(timeout>>32);
    709     unsigned long timeout_lo = (unsigned long)timeout;
    710     unsigned long ign1, ign2;
    711 
    712     __asm volatile (
    713         TRAP_INSTR
    714         : "=a" (ret), "=b" (ign1), "=c" (ign2)
    715 	: "0" (__HYPERVISOR_set_timer_op), "b" (timeout_hi), "c" (timeout_lo)
    716 	: "memory");
    717 
    718     return ret;
    719 }
    720 #endif /* XEN3 */
    721 
    722 static __inline int
    723 HYPERVISOR_multicall(void *call_list, int nr_calls)
    724 {
    725     int ret;
    726     unsigned long ign1, ign2;
    727 
    728     _hypercall(__HYPERVISOR_multicall,
    729 	 _harg("1" (call_list), "2" (nr_calls)),
    730 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    731 
    732     return ret;
    733 }
    734 
    735 
    736 static __inline int
    737 HYPERVISOR_event_channel_op(void *op)
    738 {
    739     int ret;
    740     unsigned long ign1;
    741 
    742     _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op)),
    743 	_harg("=a" (ret), "=b" (ign1)));
    744 
    745     return ret;
    746 }
    747 
    748 static __inline int
    749 HYPERVISOR_console_io(int cmd, int count, char *str)
    750 {
    751     int ret;
    752     unsigned long ign1, ign2, ign3;
    753 
    754     _hypercall(__HYPERVISOR_console_io,
    755 	_harg("1" (cmd), "2" (count), "3" (str)),
    756 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    757 
    758     return ret;
    759 }
    760 
    761 static __inline int
    762 HYPERVISOR_physdev_op(void *physdev_op)
    763 {
    764     int ret;
    765     unsigned long ign1;
    766 
    767     _hypercall(__HYPERVISOR_physdev_op, _harg("1" (physdev_op)),
    768 	_harg("=a" (ret), "=b" (ign1)));
    769 
    770     return ret;
    771 }
    772 
    773 static __inline int
    774 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
    775 {
    776     int ret;
    777     unsigned long ign1, ign2;
    778 
    779     _hypercall(__HYPERVISOR_vm_assist, _harg("1" (cmd), "2" (type)),
    780 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    781 
    782     return ret;
    783 }
    784 
    785 /*
    786  * Force a proper event-channel callback from Xen after clearing the
    787  * callback mask. We do this in a very simple manner, by making a call
    788  * down into Xen. The pending flag will be checked by Xen on return.
    789  */
    790 static __inline void hypervisor_force_callback(void)
    791 {
    792 #ifdef XEN3
    793 	(void)HYPERVISOR_xen_version(0, (void*)0);
    794 #else
    795 	(void)HYPERVISOR_xen_version(0);
    796 #endif
    797 } __attribute__((no_instrument_function)) /* used by mcount */
    798 
    799 static __inline void
    800 hypervisor_notify_via_evtchn(unsigned int port)
    801 {
    802 	evtchn_op_t op;
    803 
    804 	op.cmd = EVTCHNOP_send;
    805 #ifdef XEN3
    806 	op.u.send.port = port;
    807 #else
    808 	op.u.send.local_port = port;
    809 #endif
    810 	(void)HYPERVISOR_event_channel_op(&op);
    811 }
    812 
    813 #endif /* _XEN_HYPERVISOR_H_ */
    814