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