xref: /netbsd-src/sys/arch/xen/include/hypervisor.h (revision ce2c90c7c172d95d2402a5b3d96d8f8e6d138a21)
1 /*	$NetBSD: hypervisor.h,v 1.22 2006/09/24 18:14:44 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 #if defined(XEN3) && !defined(XEN_NO_HYPERCALLPAGE)
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