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