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