1/*	$NetBSD: hypercalls.h,v 1.13 2011/12/07 15:47:42 cegger 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28/*
29 *
30 * Communication to/from hypervisor.
31 *
32 * Copyright (c) 2002-2004, K A Fraser
33 *
34 * Permission is hereby granted, free of charge, to any person obtaining a copy
35 * of this source file (the "Software"), to deal in the Software without
36 * restriction, including without limitation the rights to use, copy, modify,
37 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
38 * and to permit persons to whom the Software is furnished to do so, subject to
39 * the following conditions:
40 *
41 * The above copyright notice and this permission notice shall be included in
42 * all copies or substantial portions of the Software.
43 *
44 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
49 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
50 * IN THE SOFTWARE.
51 */
52
53
54#ifndef _XENI386_HYPERVISOR_H_
55#define _XENI386_HYPERVISOR_H_
56/*
57 * Assembler stubs for hyper-calls.
58 */
59
60#include <machine/pte.h> /* pt_entry_t */
61
62#if !defined(XEN_COMPAT_030001)
63/* hypercall via the hypercall call page */
64#define __str(x) #x
65#define _str(x) __str(x)
66#define _hypercall(name, input_const, output_const) \
67	__asm volatile ( \
68	    "call hypercall_page + ("_str(name)" * 32)" \
69	    : output_const \
70	    : input_const \
71	    : "memory" )
72#else
73/* traditionnal hypercall via int 0x82 */
74#define _hypercall(name, input_const, output_const) \
75	__asm volatile ( \
76	    TRAP_INSTR \
77	    : output_const \
78	    : "0" (name), input_const \
79	    : "memory" )
80#endif
81
82#define _harg(...) __VA_ARGS__
83
84
85static __inline int
86HYPERVISOR_set_trap_table(trap_info_t *table)
87{
88    int ret;
89    unsigned long ign1;
90
91	_hypercall(__HYPERVISOR_set_trap_table, _harg("1" (table)),
92	    _harg("=a" (ret), "=b" (ign1)));
93
94    return ret;
95}
96
97static __inline int
98HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
99{
100    int ret;
101    unsigned long ign1, ign2;
102
103    _hypercall(__HYPERVISOR_set_gdt, _harg("1" (frame_list), "2" (entries)),
104	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
105
106    return ret;
107}
108
109static __inline int
110HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
111{
112    int ret;
113    unsigned long ign1, ign2;
114
115    _hypercall(__HYPERVISOR_stack_switch, _harg("1" (ss), "2" (esp)),
116	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
117
118    return ret;
119}
120
121static __inline int
122HYPERVISOR_set_callbacks(
123    unsigned long event_selector, unsigned long event_address,
124    unsigned long failsafe_selector, unsigned long failsafe_address)
125{
126    int ret;
127    unsigned long ign1, ign2, ign3, ign4;
128
129    _hypercall(__HYPERVISOR_set_callbacks,
130	_harg("1" (event_selector),"2" (event_address),
131	    "3" (failsafe_selector), "4" (failsafe_address)),
132	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
133
134    return ret;
135}
136
137#if __XEN_INTERFACE_VERSION__ < 0x00030204
138static __inline int
139HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
140{
141    int ret;
142    unsigned long ign1;
143
144    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
145    _hypercall(__HYPERVISOR_dom0_op, _harg("1" (dom0_op)),
146	_harg("=a" (ret), "=b" (ign1)));
147
148    return ret;
149}
150#endif	/* __XEN_INTERFACE_VERSION__ */
151
152static __inline int
153HYPERVISOR_set_debugreg(int reg, unsigned long value)
154{
155    int ret;
156    unsigned long ign1, ign2;
157
158    _hypercall(__HYPERVISOR_set_debugreg, _harg("1" (reg), "2" (value)),
159	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
160
161    return ret;
162}
163
164static __inline unsigned long
165HYPERVISOR_get_debugreg(int reg)
166{
167    unsigned long ret;
168    unsigned long ign1;
169
170    _hypercall(__HYPERVISOR_get_debugreg, _harg("1" (reg)),
171	_harg("=a" (ret), "=b" (ign1)));
172
173    return ret;
174}
175
176#include <xen/xen-public/arch-x86/xen-mca.h>
177
178static __inline int
179HYPERVISOR_machine_check(struct xen_mc *mc)
180{
181     int ret;
182     unsigned long ign1;
183
184     mc->interface_version = XEN_MCA_INTERFACE_VERSION;
185     _hypercall(__HYPERVISOR_mca, _harg("1" (mc)),
186	  _harg("=a" (ret), "=b" (ign1)));
187
188     return ret;
189}
190
191static __inline int
192HYPERVISOR_hvm_op(int cmd, void *arg)
193{
194    int ret;
195    unsigned long ign1, ign2;
196
197    _hypercall(__HYPERVISOR_hvm_op, _harg("1" (cmd), "2" (arg)),
198	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
199
200    return ret;
201}
202
203static __inline int
204HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count,
205    domid_t domid)
206{
207    int ret;
208    unsigned long ign1, ign2, ign3, ign4;
209
210    _hypercall(__HYPERVISOR_mmu_update,
211	_harg("1" (req), "2" (count), "3" (success_count), "4" (domid)),
212	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
213
214    return ret;
215}
216
217static __inline int
218HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, int *success_count,
219    domid_t domid)
220{
221    int ret;
222    unsigned long ign1, ign2, ign3, ign4;
223
224    _hypercall(__HYPERVISOR_mmuext_op,
225	_harg("1" (op), "2" (count), "3" (success_count), "4" (domid)),
226	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
227
228    return ret;
229}
230
231static __inline int
232HYPERVISOR_fpu_taskswitch(int set)
233{
234    long ret;
235    long ign1;
236
237    _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (set)),
238	_harg("=a" (ret), "=b" (ign1)));
239
240    return ret;
241}
242
243static __inline int
244HYPERVISOR_update_descriptor(uint64_t ma, uint32_t word1, uint32_t word2)
245{
246    int ret;
247    unsigned long ign1, ign2, ign3, ign4;
248    int ma1 = ma & 0xffffffff;
249    int ma2 = (ma >> 32) & 0xffffffff;
250
251    _hypercall(__HYPERVISOR_update_descriptor,
252	_harg("1" (ma1), "2" (ma2), "3" (word1), "4" (word2)),
253	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
254
255    return ret;
256}
257
258static __inline int
259HYPERVISOR_memory_op(unsigned int cmd, void *arg)
260{
261    int ret;
262    unsigned long ign1, ign2;
263
264    _hypercall(__HYPERVISOR_memory_op, _harg("1" (cmd), "2" (arg)),
265	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
266
267    return ret;
268}
269
270static __inline int
271HYPERVISOR_update_va_mapping(unsigned long page_nr, pt_entry_t new_val,
272    unsigned long flags)
273{
274    int ret;
275    unsigned long ign1, ign2, ign3, ign4;
276    unsigned long pte_low, pte_hi;
277
278    pte_low = new_val & 0xffffffff;
279#ifdef PAE
280    pte_hi = new_val >> 32;
281#else
282    pte_hi = 0;
283#endif
284
285    _hypercall(__HYPERVISOR_update_va_mapping,
286	_harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags)),
287	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
288
289#ifdef notdef
290    if (__predict_false(ret < 0))
291        panic("Failed update VA mapping: %08lx, %08lx, %08lx",
292              page_nr, new_val, flags);
293#endif
294
295    return ret;
296}
297
298static __inline int
299HYPERVISOR_xen_version(int cmd, void *arg)
300{
301    int ret;
302    unsigned long ign1, ign2;
303
304    _hypercall(__HYPERVISOR_xen_version, _harg("1" (cmd), "2" (arg)),
305	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
306
307    return ret;
308}
309
310static __inline int
311HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
312{
313    int ret;
314    unsigned long ign1, ign2, ign3;
315
316    _hypercall(__HYPERVISOR_grant_table_op,
317	_harg("1" (cmd), "2" (uop), "3" (count)),
318	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
319
320    return ret;
321}
322
323static __inline int
324HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
325    pt_entry_t new_val, unsigned long flags, domid_t domid)
326{
327    int ret;
328    unsigned long ign1, ign2, ign3, ign4, ign5;
329    unsigned long pte_low, pte_hi;
330
331    pte_low = new_val & 0xffffffff;
332#ifdef PAE
333    pte_hi = new_val >> 32;
334#else
335    pte_hi = 0;
336#endif
337
338    _hypercall(__HYPERVISOR_update_va_mapping_otherdomain,
339	_harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags), "5" (domid)),
340	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
341	    "=D" (ign5)));
342
343    return ret;
344}
345
346static __inline int
347HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
348{
349    long ret;
350    unsigned long ign1, ign2, ign3;
351
352    _hypercall(__HYPERVISOR_vcpu_op,
353	_harg("1" (cmd), "2" (vcpuid), "3" (extra_args)),
354	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
355
356    return ret;
357}
358
359static __inline long
360HYPERVISOR_yield(void)
361{
362    long ret;
363    unsigned long ign1, ign2;
364
365    _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_yield), "2" (0)),
366	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
367
368    return ret;
369}
370
371static __inline long
372HYPERVISOR_block(void)
373{
374    long ret;
375    unsigned long ign1, ign2;
376
377    _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_block), "2" (0)),
378	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
379
380    return ret;
381}
382
383static __inline long
384HYPERVISOR_shutdown(void)
385{
386    long ret;
387    unsigned long ign1, ign2;
388
389    _hypercall(__HYPERVISOR_sched_op,
390	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_poweroff)),
391	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
392
393    return ret;
394}
395
396static __inline long
397HYPERVISOR_crash(void)
398{
399    long ret;
400    unsigned long ign1, ign2;
401
402    _hypercall(__HYPERVISOR_sched_op,
403	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_crash)),
404	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
405
406    return ret;
407}
408
409static __inline long
410HYPERVISOR_reboot(void)
411{
412    long ret;
413    unsigned long ign1, ign2;
414
415    _hypercall(__HYPERVISOR_sched_op,
416	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_reboot)),
417	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
418
419    return ret;
420}
421
422static __inline long
423HYPERVISOR_suspend(unsigned long srec)
424{
425    long ret;
426    unsigned long ign1, ign2, ign3;
427
428    _hypercall(__HYPERVISOR_sched_op,
429	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_suspend), "3" (srec)),
430	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
431
432    return ret;
433}
434
435static __inline long
436HYPERVISOR_set_timer_op(uint64_t timeout)
437{
438    long ret;
439    unsigned long timeout_hi = (unsigned long)(timeout>>32);
440    unsigned long timeout_lo = (unsigned long)timeout;
441    unsigned long ign1, ign2;
442
443    _hypercall(__HYPERVISOR_set_timer_op,
444	 _harg("1" (timeout_lo), "2" (timeout_hi)),
445	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
446
447    return ret;
448}
449
450static __inline int
451HYPERVISOR_platform_op(struct xen_platform_op *platform_op)
452{
453    int ret;
454    unsigned long ign1;
455
456    platform_op->interface_version = XENPF_INTERFACE_VERSION;
457    _hypercall(__HYPERVISOR_platform_op, _harg("1" (platform_op)),
458	_harg("=a" (ret), "=b" (ign1)));
459
460    return ret;
461}
462
463static __inline int
464HYPERVISOR_multicall(void *call_list, int nr_calls)
465{
466    int ret;
467    unsigned long ign1, ign2;
468
469    _hypercall(__HYPERVISOR_multicall,
470	 _harg("1" (call_list), "2" (nr_calls)),
471	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
472
473    return ret;
474}
475
476
477static __inline int
478HYPERVISOR_event_channel_op(void *op)
479{
480    int ret;
481    unsigned long ign1;
482
483    _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op)),
484	_harg("=a" (ret), "=b" (ign1)));
485
486    return ret;
487}
488
489static __inline int
490HYPERVISOR_console_io(int cmd, int count, char *str)
491{
492    int ret;
493    unsigned long ign1, ign2, ign3;
494
495    _hypercall(__HYPERVISOR_console_io,
496	_harg("1" (cmd), "2" (count), "3" (str)),
497	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
498
499    return ret;
500}
501
502static __inline int
503HYPERVISOR_physdev_op(void *physdev_op)
504{
505    int ret;
506    unsigned long ign1;
507
508    _hypercall(__HYPERVISOR_physdev_op, _harg("1" (physdev_op)),
509	_harg("=a" (ret), "=b" (ign1)));
510
511    return ret;
512}
513
514static __inline int
515HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
516{
517    int ret;
518    unsigned long ign1, ign2;
519
520    _hypercall(__HYPERVISOR_vm_assist, _harg("1" (cmd), "2" (type)),
521	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
522
523    return ret;
524}
525
526static __inline int
527HYPERVISOR_sysctl(void *sysctl)
528{
529    int ret;
530    unsigned long ign1;
531
532    _hypercall(__HYPERVISOR_sysctl, _harg("1" (sysctl)),
533	_harg("=a" (ret), "=b" (ign1)));
534
535    return ret;
536}
537#endif /* _XENI386_HYPERVISOR_H_ */
538