hypercall.h revision 189699
1/******************************************************************************
2 * hypercall.h
3 *
4 * Linux-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
37#ifndef __MACHINE_XEN_HYPERCALL_H__
38#define __MACHINE_XEN_HYPERCALL_H__
39
40#include <sys/systm.h>
41
42#ifndef __XEN_HYPERVISOR_H__
43# error "please don't include this file directly"
44#endif
45
46#define __STR(x) #x
47#define STR(x) __STR(x)
48#define	ENOXENSYS	38
49#define CONFIG_XEN_COMPAT	0x030002
50#define __must_check
51
52#ifdef XEN
53#define HYPERCALL_STR(name)					\
54	"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"
55#else
56#define HYPERCALL_STR(name)					\
57	"mov $("STR(__HYPERVISOR_##name)" * 32),%%eax; "\
58	"add hypercall_stubs(%%rip),%%rax; "			\
59	"call *%%rax"
60#endif
61
62#define _hypercall0(type, name)			\
63({						\
64	type __res;				\
65	__asm__ volatile (				\
66		HYPERCALL_STR(name)		\
67		: "=a" (__res)			\
68		:				\
69		: "memory" );			\
70	__res;					\
71})
72
73#define _hypercall1(type, name, a1)				\
74({								\
75	type __res;						\
76	long __ign1;						\
77	__asm__ volatile (						\
78		HYPERCALL_STR(name)				\
79		: "=a" (__res), "=D" (__ign1)			\
80		: "1" ((long)(a1))				\
81		: "memory" );					\
82	__res;							\
83})
84
85#define _hypercall2(type, name, a1, a2)				\
86({								\
87	type __res;						\
88	long __ign1, __ign2;					\
89	__asm__ volatile (						\
90		HYPERCALL_STR(name)				\
91		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
92		: "1" ((long)(a1)), "2" ((long)(a2))		\
93		: "memory" );					\
94	__res;							\
95})
96
97#define _hypercall3(type, name, a1, a2, a3)			\
98({								\
99	type __res;						\
100	long __ign1, __ign2, __ign3;				\
101	__asm__ volatile (						\
102		HYPERCALL_STR(name)				\
103		: "=a" (__res), "=D" (__ign1), "=S" (__ign2), 	\
104		"=d" (__ign3)					\
105		: "1" ((long)(a1)), "2" ((long)(a2)),		\
106		"3" ((long)(a3))				\
107		: "memory" );					\
108	__res;							\
109})
110
111#define _hypercall4(type, name, a1, a2, a3, a4)			\
112({								\
113	type __res;						\
114	long __ign1, __ign2, __ign3;				\
115	register long __arg4 __asm__("r10") = (long)(a4);		\
116	__asm__ volatile (						\
117		HYPERCALL_STR(name)				\
118		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
119		  "=d" (__ign3), "+r" (__arg4)			\
120		: "1" ((long)(a1)), "2" ((long)(a2)),		\
121		  "3" ((long)(a3))				\
122		: "memory" );					\
123	__res;							\
124})
125
126#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
127({								\
128	type __res;						\
129	long __ign1, __ign2, __ign3;				\
130	register long __arg4 __asm__("r10") = (long)(a4);		\
131	register long __arg5 __asm__("r8") = (long)(a5);		\
132	__asm__ volatile (						\
133		HYPERCALL_STR(name)				\
134		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
135		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)	\
136		: "1" ((long)(a1)), "2" ((long)(a2)),		\
137		  "3" ((long)(a3))				\
138		: "memory" );					\
139	__res;							\
140})
141
142static inline int __must_check
143HYPERVISOR_set_trap_table(
144	const trap_info_t *table)
145{
146	return _hypercall1(int, set_trap_table, table);
147}
148
149static inline int __must_check
150HYPERVISOR_mmu_update(
151	mmu_update_t *req, unsigned int count, unsigned int *success_count,
152	domid_t domid)
153{
154	return _hypercall4(int, mmu_update, req, count, success_count, domid);
155}
156
157static inline int __must_check
158HYPERVISOR_mmuext_op(
159	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
160	domid_t domid)
161{
162	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
163}
164
165static inline int __must_check
166HYPERVISOR_set_gdt(
167	unsigned long *frame_list, unsigned int entries)
168{
169	return _hypercall2(int, set_gdt, frame_list, entries);
170}
171
172static inline int __must_check
173HYPERVISOR_stack_switch(
174	unsigned long ss, unsigned long esp)
175{
176	return _hypercall2(int, stack_switch, ss, esp);
177}
178
179static inline int __must_check
180HYPERVISOR_set_callbacks(
181	unsigned long event_address, unsigned long failsafe_address,
182	unsigned long syscall_address)
183{
184	return _hypercall3(int, set_callbacks,
185			   event_address, failsafe_address, syscall_address);
186}
187
188static inline int
189HYPERVISOR_fpu_taskswitch(
190	int set)
191{
192	return _hypercall1(int, fpu_taskswitch, set);
193}
194
195static inline int __must_check
196HYPERVISOR_sched_op_compat(
197	int cmd, unsigned long arg)
198{
199	return _hypercall2(int, sched_op_compat, cmd, arg);
200}
201
202static inline int __must_check
203HYPERVISOR_sched_op(
204	int cmd, void *arg)
205{
206	return _hypercall2(int, sched_op, cmd, arg);
207}
208
209static inline long __must_check
210HYPERVISOR_set_timer_op(
211	uint64_t timeout)
212{
213	return _hypercall1(long, set_timer_op, timeout);
214}
215
216static inline int __must_check
217HYPERVISOR_platform_op(
218	struct xen_platform_op *platform_op)
219{
220	platform_op->interface_version = XENPF_INTERFACE_VERSION;
221	return _hypercall1(int, platform_op, platform_op);
222}
223
224static inline int __must_check
225HYPERVISOR_set_debugreg(
226	unsigned int reg, unsigned long value)
227{
228	return _hypercall2(int, set_debugreg, reg, value);
229}
230
231static inline unsigned long __must_check
232HYPERVISOR_get_debugreg(
233	unsigned int reg)
234{
235	return _hypercall1(unsigned long, get_debugreg, reg);
236}
237
238static inline int __must_check
239HYPERVISOR_update_descriptor(
240	unsigned long ma, unsigned long word)
241{
242	return _hypercall2(int, update_descriptor, ma, word);
243}
244
245static inline int __must_check
246HYPERVISOR_memory_op(
247	unsigned int cmd, void *arg)
248{
249	return _hypercall2(int, memory_op, cmd, arg);
250}
251
252static inline int __must_check
253HYPERVISOR_multicall(
254	multicall_entry_t *call_list, unsigned int nr_calls)
255{
256	return _hypercall2(int, multicall, call_list, nr_calls);
257}
258
259static inline int __must_check
260HYPERVISOR_update_va_mapping(
261	unsigned long va, uint64_t new_val, unsigned long flags)
262{
263	return _hypercall3(int, update_va_mapping, va, new_val, flags);
264}
265
266static inline int __must_check
267HYPERVISOR_event_channel_op(
268	int cmd, void *arg)
269{
270	int rc = _hypercall2(int, event_channel_op, cmd, arg);
271
272#if CONFIG_XEN_COMPAT <= 0x030002
273	if (unlikely(rc == -ENOXENSYS)) {
274		struct evtchn_op op;
275		op.cmd = cmd;
276		memcpy(&op.u, arg, sizeof(op.u));
277		rc = _hypercall1(int, event_channel_op_compat, &op);
278		memcpy(arg, &op.u, sizeof(op.u));
279	}
280#endif
281
282	return rc;
283}
284
285static inline int __must_check
286HYPERVISOR_xen_version(
287	int cmd, void *arg)
288{
289	return _hypercall2(int, xen_version, cmd, arg);
290}
291
292static inline int __must_check
293HYPERVISOR_console_io(
294	int cmd, unsigned int count, char *str)
295{
296	return _hypercall3(int, console_io, cmd, count, str);
297}
298
299static inline int __must_check
300HYPERVISOR_physdev_op(
301	int cmd, void *arg)
302{
303	int rc = _hypercall2(int, physdev_op, cmd, arg);
304
305#if CONFIG_XEN_COMPAT <= 0x030002
306	if (unlikely(rc == -ENOXENSYS)) {
307		struct physdev_op op;
308		op.cmd = cmd;
309		memcpy(&op.u, arg, sizeof(op.u));
310		rc = _hypercall1(int, physdev_op_compat, &op);
311		memcpy(arg, &op.u, sizeof(op.u));
312	}
313#endif
314
315	return rc;
316}
317
318static inline int __must_check
319HYPERVISOR_grant_table_op(
320	unsigned int cmd, void *uop, unsigned int count)
321{
322	return _hypercall3(int, grant_table_op, cmd, uop, count);
323}
324
325static inline int __must_check
326HYPERVISOR_update_va_mapping_otherdomain(
327	unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid)
328{
329	return _hypercall4(int, update_va_mapping_otherdomain, va,
330			   new_val, flags, domid);
331}
332
333static inline int __must_check
334HYPERVISOR_vm_assist(
335	unsigned int cmd, unsigned int type)
336{
337	return _hypercall2(int, vm_assist, cmd, type);
338}
339
340static inline int __must_check
341HYPERVISOR_vcpu_op(
342	int cmd, unsigned int vcpuid, void *extra_args)
343{
344	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
345}
346
347static inline int __must_check
348HYPERVISOR_set_segment_base(
349	int reg, unsigned long value)
350{
351	return _hypercall2(int, set_segment_base, reg, value);
352}
353
354static inline int __must_check
355HYPERVISOR_suspend(
356	unsigned long srec)
357{
358	struct sched_shutdown sched_shutdown = {
359		.reason = SHUTDOWN_suspend
360	};
361
362	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
363			     &sched_shutdown, srec);
364
365#if CONFIG_XEN_COMPAT <= 0x030002
366	if (rc == -ENOXENSYS)
367		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
368				 SHUTDOWN_suspend, srec);
369#endif
370
371	return rc;
372}
373
374#if CONFIG_XEN_COMPAT <= 0x030002
375static inline int
376HYPERVISOR_nmi_op(
377	unsigned long op, void *arg)
378{
379	return _hypercall2(int, nmi_op, op, arg);
380}
381#endif
382
383#ifndef CONFIG_XEN
384static inline unsigned long __must_check
385HYPERVISOR_hvm_op(
386    int op, void *arg)
387{
388    return _hypercall2(unsigned long, hvm_op, op, arg);
389}
390#endif
391
392static inline int __must_check
393HYPERVISOR_callback_op(
394	int cmd, const void *arg)
395{
396	return _hypercall2(int, callback_op, cmd, arg);
397}
398
399static inline int __must_check
400HYPERVISOR_xenoprof_op(
401	int op, void *arg)
402{
403	return _hypercall2(int, xenoprof_op, op, arg);
404}
405
406static inline int __must_check
407HYPERVISOR_kexec_op(
408	unsigned long op, void *args)
409{
410	return _hypercall2(int, kexec_op, op, args);
411}
412
413#undef __must_check
414
415#endif /* __MACHINE_XEN_HYPERCALL_H__ */
416