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