xref: /netbsd-src/sys/arch/i386/include/xen/hypercalls.h (revision c24c993fe4cf289234b8ce9b47d92eb1278cfbda)
1 /*	$NetBSD: hypercalls.h,v 1.2 2020/04/25 15:26:17 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  *
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 /* hypercall via the hypercall call page */
63 #define __str(x) #x
64 #define _str(x) __str(x)
65 #define _hypercall(name, input_const, output_const) \
66 	__asm volatile ( \
67 	    "call hypercall_page + ("_str(name)" * 32)" \
68 	    : output_const \
69 	    : input_const \
70 	    : "memory" )
71 
72 #define _harg(...) __VA_ARGS__
73 
74 
75 static __inline int
HYPERVISOR_set_trap_table(trap_info_t * table)76 HYPERVISOR_set_trap_table(trap_info_t *table)
77 {
78     int ret;
79     unsigned long ign1;
80 
81 	_hypercall(__HYPERVISOR_set_trap_table, _harg("1" (table)),
82 	    _harg("=a" (ret), "=b" (ign1)));
83 
84     return ret;
85 }
86 
87 static __inline int
HYPERVISOR_set_gdt(unsigned long * frame_list,int entries)88 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
89 {
90     int ret;
91     unsigned long ign1, ign2;
92 
93     _hypercall(__HYPERVISOR_set_gdt, _harg("1" (frame_list), "2" (entries)),
94 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
95 
96     return ret;
97 }
98 
99 static __inline int
HYPERVISOR_stack_switch(unsigned long ss,unsigned long esp)100 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
101 {
102     int ret;
103     unsigned long ign1, ign2;
104 
105     _hypercall(__HYPERVISOR_stack_switch, _harg("1" (ss), "2" (esp)),
106 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
107 
108     return ret;
109 }
110 
111 static __inline int
HYPERVISOR_set_callbacks(unsigned long event_selector,unsigned long event_address,unsigned long failsafe_selector,unsigned long failsafe_address)112 HYPERVISOR_set_callbacks(
113     unsigned long event_selector, unsigned long event_address,
114     unsigned long failsafe_selector, unsigned long failsafe_address)
115 {
116     int ret;
117     unsigned long ign1, ign2, ign3, ign4;
118 
119     _hypercall(__HYPERVISOR_set_callbacks,
120 	_harg("1" (event_selector),"2" (event_address),
121 	    "3" (failsafe_selector), "4" (failsafe_address)),
122 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
123 
124     return ret;
125 }
126 
127 #if __XEN_INTERFACE_VERSION__ < 0x00030204
128 static __inline int
HYPERVISOR_dom0_op(dom0_op_t * dom0_op)129 HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
130 {
131     int ret;
132     unsigned long ign1;
133 
134     dom0_op->interface_version = DOM0_INTERFACE_VERSION;
135     _hypercall(__HYPERVISOR_dom0_op, _harg("1" (dom0_op)),
136 	_harg("=a" (ret), "=b" (ign1)));
137 
138     return ret;
139 }
140 #endif	/* __XEN_INTERFACE_VERSION__ */
141 
142 static __inline int
HYPERVISOR_set_debugreg(int reg,unsigned long value)143 HYPERVISOR_set_debugreg(int reg, unsigned long value)
144 {
145     int ret;
146     unsigned long ign1, ign2;
147 
148     _hypercall(__HYPERVISOR_set_debugreg, _harg("1" (reg), "2" (value)),
149 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
150 
151     return ret;
152 }
153 
154 static __inline unsigned long
HYPERVISOR_get_debugreg(int reg)155 HYPERVISOR_get_debugreg(int reg)
156 {
157     unsigned long ret;
158     unsigned long ign1;
159 
160     _hypercall(__HYPERVISOR_get_debugreg, _harg("1" (reg)),
161 	_harg("=a" (ret), "=b" (ign1)));
162 
163     return ret;
164 }
165 
166 #include <xen/include/public/arch-x86/xen-mca.h>
167 
168 static __inline int
HYPERVISOR_machine_check(struct xen_mc * mc)169 HYPERVISOR_machine_check(struct xen_mc *mc)
170 {
171      int ret;
172      unsigned long ign1;
173 
174      mc->interface_version = XEN_MCA_INTERFACE_VERSION;
175      _hypercall(__HYPERVISOR_mca, _harg("1" (mc)),
176 	  _harg("=a" (ret), "=b" (ign1)));
177 
178      return ret;
179 }
180 
181 static __inline int
HYPERVISOR_hvm_op(int cmd,void * arg)182 HYPERVISOR_hvm_op(int cmd, void *arg)
183 {
184     int ret;
185     unsigned long ign1, ign2;
186 
187     _hypercall(__HYPERVISOR_hvm_op, _harg("1" (cmd), "2" (arg)),
188 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
189 
190     return ret;
191 }
192 
193 static __inline int
HYPERVISOR_mmu_update(mmu_update_t * req,int count,int * success_count,domid_t domid)194 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count,
195     domid_t domid)
196 {
197     int ret;
198     unsigned long ign1, ign2, ign3, ign4;
199 
200     _hypercall(__HYPERVISOR_mmu_update,
201 	_harg("1" (req), "2" (count), "3" (success_count), "4" (domid)),
202 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
203 
204     return ret;
205 }
206 
207 static __inline int
HYPERVISOR_mmuext_op(struct mmuext_op * op,int count,int * success_count,domid_t domid)208 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, int *success_count,
209     domid_t domid)
210 {
211     int ret;
212     unsigned long ign1, ign2, ign3, ign4;
213 
214     _hypercall(__HYPERVISOR_mmuext_op,
215 	_harg("1" (op), "2" (count), "3" (success_count), "4" (domid)),
216 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
217 
218     return ret;
219 }
220 
221 static __inline int
HYPERVISOR_fpu_taskswitch(int set)222 HYPERVISOR_fpu_taskswitch(int set)
223 {
224     long ret;
225     long ign1;
226 
227     _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (set)),
228 	_harg("=a" (ret), "=b" (ign1)));
229 
230     return ret;
231 }
232 
233 static __inline int
HYPERVISOR_update_descriptor(uint64_t ma,uint32_t word1,uint32_t word2)234 HYPERVISOR_update_descriptor(uint64_t ma, uint32_t word1, uint32_t word2)
235 {
236     int ret;
237     unsigned long ign1, ign2, ign3, ign4;
238     int ma1 = ma & 0xffffffff;
239     int ma2 = (ma >> 32) & 0xffffffff;
240 
241     _hypercall(__HYPERVISOR_update_descriptor,
242 	_harg("1" (ma1), "2" (ma2), "3" (word1), "4" (word2)),
243 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
244 
245     return ret;
246 }
247 
248 static __inline int
HYPERVISOR_memory_op(unsigned int cmd,void * arg)249 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
250 {
251     int ret;
252     unsigned long ign1, ign2;
253 
254     _hypercall(__HYPERVISOR_memory_op, _harg("1" (cmd), "2" (arg)),
255 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
256 
257     return ret;
258 }
259 
260 #ifdef XENPV
261 static __inline int
HYPERVISOR_update_va_mapping(unsigned long page_nr,pt_entry_t new_val,unsigned long flags)262 HYPERVISOR_update_va_mapping(unsigned long page_nr, pt_entry_t new_val,
263     unsigned long flags)
264 {
265     int ret;
266     unsigned long ign1, ign2, ign3, ign4;
267     unsigned long pte_low, pte_hi;
268 
269     pte_low = new_val & 0xffffffff;
270     pte_hi = new_val >> 32;
271 
272     _hypercall(__HYPERVISOR_update_va_mapping,
273 	_harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags)),
274 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
275 
276 #ifdef notdef
277     if (__predict_false(ret < 0))
278         panic("Failed update VA mapping: %08lx, %08lx, %08lx",
279               page_nr, new_val, flags);
280 #endif
281 
282     return ret;
283 }
284 
285 static __inline int
HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,pt_entry_t new_val,unsigned long flags,domid_t domid)286 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
287     pt_entry_t new_val, unsigned long flags, domid_t domid)
288 {
289     int ret;
290     unsigned long ign1, ign2, ign3, ign4, ign5;
291     unsigned long pte_low, pte_hi;
292 
293     pte_low = new_val & 0xffffffff;
294     pte_hi = new_val >> 32;
295 
296     _hypercall(__HYPERVISOR_update_va_mapping_otherdomain,
297 	_harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags), "5" (domid)),
298 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
299 	    "=D" (ign5)));
300 
301     return ret;
302 }
303 #endif /* XENPV */
304 
305 static __inline int
HYPERVISOR_xen_version(int cmd,void * arg)306 HYPERVISOR_xen_version(int cmd, void *arg)
307 {
308     int ret;
309     unsigned long ign1, ign2;
310 
311     _hypercall(__HYPERVISOR_xen_version, _harg("1" (cmd), "2" (arg)),
312 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
313 
314     return ret;
315 }
316 
317 static __inline int
HYPERVISOR_grant_table_op(unsigned int cmd,void * uop,unsigned int count)318 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
319 {
320     int ret;
321     unsigned long ign1, ign2, ign3;
322 
323     _hypercall(__HYPERVISOR_grant_table_op,
324 	_harg("1" (cmd), "2" (uop), "3" (count)),
325 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
326 
327     return ret;
328 }
329 
330 
331 static __inline int
HYPERVISOR_vcpu_op(int cmd,int vcpuid,void * extra_args)332 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
333 {
334     long ret;
335     unsigned long ign1, ign2, ign3;
336 
337     _hypercall(__HYPERVISOR_vcpu_op,
338 	_harg("1" (cmd), "2" (vcpuid), "3" (extra_args)),
339 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
340 
341     return ret;
342 }
343 
344 static __inline long
HYPERVISOR_yield(void)345 HYPERVISOR_yield(void)
346 {
347     long ret;
348     unsigned long ign1, ign2;
349 
350     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_yield), "2" (0)),
351 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
352 
353     return ret;
354 }
355 
356 static __inline long
HYPERVISOR_block(void)357 HYPERVISOR_block(void)
358 {
359     long ret;
360     unsigned long ign1, ign2;
361 
362     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_block), "2" (0)),
363 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
364 
365     return ret;
366 }
367 
368 static __inline long
HYPERVISOR_shutdown(void)369 HYPERVISOR_shutdown(void)
370 {
371     long ret;
372     unsigned long ign1, ign2;
373 
374 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
375 
376     struct sched_shutdown shutdown_reason = {
377 	    .reason = SHUTDOWN_poweroff
378     };
379 
380     _hypercall(__HYPERVISOR_sched_op,
381 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason)),
382 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
383 #else
384      _hypercall(__HYPERVISOR_sched_op,
385 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_poweroff)),
386  	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
387 
388 #endif
389 
390     return ret;
391 }
392 
393 static __inline long
HYPERVISOR_crash(void)394 HYPERVISOR_crash(void)
395 {
396     long ret;
397     unsigned long ign1, ign2;
398 
399 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
400 
401     struct sched_shutdown shutdown_reason = {
402 	    .reason = SHUTDOWN_crash
403     };
404 
405     _hypercall(__HYPERVISOR_sched_op,
406 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason)),
407 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
408 #else
409     _hypercall(__HYPERVISOR_sched_op,
410 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_crash)),
411 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
412 #endif
413 
414     return ret;
415 }
416 
417 static __inline long
HYPERVISOR_reboot(void)418 HYPERVISOR_reboot(void)
419 {
420     long ret;
421     unsigned long ign1, ign2;
422 
423 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
424 
425     struct sched_shutdown shutdown_reason = {
426 	    .reason = SHUTDOWN_reboot
427     };
428 
429     _hypercall(__HYPERVISOR_sched_op,
430 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason)),
431 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
432 #else
433     _hypercall(__HYPERVISOR_sched_op,
434 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_reboot)),
435 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
436 #endif
437 
438     return ret;
439 }
440 
441 static __inline long
HYPERVISOR_suspend(unsigned long srec)442 HYPERVISOR_suspend(unsigned long srec)
443 {
444     long ret;
445     unsigned long ign1, ign2, ign3;
446 
447 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
448 
449     struct sched_shutdown shutdown_reason = {
450 	    .reason = SHUTDOWN_suspend
451     };
452 
453     _hypercall(__HYPERVISOR_sched_op,
454 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason), "3" (srec)),
455 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
456 #else
457     _hypercall(__HYPERVISOR_sched_op,
458 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_suspend), "3" (srec)),
459 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
460 #endif
461 
462     return ret;
463 }
464 
465 static __inline long
HYPERVISOR_set_timer_op(uint64_t timeout)466 HYPERVISOR_set_timer_op(uint64_t timeout)
467 {
468     long ret;
469     unsigned long timeout_hi = (unsigned long)(timeout>>32);
470     unsigned long timeout_lo = (unsigned long)timeout;
471     unsigned long ign1, ign2;
472 
473     _hypercall(__HYPERVISOR_set_timer_op,
474 	 _harg("1" (timeout_lo), "2" (timeout_hi)),
475 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
476 
477     return ret;
478 }
479 
480 static __inline int
HYPERVISOR_platform_op(struct xen_platform_op * platform_op)481 HYPERVISOR_platform_op(struct xen_platform_op *platform_op)
482 {
483     int ret;
484     unsigned long ign1;
485 
486     platform_op->interface_version = XENPF_INTERFACE_VERSION;
487     _hypercall(__HYPERVISOR_platform_op, _harg("1" (platform_op)),
488 	_harg("=a" (ret), "=b" (ign1)));
489 
490     return ret;
491 }
492 
493 static __inline int
HYPERVISOR_multicall(void * call_list,int nr_calls)494 HYPERVISOR_multicall(void *call_list, int nr_calls)
495 {
496     int ret;
497     unsigned long ign1, ign2;
498 
499     _hypercall(__HYPERVISOR_multicall,
500 	 _harg("1" (call_list), "2" (nr_calls)),
501 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
502 
503     return ret;
504 }
505 
506 
507 static __inline int
HYPERVISOR_event_channel_op(evtchn_op_t * op)508 HYPERVISOR_event_channel_op(evtchn_op_t *op)
509 {
510     int ret;
511     unsigned long ign1;
512 
513 #if __XEN_INTERFACE_VERSION__ < 0x00030202
514     _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op)),
515 	_harg("=a" (ret), "=b" (ign1)));
516 #else
517     unsigned long ign2;
518 
519     _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op->cmd), "2" (&op->u)),
520 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
521 #endif
522     return ret;
523 }
524 
525 static __inline int
HYPERVISOR_console_io(int cmd,int count,char * str)526 HYPERVISOR_console_io(int cmd, int count, char *str)
527 {
528     int ret;
529     unsigned long ign1, ign2, ign3;
530 
531     _hypercall(__HYPERVISOR_console_io,
532 	_harg("1" (cmd), "2" (count), "3" (str)),
533 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
534 
535     return ret;
536 }
537 
538 static __inline int
HYPERVISOR_physdev_op(int cmd,void * physdev_op)539 HYPERVISOR_physdev_op(int cmd, void *physdev_op)
540 {
541     int ret;
542     unsigned long ign1, ign2;
543 
544     _hypercall(__HYPERVISOR_physdev_op, _harg("1" (cmd), "2" (physdev_op)),
545 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
546 
547     return ret;
548 }
549 
550 static __inline int
HYPERVISOR_vm_assist(unsigned int cmd,unsigned int type)551 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
552 {
553     int ret;
554     unsigned long ign1, ign2;
555 
556     _hypercall(__HYPERVISOR_vm_assist, _harg("1" (cmd), "2" (type)),
557 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
558 
559     return ret;
560 }
561 
562 static __inline int
HYPERVISOR_sysctl(void * sysctl)563 HYPERVISOR_sysctl(void *sysctl)
564 {
565     int ret;
566     unsigned long ign1;
567 
568     _hypercall(__HYPERVISOR_sysctl, _harg("1" (sysctl)),
569 	_harg("=a" (ret), "=b" (ign1)));
570 
571     return ret;
572 }
573 #endif /* _XENI386_HYPERVISOR_H_ */
574