1183906Skmacy/******************************************************************************
2183906Skmacy * hypercall.h
3183906Skmacy *
4255040Sgibbs * FreeBSD-specific hypervisor handling.
5183906Skmacy *
6183906Skmacy * Copyright (c) 2002-2004, K A Fraser
7183906Skmacy *
8185386Sdfr * 64-bit updates:
9185386Sdfr *   Benjamin Liu <benjamin.liu@intel.com>
10185386Sdfr *   Jun Nakajima <jun.nakajima@intel.com>
11183906Skmacy *
12185386Sdfr * This program is free software; you can redistribute it and/or
13185386Sdfr * modify it under the terms of the GNU General Public License version 2
14185386Sdfr * as published by the Free Software Foundation; or, when distributed
15185386Sdfr * separately from the Linux kernel or incorporated into other
16185386Sdfr * software packages, subject to the following license:
17185386Sdfr *
18183906Skmacy * Permission is hereby granted, free of charge, to any person obtaining a copy
19183906Skmacy * of this source file (the "Software"), to deal in the Software without
20183906Skmacy * restriction, including without limitation the rights to use, copy, modify,
21183906Skmacy * merge, publish, distribute, sublicense, and/or sell copies of the Software,
22183906Skmacy * and to permit persons to whom the Software is furnished to do so, subject to
23183906Skmacy * the following conditions:
24183906Skmacy *
25183906Skmacy * The above copyright notice and this permission notice shall be included in
26183906Skmacy * all copies or substantial portions of the Software.
27183906Skmacy *
28183906Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29183906Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30183906Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31183906Skmacy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32183906Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33183906Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34183906Skmacy * IN THE SOFTWARE.
35255040Sgibbs *
36255040Sgibbs * $FreeBSD$
37183906Skmacy */
38183906Skmacy
39185637Sdfr#ifndef __MACHINE_XEN_HYPERCALL_H__
40185637Sdfr#define __MACHINE_XEN_HYPERCALL_H__
41183906Skmacy
42183906Skmacy#include <sys/systm.h>
43183906Skmacy
44185637Sdfr#ifndef __XEN_HYPERVISOR_H__
45185386Sdfr# error "please don't include this file directly"
46185386Sdfr#endif
47185386Sdfr
48273476Sroygerextern char *hypercall_page;
49273476Sroyger
50183906Skmacy#define __STR(x) #x
51183906Skmacy#define STR(x) __STR(x)
52183906Skmacy#define	ENOXENSYS	38
53183906Skmacy#define CONFIG_XEN_COMPAT	0x030002
54185386Sdfr#define __must_check
55183906Skmacy
56185386Sdfr#define HYPERCALL_STR(name)					\
57185386Sdfr	"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"
58183906Skmacy
59185386Sdfr#define _hypercall0(type, name)			\
60185386Sdfr({						\
61185386Sdfr	type __res;				\
62185386Sdfr	__asm__ volatile (				\
63185386Sdfr		HYPERCALL_STR(name)		\
64185386Sdfr		: "=a" (__res)			\
65185386Sdfr		:				\
66185386Sdfr		: "memory" );			\
67185386Sdfr	__res;					\
68183906Skmacy})
69183906Skmacy
70185386Sdfr#define _hypercall1(type, name, a1)				\
71185386Sdfr({								\
72185386Sdfr	type __res;						\
73185386Sdfr	long __ign1;						\
74185386Sdfr	__asm__ volatile (						\
75185386Sdfr		HYPERCALL_STR(name)				\
76185386Sdfr		: "=a" (__res), "=D" (__ign1)			\
77185386Sdfr		: "1" ((long)(a1))				\
78185386Sdfr		: "memory" );					\
79185386Sdfr	__res;							\
80183906Skmacy})
81183906Skmacy
82185386Sdfr#define _hypercall2(type, name, a1, a2)				\
83185386Sdfr({								\
84185386Sdfr	type __res;						\
85185386Sdfr	long __ign1, __ign2;					\
86185386Sdfr	__asm__ volatile (						\
87185386Sdfr		HYPERCALL_STR(name)				\
88185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
89185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2))		\
90185386Sdfr		: "memory" );					\
91185386Sdfr	__res;							\
92183906Skmacy})
93183906Skmacy
94185386Sdfr#define _hypercall3(type, name, a1, a2, a3)			\
95185386Sdfr({								\
96185386Sdfr	type __res;						\
97185386Sdfr	long __ign1, __ign2, __ign3;				\
98185386Sdfr	__asm__ volatile (						\
99185386Sdfr		HYPERCALL_STR(name)				\
100185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2), 	\
101185386Sdfr		"=d" (__ign3)					\
102185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2)),		\
103185386Sdfr		"3" ((long)(a3))				\
104185386Sdfr		: "memory" );					\
105185386Sdfr	__res;							\
106183906Skmacy})
107183906Skmacy
108185386Sdfr#define _hypercall4(type, name, a1, a2, a3, a4)			\
109185386Sdfr({								\
110185386Sdfr	type __res;						\
111185386Sdfr	long __ign1, __ign2, __ign3;				\
112185386Sdfr	register long __arg4 __asm__("r10") = (long)(a4);		\
113185386Sdfr	__asm__ volatile (						\
114185386Sdfr		HYPERCALL_STR(name)				\
115185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
116185386Sdfr		  "=d" (__ign3), "+r" (__arg4)			\
117185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2)),		\
118185386Sdfr		  "3" ((long)(a3))				\
119185386Sdfr		: "memory" );					\
120185386Sdfr	__res;							\
121183906Skmacy})
122183906Skmacy
123185386Sdfr#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
124185386Sdfr({								\
125185386Sdfr	type __res;						\
126185386Sdfr	long __ign1, __ign2, __ign3;				\
127185386Sdfr	register long __arg4 __asm__("r10") = (long)(a4);		\
128185386Sdfr	register long __arg5 __asm__("r8") = (long)(a5);		\
129185386Sdfr	__asm__ volatile (						\
130185386Sdfr		HYPERCALL_STR(name)				\
131185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
132185386Sdfr		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)	\
133185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2)),		\
134185386Sdfr		  "3" ((long)(a3))				\
135185386Sdfr		: "memory" );					\
136185386Sdfr	__res;							\
137185386Sdfr})
138183906Skmacy
139273476Sroygerstatic inline int
140273476Sroygerprivcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5)
141273476Sroyger{
142273476Sroyger	int __res;
143273476Sroyger	long __ign1, __ign2, __ign3;
144273476Sroyger	register long __arg4 __asm__("r10") = (long)(a4);
145273476Sroyger	register long __arg5 __asm__("r8") = (long)(a5);
146273476Sroyger	long __call = (long)&hypercall_page + (op * 32);
147273476Sroyger
148273476Sroyger	__asm__ volatile (
149273476Sroyger		"call *%[call]"
150273476Sroyger		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),
151273476Sroyger		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)
152273476Sroyger		: "1" ((long)(a1)), "2" ((long)(a2)),
153273476Sroyger		  "3" ((long)(a3)), [call] "a" (__call)
154273476Sroyger		: "memory" );
155273476Sroyger
156273476Sroyger	return (__res);
157273476Sroyger}
158273476Sroyger
159185386Sdfrstatic inline int __must_check
160183906SkmacyHYPERVISOR_set_trap_table(
161185386Sdfr	const trap_info_t *table)
162183906Skmacy{
163183906Skmacy	return _hypercall1(int, set_trap_table, table);
164183906Skmacy}
165183906Skmacy
166185386Sdfrstatic inline int __must_check
167183906SkmacyHYPERVISOR_mmu_update(
168185386Sdfr	mmu_update_t *req, unsigned int count, unsigned int *success_count,
169185386Sdfr	domid_t domid)
170183906Skmacy{
171183906Skmacy	return _hypercall4(int, mmu_update, req, count, success_count, domid);
172183906Skmacy}
173183906Skmacy
174185386Sdfrstatic inline int __must_check
175183906SkmacyHYPERVISOR_mmuext_op(
176185386Sdfr	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
177185386Sdfr	domid_t domid)
178183906Skmacy{
179183906Skmacy	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
180183906Skmacy}
181183906Skmacy
182185386Sdfrstatic inline int __must_check
183183906SkmacyHYPERVISOR_set_gdt(
184185386Sdfr	unsigned long *frame_list, unsigned int entries)
185183906Skmacy{
186183906Skmacy	return _hypercall2(int, set_gdt, frame_list, entries);
187183906Skmacy}
188183906Skmacy
189185386Sdfrstatic inline int __must_check
190183906SkmacyHYPERVISOR_stack_switch(
191183906Skmacy	unsigned long ss, unsigned long esp)
192183906Skmacy{
193183906Skmacy	return _hypercall2(int, stack_switch, ss, esp);
194183906Skmacy}
195183906Skmacy
196185386Sdfrstatic inline int __must_check
197183906SkmacyHYPERVISOR_set_callbacks(
198185386Sdfr	unsigned long event_address, unsigned long failsafe_address,
199185386Sdfr	unsigned long syscall_address)
200183906Skmacy{
201185386Sdfr	return _hypercall3(int, set_callbacks,
202185386Sdfr			   event_address, failsafe_address, syscall_address);
203183906Skmacy}
204183906Skmacy
205183906Skmacystatic inline int
206183906SkmacyHYPERVISOR_fpu_taskswitch(
207183906Skmacy	int set)
208183906Skmacy{
209183906Skmacy	return _hypercall1(int, fpu_taskswitch, set);
210183906Skmacy}
211183906Skmacy
212185386Sdfrstatic inline int __must_check
213183906SkmacyHYPERVISOR_sched_op_compat(
214183906Skmacy	int cmd, unsigned long arg)
215183906Skmacy{
216183906Skmacy	return _hypercall2(int, sched_op_compat, cmd, arg);
217183906Skmacy}
218183906Skmacy
219185386Sdfrstatic inline int __must_check
220183906SkmacyHYPERVISOR_sched_op(
221183906Skmacy	int cmd, void *arg)
222183906Skmacy{
223183906Skmacy	return _hypercall2(int, sched_op, cmd, arg);
224183906Skmacy}
225183906Skmacy
226185386Sdfrstatic inline long __must_check
227183906SkmacyHYPERVISOR_set_timer_op(
228183906Skmacy	uint64_t timeout)
229183906Skmacy{
230185386Sdfr	return _hypercall1(long, set_timer_op, timeout);
231183906Skmacy}
232185386Sdfr
233185386Sdfrstatic inline int __must_check
234183906SkmacyHYPERVISOR_platform_op(
235185386Sdfr	struct xen_platform_op *platform_op)
236183906Skmacy{
237185386Sdfr	platform_op->interface_version = XENPF_INTERFACE_VERSION;
238185386Sdfr	return _hypercall1(int, platform_op, platform_op);
239183906Skmacy}
240185386Sdfr
241185386Sdfrstatic inline int __must_check
242183906SkmacyHYPERVISOR_set_debugreg(
243185386Sdfr	unsigned int reg, unsigned long value)
244183906Skmacy{
245183906Skmacy	return _hypercall2(int, set_debugreg, reg, value);
246183906Skmacy}
247183906Skmacy
248185386Sdfrstatic inline unsigned long __must_check
249183906SkmacyHYPERVISOR_get_debugreg(
250185386Sdfr	unsigned int reg)
251183906Skmacy{
252183906Skmacy	return _hypercall1(unsigned long, get_debugreg, reg);
253183906Skmacy}
254183906Skmacy
255185386Sdfrstatic inline int __must_check
256183906SkmacyHYPERVISOR_update_descriptor(
257185386Sdfr	unsigned long ma, unsigned long word)
258183906Skmacy{
259185386Sdfr	return _hypercall2(int, update_descriptor, ma, word);
260183906Skmacy}
261183906Skmacy
262185386Sdfrstatic inline int __must_check
263183906SkmacyHYPERVISOR_memory_op(
264183906Skmacy	unsigned int cmd, void *arg)
265183906Skmacy{
266183906Skmacy	return _hypercall2(int, memory_op, cmd, arg);
267183906Skmacy}
268183906Skmacy
269185386Sdfrstatic inline int __must_check
270183906SkmacyHYPERVISOR_multicall(
271185386Sdfr	multicall_entry_t *call_list, unsigned int nr_calls)
272183906Skmacy{
273183906Skmacy	return _hypercall2(int, multicall, call_list, nr_calls);
274183906Skmacy}
275183906Skmacy
276185386Sdfrstatic inline int __must_check
277183906SkmacyHYPERVISOR_update_va_mapping(
278183906Skmacy	unsigned long va, uint64_t new_val, unsigned long flags)
279183906Skmacy{
280185386Sdfr	return _hypercall3(int, update_va_mapping, va, new_val, flags);
281183906Skmacy}
282183906Skmacy
283185386Sdfrstatic inline int __must_check
284183906SkmacyHYPERVISOR_event_channel_op(
285183906Skmacy	int cmd, void *arg)
286183906Skmacy{
287183906Skmacy	int rc = _hypercall2(int, event_channel_op, cmd, arg);
288183906Skmacy
289183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
290255040Sgibbs	if (__predict_false(rc == -ENOXENSYS)) {
291183906Skmacy		struct evtchn_op op;
292183906Skmacy		op.cmd = cmd;
293183906Skmacy		memcpy(&op.u, arg, sizeof(op.u));
294183906Skmacy		rc = _hypercall1(int, event_channel_op_compat, &op);
295183906Skmacy		memcpy(arg, &op.u, sizeof(op.u));
296183906Skmacy	}
297183906Skmacy#endif
298185386Sdfr
299185386Sdfr	return rc;
300183906Skmacy}
301183906Skmacy
302185386Sdfrstatic inline int __must_check
303183906SkmacyHYPERVISOR_xen_version(
304183906Skmacy	int cmd, void *arg)
305183906Skmacy{
306183906Skmacy	return _hypercall2(int, xen_version, cmd, arg);
307183906Skmacy}
308183906Skmacy
309185386Sdfrstatic inline int __must_check
310183906SkmacyHYPERVISOR_console_io(
311289033Sroyger	int cmd, unsigned int count, const char *str)
312183906Skmacy{
313183906Skmacy	return _hypercall3(int, console_io, cmd, count, str);
314183906Skmacy}
315183906Skmacy
316185386Sdfrstatic inline int __must_check
317183906SkmacyHYPERVISOR_physdev_op(
318183906Skmacy	int cmd, void *arg)
319183906Skmacy{
320183906Skmacy	int rc = _hypercall2(int, physdev_op, cmd, arg);
321185386Sdfr
322183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
323255040Sgibbs	if (__predict_false(rc == -ENOXENSYS)) {
324183906Skmacy		struct physdev_op op;
325183906Skmacy		op.cmd = cmd;
326183906Skmacy		memcpy(&op.u, arg, sizeof(op.u));
327183906Skmacy		rc = _hypercall1(int, physdev_op_compat, &op);
328183906Skmacy		memcpy(arg, &op.u, sizeof(op.u));
329183906Skmacy	}
330183906Skmacy#endif
331185386Sdfr
332185386Sdfr	return rc;
333183906Skmacy}
334183906Skmacy
335185386Sdfrstatic inline int __must_check
336183906SkmacyHYPERVISOR_grant_table_op(
337183906Skmacy	unsigned int cmd, void *uop, unsigned int count)
338183906Skmacy{
339183906Skmacy	return _hypercall3(int, grant_table_op, cmd, uop, count);
340183906Skmacy}
341183906Skmacy
342185386Sdfrstatic inline int __must_check
343183906SkmacyHYPERVISOR_update_va_mapping_otherdomain(
344183906Skmacy	unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid)
345183906Skmacy{
346185386Sdfr	return _hypercall4(int, update_va_mapping_otherdomain, va,
347185386Sdfr			   new_val, flags, domid);
348183906Skmacy}
349183906Skmacy
350185386Sdfrstatic inline int __must_check
351183906SkmacyHYPERVISOR_vm_assist(
352183906Skmacy	unsigned int cmd, unsigned int type)
353183906Skmacy{
354183906Skmacy	return _hypercall2(int, vm_assist, cmd, type);
355183906Skmacy}
356183906Skmacy
357185386Sdfrstatic inline int __must_check
358183906SkmacyHYPERVISOR_vcpu_op(
359185386Sdfr	int cmd, unsigned int vcpuid, void *extra_args)
360183906Skmacy{
361183906Skmacy	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
362183906Skmacy}
363183906Skmacy
364185386Sdfrstatic inline int __must_check
365185386SdfrHYPERVISOR_set_segment_base(
366185386Sdfr	int reg, unsigned long value)
367185386Sdfr{
368185386Sdfr	return _hypercall2(int, set_segment_base, reg, value);
369185386Sdfr}
370185386Sdfr
371185386Sdfrstatic inline int __must_check
372183906SkmacyHYPERVISOR_suspend(
373183906Skmacy	unsigned long srec)
374183906Skmacy{
375183906Skmacy	struct sched_shutdown sched_shutdown = {
376183906Skmacy		.reason = SHUTDOWN_suspend
377183906Skmacy	};
378185386Sdfr
379183906Skmacy	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
380185386Sdfr			     &sched_shutdown, srec);
381185386Sdfr
382183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
383183906Skmacy	if (rc == -ENOXENSYS)
384183906Skmacy		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
385183906Skmacy				 SHUTDOWN_suspend, srec);
386185386Sdfr#endif
387185386Sdfr
388185386Sdfr	return rc;
389183906Skmacy}
390183906Skmacy
391183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
392183906Skmacystatic inline int
393183906SkmacyHYPERVISOR_nmi_op(
394185386Sdfr	unsigned long op, void *arg)
395183906Skmacy{
396185386Sdfr	return _hypercall2(int, nmi_op, op, arg);
397183906Skmacy}
398183906Skmacy#endif
399183906Skmacy
400183906Skmacy#ifndef CONFIG_XEN
401185386Sdfrstatic inline unsigned long __must_check
402183906SkmacyHYPERVISOR_hvm_op(
403183906Skmacy    int op, void *arg)
404183906Skmacy{
405183906Skmacy    return _hypercall2(unsigned long, hvm_op, op, arg);
406183906Skmacy}
407183906Skmacy#endif
408183906Skmacy
409185386Sdfrstatic inline int __must_check
410185386SdfrHYPERVISOR_callback_op(
411185386Sdfr	int cmd, const void *arg)
412185386Sdfr{
413185386Sdfr	return _hypercall2(int, callback_op, cmd, arg);
414185386Sdfr}
415185386Sdfr
416185386Sdfrstatic inline int __must_check
417183906SkmacyHYPERVISOR_xenoprof_op(
418185386Sdfr	int op, void *arg)
419183906Skmacy{
420185386Sdfr	return _hypercall2(int, xenoprof_op, op, arg);
421183906Skmacy}
422183906Skmacy
423185386Sdfrstatic inline int __must_check
424183906SkmacyHYPERVISOR_kexec_op(
425185386Sdfr	unsigned long op, void *args)
426183906Skmacy{
427185386Sdfr	return _hypercall2(int, kexec_op, op, args);
428183906Skmacy}
429185386Sdfr
430185386Sdfr#undef __must_check
431185386Sdfr
432185637Sdfr#endif /* __MACHINE_XEN_HYPERCALL_H__ */
433