Home | History | Annotate | Line # | Download | only in include
hypervisor.h revision 1.14.2.2
      1 /*	$NetBSD: hypervisor.h,v 1.14.2.2 2006/12/30 20:47:25 yamt 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 #if defined(XEN3) && !defined(XEN_COMPAT_030001)
    147 /* hypercall via the hypercall call page */
    148 #define __str(x) #x
    149 #define _str(x) __str(x)
    150 #define _hypercall(name, input_const, output_const) \
    151 	__asm volatile ( \
    152 	    "call hypercall_page + ("_str(name)" * 32)" \
    153 	    : output_const \
    154 	    : input_const \
    155 	    : "memory" )
    156 #else
    157 /* traditionnal hypercall via int 0x82 */
    158 #define _hypercall(name, input_const, output_const) \
    159 	__asm volatile ( \
    160 	    TRAP_INSTR \
    161 	    : output_const \
    162 	    : "0" (name), input_const \
    163 	    : "memory" )
    164 #endif
    165 
    166 #define _harg(...) __VA_ARGS__
    167 
    168 
    169 static __inline int
    170 HYPERVISOR_set_trap_table(trap_info_t *table)
    171 {
    172     int ret;
    173     unsigned long ign1;
    174 
    175 	_hypercall(__HYPERVISOR_set_trap_table, _harg("1" (table)),
    176 	    _harg("=a" (ret), "=b" (ign1)));
    177 
    178     return ret;
    179 }
    180 
    181 static __inline int
    182 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
    183 {
    184     int ret;
    185     unsigned long ign1, ign2;
    186 
    187     _hypercall(__HYPERVISOR_set_gdt, _harg("1" (frame_list), "2" (entries)),
    188 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    189 
    190     return ret;
    191 }
    192 
    193 static __inline int
    194 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
    195 {
    196     int ret;
    197     unsigned long ign1, ign2;
    198 
    199     _hypercall(__HYPERVISOR_stack_switch, _harg("1" (ss), "2" (esp)),
    200 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    201 
    202     return ret;
    203 }
    204 
    205 static __inline int
    206 HYPERVISOR_set_callbacks(
    207     unsigned long event_selector, unsigned long event_address,
    208     unsigned long failsafe_selector, unsigned long failsafe_address)
    209 {
    210     int ret;
    211     unsigned long ign1, ign2, ign3, ign4;
    212 
    213     _hypercall(__HYPERVISOR_set_callbacks,
    214 	_harg("1" (event_selector),"2" (event_address),
    215 	    "3" (failsafe_selector), "4" (failsafe_address)),
    216 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    217 
    218     return ret;
    219 }
    220 
    221 static __inline int
    222 HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
    223 {
    224     int ret;
    225     unsigned long ign1;
    226 
    227     dom0_op->interface_version = DOM0_INTERFACE_VERSION;
    228     _hypercall(__HYPERVISOR_dom0_op, _harg("1" (dom0_op)),
    229 	_harg("=a" (ret), "=b" (ign1)));
    230 
    231     return ret;
    232 }
    233 
    234 static __inline int
    235 HYPERVISOR_set_debugreg(int reg, unsigned long value)
    236 {
    237     int ret;
    238     unsigned long ign1, ign2;
    239 
    240     _hypercall(__HYPERVISOR_set_debugreg, _harg("1" (reg), "2" (value)),
    241 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    242 
    243     return ret;
    244 }
    245 
    246 static __inline unsigned long
    247 HYPERVISOR_get_debugreg(int reg)
    248 {
    249     unsigned long ret;
    250     unsigned long ign1;
    251 
    252     _hypercall(__HYPERVISOR_get_debugreg, _harg("1" (reg)),
    253 	_harg("=a" (ret), "=b" (ign1)));
    254 
    255     return ret;
    256 }
    257 
    258 #ifdef XEN3
    259 static __inline int
    260 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count,
    261     domid_t domid)
    262 {
    263     int ret;
    264     unsigned long ign1, ign2, ign3, ign4;
    265 
    266     _hypercall(__HYPERVISOR_mmu_update,
    267 	_harg("1" (req), "2" (count), "3" (success_count), "4" (domid)),
    268 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    269 
    270     return ret;
    271 }
    272 
    273 static __inline int
    274 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, int *success_count,
    275     domid_t domid)
    276 {
    277     int ret;
    278     unsigned long ign1, ign2, ign3, ign4;
    279 
    280     _hypercall(__HYPERVISOR_mmuext_op,
    281 	_harg("1" (op), "2" (count), "3" (success_count), "4" (domid)),
    282 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    283 
    284     return ret;
    285 }
    286 
    287 #if 0
    288 static __inline int
    289 HYPERVISOR_fpu_taskswitch(int set)
    290 {
    291     long ret;
    292     long ign1;
    293 
    294     _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (set)),
    295 	_harg("=a" (ret), "=b" (ign1)));
    296 
    297     return ret;
    298 }
    299 #else /* 0 */
    300 /* Xen2 compat: always i38HYPERVISOR_fpu_taskswitch(1) */
    301 static __inline int
    302 HYPERVISOR_fpu_taskswitch(void)
    303 {
    304     long ret;
    305     long ign1;
    306     _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (1)),
    307 	_harg("=a" (ret), "=b" (ign1)));
    308 
    309     return ret;
    310 }
    311 #endif /* 0 */
    312 
    313 static __inline int
    314 HYPERVISOR_update_descriptor(uint64_t ma, uint32_t word1, uint32_t word2)
    315 {
    316     int ret;
    317     unsigned long ign1, ign2, ign3, ign4;
    318     int ma1 = ma & 0xffffffff;
    319     int ma2 = (ma >> 32) & 0xffffffff;
    320 
    321     _hypercall(__HYPERVISOR_update_descriptor,
    322 	_harg("1" (ma1), "2" (ma2), "3" (word1), "4" (word2)),
    323 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    324 
    325     return ret;
    326 }
    327 
    328 static __inline int
    329 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
    330 {
    331     int ret;
    332     unsigned long ign1, ign2;
    333 
    334     _hypercall(__HYPERVISOR_memory_op, _harg("1" (cmd), "2" (arg)),
    335 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    336 
    337     return ret;
    338 }
    339 
    340 static __inline int
    341 HYPERVISOR_update_va_mapping(unsigned long page_nr, unsigned long new_val,
    342     unsigned long flags)
    343 {
    344     int ret;
    345     unsigned long ign1, ign2, ign3, ign4;
    346 
    347     _hypercall(__HYPERVISOR_update_va_mapping,
    348 	_harg("1" (page_nr), "2" (new_val), "3" (0), "4" (flags)),
    349 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    350 
    351 #ifdef notdef
    352     if (__predict_false(ret < 0))
    353         panic("Failed update VA mapping: %08lx, %08lx, %08lx",
    354               page_nr, new_val, flags);
    355 #endif
    356 
    357     return ret;
    358 }
    359 
    360 static __inline int
    361 HYPERVISOR_xen_version(int cmd, void *arg)
    362 {
    363     int ret;
    364     unsigned long ign1, ign2;
    365 
    366     _hypercall(__HYPERVISOR_xen_version, _harg("1" (cmd), "2" (arg)),
    367 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    368 
    369     return ret;
    370 }
    371 
    372 static __inline int
    373 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
    374 {
    375     int ret;
    376     unsigned long ign1, ign2, ign3;
    377 
    378     _hypercall(__HYPERVISOR_grant_table_op,
    379 	_harg("1" (cmd), "2" (uop), "3" (count)),
    380 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    381 
    382     return ret;
    383 }
    384 
    385 static __inline int
    386 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
    387     unsigned long new_val, unsigned long flags, domid_t domid)
    388 {
    389     int ret;
    390     unsigned long ign1, ign2, ign3, ign4, ign5;
    391 
    392     _hypercall(__HYPERVISOR_update_va_mapping_otherdomain,
    393 	_harg("1" (page_nr), "2" (new_val), "3" (0), "4" (flags), "5" (domid)),
    394 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
    395 	    "=D" (ign5)));
    396 
    397     return ret;
    398 }
    399 
    400 static __inline int
    401 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
    402 {
    403     long ret;
    404     unsigned long ign1, ign2, ign3;
    405 
    406     _hypercall(__HYPERVISOR_vcpu_op,
    407 	_harg("1" (cmd), "2" (vcpuid), "3" (extra_args)),
    408 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    409 
    410     return ret;
    411 }
    412 
    413 static __inline long
    414 HYPERVISOR_yield(void)
    415 {
    416     long ret;
    417     unsigned long ign1, ign2;
    418 
    419     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_yield), "2" (0)),
    420 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    421 
    422     return ret;
    423 }
    424 
    425 static __inline long
    426 HYPERVISOR_block(void)
    427 {
    428     long ret;
    429     unsigned long ign1, ign2;
    430 
    431     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_block), "2" (0)),
    432 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    433 
    434     return ret;
    435 }
    436 
    437 static __inline long
    438 HYPERVISOR_shutdown(void)
    439 {
    440     long ret;
    441     unsigned long ign1, ign2;
    442 
    443     _hypercall(__HYPERVISOR_sched_op,
    444 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_poweroff)),
    445 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    446 
    447     return ret;
    448 }
    449 
    450 static __inline long
    451 HYPERVISOR_reboot(void)
    452 {
    453     long ret;
    454     unsigned long ign1, ign2;
    455 
    456     _hypercall(__HYPERVISOR_sched_op,
    457 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_reboot)),
    458 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    459 
    460     return ret;
    461 }
    462 
    463 static __inline long
    464 HYPERVISOR_suspend(unsigned long srec)
    465 {
    466     long ret;
    467     unsigned long ign1, ign2, ign3;
    468 
    469     _hypercall(__HYPERVISOR_sched_op,
    470 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_suspend), "3" (srec)),
    471 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    472 
    473     return ret;
    474 }
    475 
    476 static __inline long
    477 HYPERVISOR_set_timer_op(uint64_t timeout)
    478 {
    479     long ret;
    480     unsigned long timeout_hi = (unsigned long)(timeout>>32);
    481     unsigned long timeout_lo = (unsigned long)timeout;
    482     unsigned long ign1, ign2;
    483 
    484     _hypercall(__HYPERVISOR_set_timer_op,
    485 	 _harg("1" (timeout_lo), "2" (timeout_hi)),
    486 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    487 
    488     return ret;
    489 }
    490 #else /* !XEN3 */
    491 static __inline int
    492 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count)
    493 {
    494     int ret;
    495     unsigned long ign1, ign2, ign3;
    496 
    497     __asm__ __volatile__ (
    498         TRAP_INSTR
    499         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    500 	: "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
    501 	  "3" (success_count)
    502 	: "memory" );
    503 
    504     return ret;
    505 }
    506 
    507 static __inline int
    508 HYPERVISOR_fpu_taskswitch(void)
    509 {
    510     int ret;
    511     __asm volatile (
    512         TRAP_INSTR
    513         : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" );
    514 
    515     return ret;
    516 }
    517 
    518 static __inline int
    519 HYPERVISOR_update_descriptor(unsigned long pa, unsigned long word1,
    520     unsigned long word2)
    521 {
    522     int ret;
    523     unsigned long ign1, ign2, ign3;
    524 
    525     __asm volatile (
    526         TRAP_INSTR
    527         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    528 	: "0" (__HYPERVISOR_update_descriptor), "1" (pa), "2" (word1),
    529 	  "3" (word2)
    530 	: "memory" );
    531 
    532     return ret;
    533 }
    534 
    535 static __inline int
    536 HYPERVISOR_yield(void)
    537 {
    538     int ret;
    539     unsigned long ign1;
    540 
    541     __asm__ __volatile__ (
    542         TRAP_INSTR
    543         : "=a" (ret), "=b" (ign1)
    544 	: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
    545 	: "memory" );
    546 
    547     return ret;
    548 }
    549 
    550 static __inline int
    551 HYPERVISOR_block(void)
    552 {
    553     int ret;
    554     unsigned long ign1;
    555 
    556     __asm__ __volatile__ (
    557         TRAP_INSTR
    558         : "=a" (ret), "=b" (ign1)
    559 	: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
    560 	: "memory" );
    561 
    562     return ret;
    563 }
    564 
    565 static __inline int
    566 HYPERVISOR_shutdown(void)
    567 {
    568     int ret;
    569     unsigned long ign1;
    570 
    571     __asm__ __volatile__ (
    572         TRAP_INSTR
    573         : "=a" (ret), "=b" (ign1)
    574 	: "0" (__HYPERVISOR_sched_op),
    575 	  "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
    576         : "memory" );
    577 
    578     return ret;
    579 }
    580 
    581 static __inline int
    582 HYPERVISOR_reboot(void)
    583 {
    584     int ret;
    585     unsigned long ign1;
    586 
    587     __asm__ __volatile__ (
    588         TRAP_INSTR
    589         : "=a" (ret), "=b" (ign1)
    590 	: "0" (__HYPERVISOR_sched_op),
    591 	  "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
    592         : "memory" );
    593 
    594     return ret;
    595 }
    596 
    597 static __inline int
    598 HYPERVISOR_suspend(unsigned long srec)
    599 {
    600     int ret;
    601     unsigned long ign1, ign2;
    602 
    603     /* NB. On suspend, control software expects a suspend record in %esi. */
    604     __asm__ __volatile__ (
    605         TRAP_INSTR
    606         : "=a" (ret), "=b" (ign1), "=S" (ign2)
    607 	: "0" (__HYPERVISOR_sched_op),
    608         "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
    609         "S" (srec) : "memory");
    610 
    611     return ret;
    612 }
    613 
    614 static __inline int
    615 HYPERVISOR_set_fast_trap(int idx)
    616 {
    617     int ret;
    618     unsigned long ign1;
    619 
    620     __asm volatile (
    621         TRAP_INSTR
    622         : "=a" (ret), "=b" (ign1)
    623 	: "0" (__HYPERVISOR_set_fast_trap), "1" (idx)
    624 	: "memory" );
    625 
    626     return ret;
    627 }
    628 
    629 static __inline int
    630 HYPERVISOR_dom_mem_op(unsigned int op, unsigned long *extent_list,
    631     unsigned long nr_extents, unsigned int extent_order)
    632 {
    633     int ret;
    634     unsigned long ign1, ign2, ign3, ign4, ign5;
    635 
    636     __asm volatile (
    637         TRAP_INSTR
    638         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
    639 	  "=D" (ign5)
    640 	: "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
    641 	  "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
    642         : "memory" );
    643 
    644     return ret;
    645 }
    646 
    647 static __inline int
    648 HYPERVISOR_update_va_mapping(unsigned long page_nr, unsigned long new_val,
    649     unsigned long flags)
    650 {
    651     int ret;
    652     unsigned long ign1, ign2, ign3;
    653 
    654     __asm volatile (
    655         TRAP_INSTR
    656         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    657 	: "0" (__HYPERVISOR_update_va_mapping),
    658           "1" (page_nr), "2" (new_val), "3" (flags)
    659 	: "memory" );
    660 
    661 #ifdef notdef
    662     if (__predict_false(ret < 0))
    663         panic("Failed update VA mapping: %08lx, %08lx, %08lx",
    664               page_nr, new_val, flags);
    665 #endif
    666 
    667     return ret;
    668 }
    669 
    670 static __inline int
    671 HYPERVISOR_xen_version(int cmd)
    672 {
    673     int ret;
    674     unsigned long ign1;
    675 
    676     __asm volatile (
    677         TRAP_INSTR
    678         : "=a" (ret), "=b" (ign1)
    679 	: "0" (__HYPERVISOR_xen_version), "1" (cmd)
    680 	: "memory" );
    681 
    682     return ret;
    683 }
    684 
    685 static __inline int
    686 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
    687 {
    688     int ret;
    689     unsigned long ign1, ign2, ign3;
    690 
    691     __asm volatile (
    692         TRAP_INSTR
    693         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
    694 	: "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (count), "3" (uop)
    695 	: "memory" );
    696 
    697     return ret;
    698 }
    699 
    700 static __inline int
    701 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
    702     unsigned long new_val, unsigned long flags, domid_t domid)
    703 {
    704     int ret;
    705     unsigned long ign1, ign2, ign3, ign4;
    706 
    707     __asm volatile (
    708         TRAP_INSTR
    709         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
    710 	: "0" (__HYPERVISOR_update_va_mapping_otherdomain),
    711           "1" (page_nr), "2" (new_val), "3" (flags), "4" (domid) :
    712         "memory" );
    713 
    714     return ret;
    715 }
    716 
    717 static __inline long
    718 HYPERVISOR_set_timer_op(uint64_t timeout)
    719 {
    720     long ret;
    721     unsigned long timeout_hi = (unsigned long)(timeout>>32);
    722     unsigned long timeout_lo = (unsigned long)timeout;
    723     unsigned long ign1, ign2;
    724 
    725     __asm volatile (
    726         TRAP_INSTR
    727         : "=a" (ret), "=b" (ign1), "=c" (ign2)
    728 	: "0" (__HYPERVISOR_set_timer_op), "b" (timeout_hi), "c" (timeout_lo)
    729 	: "memory");
    730 
    731     return ret;
    732 }
    733 #endif /* XEN3 */
    734 
    735 static __inline int
    736 HYPERVISOR_multicall(void *call_list, int nr_calls)
    737 {
    738     int ret;
    739     unsigned long ign1, ign2;
    740 
    741     _hypercall(__HYPERVISOR_multicall,
    742 	 _harg("1" (call_list), "2" (nr_calls)),
    743 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    744 
    745     return ret;
    746 }
    747 
    748 
    749 static __inline int
    750 HYPERVISOR_event_channel_op(void *op)
    751 {
    752     int ret;
    753     unsigned long ign1;
    754 
    755     _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op)),
    756 	_harg("=a" (ret), "=b" (ign1)));
    757 
    758     return ret;
    759 }
    760 
    761 static __inline int
    762 HYPERVISOR_console_io(int cmd, int count, char *str)
    763 {
    764     int ret;
    765     unsigned long ign1, ign2, ign3;
    766 
    767     _hypercall(__HYPERVISOR_console_io,
    768 	_harg("1" (cmd), "2" (count), "3" (str)),
    769 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    770 
    771     return ret;
    772 }
    773 
    774 static __inline int
    775 HYPERVISOR_physdev_op(void *physdev_op)
    776 {
    777     int ret;
    778     unsigned long ign1;
    779 
    780     _hypercall(__HYPERVISOR_physdev_op, _harg("1" (physdev_op)),
    781 	_harg("=a" (ret), "=b" (ign1)));
    782 
    783     return ret;
    784 }
    785 
    786 static __inline int
    787 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
    788 {
    789     int ret;
    790     unsigned long ign1, ign2;
    791 
    792     _hypercall(__HYPERVISOR_vm_assist, _harg("1" (cmd), "2" (type)),
    793 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    794 
    795     return ret;
    796 }
    797 
    798 /*
    799  * Force a proper event-channel callback from Xen after clearing the
    800  * callback mask. We do this in a very simple manner, by making a call
    801  * down into Xen. The pending flag will be checked by Xen on return.
    802  */
    803 static __inline void hypervisor_force_callback(void)
    804 {
    805 #ifdef XEN3
    806 	(void)HYPERVISOR_xen_version(0, (void*)0);
    807 #else
    808 	(void)HYPERVISOR_xen_version(0);
    809 #endif
    810 } __attribute__((no_instrument_function)) /* used by mcount */
    811 
    812 static __inline void
    813 hypervisor_notify_via_evtchn(unsigned int port)
    814 {
    815 	evtchn_op_t op;
    816 
    817 	op.cmd = EVTCHNOP_send;
    818 #ifdef XEN3
    819 	op.u.send.port = port;
    820 #else
    821 	op.u.send.local_port = port;
    822 #endif
    823 	(void)HYPERVISOR_event_channel_op(&op);
    824 }
    825 
    826 #endif /* _XEN_HYPERVISOR_H_ */
    827