Home | History | Annotate | Line # | Download | only in xen
      1 /* $NetBSD: hypercalls.h,v 1.2 2020/04/25 15:26:16 bouyer Exp $ */
      2 /******************************************************************************
      3  * hypercall.h
      4  *
      5  * Linux-specific hypervisor handling.
      6  *
      7  * Copyright (c) 2002-2004, K A Fraser
      8  *
      9  * 64-bit updates:
     10  *   Benjamin Liu <benjamin.liu (at) intel.com>
     11  *   Jun Nakajima <jun.nakajima (at) intel.com>
     12  *
     13  * This program is free software; you can redistribute it and/or
     14  * modify it under the terms of the GNU General Public License version 2
     15  * as published by the Free Software Foundation; or, when distributed
     16  * separately from the Linux kernel or incorporated into other
     17  * software packages, subject to the following license:
     18  *
     19  * Permission is hereby granted, free of charge, to any person obtaining a copy
     20  * of this source file (the "Software"), to deal in the Software without
     21  * restriction, including without limitation the rights to use, copy, modify,
     22  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
     23  * and to permit persons to whom the Software is furnished to do so, subject to
     24  * the following conditions:
     25  *
     26  * The above copyright notice and this permission notice shall be included in
     27  * all copies or substantial portions of the Software.
     28  *
     29  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     30  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     31  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     32  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     33  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     34  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     35  * IN THE SOFTWARE.
     36  */
     37 
     38 #ifndef __HYPERCALL_H__
     39 #define __HYPERCALL_H__
     40 
     41 #define __STR(x) #x
     42 #define STR(x) __STR(x)
     43 
     44 #define HYPERCALL_STR(name)					\
     45 	"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"
     46 
     47 #define _hypercall0(type, name)			\
     48 ({						\
     49 	long __res;				\
     50 	asm volatile (				\
     51 		HYPERCALL_STR(name)		\
     52 		: "=a" (__res)			\
     53 		:				\
     54 		: "memory" );			\
     55 	(type)__res;				\
     56 })
     57 
     58 #define _hypercall1(type, name, a1)				\
     59 ({								\
     60 	long __res, __ign1;					\
     61 	asm volatile (						\
     62 		HYPERCALL_STR(name)				\
     63 		: "=a" (__res), "=D" (__ign1)			\
     64 		: "1" ((long)(a1))				\
     65 		: "memory" );					\
     66 	(type)__res;						\
     67 })
     68 
     69 #define _hypercall2(type, name, a1, a2)				\
     70 ({								\
     71 	long __res, __ign1, __ign2;				\
     72 	asm volatile (						\
     73 		HYPERCALL_STR(name)				\
     74 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
     75 		: "1" ((long)(a1)), "2" ((long)(a2))		\
     76 		: "memory" );					\
     77 	(type)__res;						\
     78 })
     79 
     80 #define _hypercall3(type, name, a1, a2, a3)			\
     81 ({								\
     82 	long __res, __ign1, __ign2, __ign3;			\
     83 	asm volatile (						\
     84 		HYPERCALL_STR(name)				\
     85 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2), 	\
     86 		"=d" (__ign3)					\
     87 		: "1" ((long)(a1)), "2" ((long)(a2)),		\
     88 		"3" ((long)(a3))				\
     89 		: "memory" );					\
     90 	(type)__res;						\
     91 })
     92 
     93 #define _hypercall4(type, name, a1, a2, a3, a4)			\
     94 ({								\
     95 	long __res, __ign1, __ign2, __ign3;			\
     96 	asm volatile (						\
     97 		"movq %7,%%r10; "				\
     98 		HYPERCALL_STR(name)				\
     99 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
    100 		"=d" (__ign3)					\
    101 		: "1" ((long)(a1)), "2" ((long)(a2)),		\
    102 		"3" ((long)(a3)), "g" ((long)(a4))		\
    103 		: "memory", "r10" );				\
    104 	(type)__res;						\
    105 })
    106 
    107 #define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
    108 ({								\
    109 	long __res, __ign1, __ign2, __ign3;			\
    110 	asm volatile (						\
    111 		"movq %7,%%r10; movq %8,%%r8; "			\
    112 		HYPERCALL_STR(name)				\
    113 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
    114 		"=d" (__ign3)					\
    115 		: "1" ((long)(a1)), "2" ((long)(a2)),		\
    116 		"3" ((long)(a3)), "g" ((long)(a4)),		\
    117 		"g" ((long)(a5))				\
    118 		: "memory", "r10", "r8" );			\
    119 	(type)__res;						\
    120 })
    121 
    122 static inline int
    123 HYPERVISOR_set_trap_table(
    124 	trap_info_t *table)
    125 {
    126 	return _hypercall1(int, set_trap_table, table);
    127 }
    128 
    129 static inline int
    130 HYPERVISOR_mmu_update(
    131 	mmu_update_t *req, int count, int *success_count, domid_t domid)
    132 {
    133 	return _hypercall4(int, mmu_update, req, count, success_count, domid);
    134 }
    135 
    136 static inline int
    137 HYPERVISOR_mmuext_op(
    138 	struct mmuext_op *op, int count, int *success_count, domid_t domid)
    139 {
    140 	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
    141 }
    142 
    143 static inline int
    144 HYPERVISOR_set_gdt(
    145 	unsigned long *frame_list, int entries)
    146 {
    147 	return _hypercall2(int, set_gdt, frame_list, entries);
    148 }
    149 
    150 static inline int
    151 HYPERVISOR_stack_switch(
    152 	unsigned long ss, unsigned long esp)
    153 {
    154 	return _hypercall2(int, stack_switch, ss, esp);
    155 }
    156 
    157 static inline int
    158 HYPERVISOR_set_callbacks(
    159 	unsigned long event_address, unsigned long failsafe_address,
    160 	unsigned long syscall_address)
    161 {
    162 	return _hypercall3(int, set_callbacks,
    163 			   event_address, failsafe_address, syscall_address);
    164 }
    165 
    166 static inline int
    167 HYPERVISOR_fpu_taskswitch(
    168 	int set)
    169 {
    170 	return _hypercall1(int, fpu_taskswitch, set);
    171 }
    172 
    173 static inline int
    174 HYPERVISOR_sched_op_compat(
    175 	int cmd, unsigned long arg)
    176 {
    177 	return _hypercall2(int, sched_op_compat, cmd, arg);
    178 }
    179 
    180 static inline int
    181 HYPERVISOR_sched_op(
    182 	int cmd, void *arg)
    183 {
    184 	return _hypercall2(int, sched_op, cmd, arg);
    185 }
    186 
    187 static inline long
    188 HYPERVISOR_set_timer_op(
    189 	u64 timeout)
    190 {
    191 	return _hypercall1(long, set_timer_op, timeout);
    192 }
    193 
    194 static inline int
    195 HYPERVISOR_platform_op(
    196 	struct xen_platform_op *platform_op)
    197 {
    198 	platform_op->interface_version = XENPF_INTERFACE_VERSION;
    199 	return _hypercall1(int, platform_op, platform_op);
    200 }
    201 
    202 static inline int
    203 HYPERVISOR_set_debugreg(
    204 	int reg, unsigned long value)
    205 {
    206 	return _hypercall2(int, set_debugreg, reg, value);
    207 }
    208 
    209 static inline unsigned long
    210 HYPERVISOR_get_debugreg(
    211 	int reg)
    212 {
    213 	return _hypercall1(unsigned long, get_debugreg, reg);
    214 }
    215 
    216 static inline int
    217 HYPERVISOR_update_descriptor(
    218 	unsigned long ma, unsigned long word)
    219 {
    220 	return _hypercall2(int, update_descriptor, ma, word);
    221 }
    222 
    223 static inline int
    224 HYPERVISOR_memory_op(
    225 	unsigned int cmd, void *arg)
    226 {
    227 	return _hypercall2(int, memory_op, cmd, arg);
    228 }
    229 
    230 static inline int
    231 HYPERVISOR_multicall(
    232 	multicall_entry_t *call_list, int nr_calls)
    233 {
    234 	return _hypercall2(int, multicall, call_list, nr_calls);
    235 }
    236 
    237 static inline int
    238 HYPERVISOR_update_va_mapping(
    239 	unsigned long va, unsigned long new_val, unsigned long flags)
    240 {
    241 	return _hypercall3(int, update_va_mapping, va, new_val, flags);
    242 }
    243 
    244 static inline int
    245 HYPERVISOR_event_channel_op(evtchn_op_t *op)
    246 {
    247 	KASSERT(op != NULL);
    248 #if __XEN_INTERFACE_VERSION__ < 0x00030202
    249 	return _hypercall1(int, event_channel_op, op);
    250 #else
    251 	return _hypercall2(int, event_channel_op, op->cmd, &op->u);
    252 #endif
    253 }
    254 
    255 static inline int
    256 HYPERVISOR_acm_op(
    257 	int cmd, void *arg)
    258 {
    259 	return _hypercall2(int, acm_op, cmd, arg);
    260 }
    261 
    262 static inline int
    263 HYPERVISOR_xen_version(
    264 	int cmd, void *arg)
    265 {
    266 	return _hypercall2(int, xen_version, cmd, arg);
    267 }
    268 
    269 static inline int
    270 HYPERVISOR_console_io(
    271 	int cmd, int count, char *str)
    272 {
    273 	return _hypercall3(int, console_io, cmd, count, str);
    274 }
    275 
    276 static inline int
    277 HYPERVISOR_physdev_op(int cmd, void *op)
    278 {
    279 	return _hypercall2(int, physdev_op, cmd, op);
    280 }
    281 
    282 static inline int
    283 HYPERVISOR_grant_table_op(
    284 	unsigned int cmd, void *uop, unsigned int count)
    285 {
    286 	return _hypercall3(int, grant_table_op, cmd, uop, count);
    287 }
    288 
    289 static inline int
    290 HYPERVISOR_update_va_mapping_otherdomain(
    291 	unsigned long va, unsigned long new_val, unsigned long flags,
    292 	domid_t domid)
    293 {
    294 	return _hypercall4(int, update_va_mapping_otherdomain, va,
    295 			   new_val, flags, domid);
    296 }
    297 
    298 static inline int
    299 HYPERVISOR_vm_assist(
    300 	unsigned int cmd, unsigned int type)
    301 {
    302 	return _hypercall2(int, vm_assist, cmd, type);
    303 }
    304 
    305 static inline int
    306 HYPERVISOR_vcpu_op(
    307 	int cmd, int vcpuid, void *extra_args)
    308 {
    309 	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
    310 }
    311 
    312 static inline int
    313 HYPERVISOR_set_segment_base(
    314 	int reg, unsigned long value)
    315 {
    316 	return _hypercall2(int, set_segment_base, reg, value);
    317 }
    318 
    319 static inline int
    320 HYPERVISOR_suspend(
    321 	unsigned long srec)
    322 {
    323 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    324 
    325 	struct sched_shutdown shutdown_reason = {
    326 		.reason = SHUTDOWN_suspend,
    327 	};
    328 
    329 	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
    330 	    &shutdown_reason, srec);
    331 #else
    332 	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
    333 				 SHUTDOWN_suspend, srec);
    334 #endif
    335 }
    336 
    337 static inline long
    338 HYPERVISOR_yield(
    339 	void)
    340 {
    341 	return _hypercall2(int, sched_op, SCHEDOP_yield, 0);
    342 }
    343 
    344 static inline long
    345 HYPERVISOR_block(
    346 	void)
    347 {
    348 	return _hypercall2(int, sched_op, SCHEDOP_block, 0);
    349 }
    350 
    351 static inline long
    352 HYPERVISOR_shutdown(
    353 	void)
    354 {
    355 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    356 
    357 	struct sched_shutdown shutdown_reason = {
    358 		.reason = SHUTDOWN_poweroff,
    359 	};
    360 
    361 	return _hypercall2(int, sched_op, SCHEDOP_shutdown,
    362 	    &shutdown_reason);
    363 #else
    364 -	return _hypercall2(int, sched_op, SCHEDOP_shutdown, SHUTDOWN_poweroff);
    365 #endif
    366 }
    367 
    368 static inline long
    369 HYPERVISOR_crash(
    370 	void)
    371 {
    372 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    373 
    374 	struct sched_shutdown shutdown_reason = {
    375 		.reason = SHUTDOWN_crash,
    376 	};
    377 
    378 	return _hypercall2(int, sched_op, SCHEDOP_shutdown,
    379 	    &shutdown_reason);
    380 #else
    381 	return _hypercall2(int, sched_op, SCHEDOP_shutdown, SHUTDOWN_crash);
    382 #endif
    383 }
    384 
    385 static inline long
    386 HYPERVISOR_reboot(
    387 	void)
    388 {
    389 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    390 
    391 	struct sched_shutdown shutdown_reason = {
    392 		.reason = SHUTDOWN_reboot,
    393 	};
    394 
    395 	return _hypercall2(int, sched_op, SCHEDOP_shutdown,
    396 	    &shutdown_reason);
    397 #else
    398 	return _hypercall2(int, sched_op, SCHEDOP_shutdown, SHUTDOWN_reboot);
    399 #endif
    400 }
    401 
    402 static inline int
    403 HYPERVISOR_nmi_op(
    404 	unsigned long op, void *arg)
    405 {
    406 	return _hypercall2(int, nmi_op, op, arg);
    407 }
    408 
    409 static inline long
    410 HYPERVISOR_hvm_op(
    411     int op, void *arg)
    412 {
    413     return _hypercall2(long, hvm_op, op, arg);
    414 }
    415 
    416 static inline int
    417 HYPERVISOR_callback_op(
    418 	int cmd, void *arg)
    419 {
    420 	return _hypercall2(int, callback_op, cmd, arg);
    421 }
    422 
    423 static inline int
    424 HYPERVISOR_xenoprof_op(
    425 	int op, void *arg)
    426 {
    427 	return _hypercall2(int, xenoprof_op, op, arg);
    428 }
    429 
    430 static inline int
    431 HYPERVISOR_kexec_op(
    432 	unsigned long op, void *args)
    433 {
    434 	return _hypercall2(int, kexec_op, op, args);
    435 }
    436 
    437 #if __XEN_INTERFACE_VERSION__ < 0x00030204
    438 static inline int
    439 HYPERVISOR_dom0_op(
    440 	dom0_op_t *dom0_op)
    441 {
    442 	dom0_op->interface_version = DOM0_INTERFACE_VERSION;
    443 	return _hypercall1(int, dom0_op, dom0_op);
    444 }
    445 #endif	/* __XEN_INTERFACE_VERSION__ */
    446 
    447 #include <xen/include/public/arch-x86/xen-mca.h>
    448 
    449 static inline int
    450 HYPERVISOR_machine_check(struct xen_mc *mc)
    451 {
    452 	mc->interface_version = XEN_MCA_INTERFACE_VERSION;
    453 	return _hypercall1(int, mca, mc);
    454 }
    455 
    456 static inline int
    457 HYPERVISOR_sysctl(void *sysctl)
    458 {
    459 	return _hypercall1(int, sysctl, sysctl);
    460 }
    461 
    462 #endif /* __HYPERCALL_H__ */
    463