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
48183906Skmacy#define __STR(x) #x
49183906Skmacy#define STR(x) __STR(x)
50183906Skmacy#define	ENOXENSYS	38
51183906Skmacy#define CONFIG_XEN_COMPAT	0x030002
52185386Sdfr#define __must_check
53183906Skmacy
54185386Sdfr#ifdef XEN
55185386Sdfr#define HYPERCALL_STR(name)					\
56185386Sdfr	"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"
57183906Skmacy#else
58185386Sdfr#define HYPERCALL_STR(name)					\
59185386Sdfr	"mov $("STR(__HYPERVISOR_##name)" * 32),%%eax; "\
60185386Sdfr	"add hypercall_stubs(%%rip),%%rax; "			\
61185386Sdfr	"call *%%rax"
62183906Skmacy#endif
63183906Skmacy
64185386Sdfr#define _hypercall0(type, name)			\
65185386Sdfr({						\
66185386Sdfr	type __res;				\
67185386Sdfr	__asm__ volatile (				\
68185386Sdfr		HYPERCALL_STR(name)		\
69185386Sdfr		: "=a" (__res)			\
70185386Sdfr		:				\
71185386Sdfr		: "memory" );			\
72185386Sdfr	__res;					\
73183906Skmacy})
74183906Skmacy
75185386Sdfr#define _hypercall1(type, name, a1)				\
76185386Sdfr({								\
77185386Sdfr	type __res;						\
78185386Sdfr	long __ign1;						\
79185386Sdfr	__asm__ volatile (						\
80185386Sdfr		HYPERCALL_STR(name)				\
81185386Sdfr		: "=a" (__res), "=D" (__ign1)			\
82185386Sdfr		: "1" ((long)(a1))				\
83185386Sdfr		: "memory" );					\
84185386Sdfr	__res;							\
85183906Skmacy})
86183906Skmacy
87185386Sdfr#define _hypercall2(type, name, a1, a2)				\
88185386Sdfr({								\
89185386Sdfr	type __res;						\
90185386Sdfr	long __ign1, __ign2;					\
91185386Sdfr	__asm__ volatile (						\
92185386Sdfr		HYPERCALL_STR(name)				\
93185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
94185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2))		\
95185386Sdfr		: "memory" );					\
96185386Sdfr	__res;							\
97183906Skmacy})
98183906Skmacy
99185386Sdfr#define _hypercall3(type, name, a1, a2, a3)			\
100185386Sdfr({								\
101185386Sdfr	type __res;						\
102185386Sdfr	long __ign1, __ign2, __ign3;				\
103185386Sdfr	__asm__ volatile (						\
104185386Sdfr		HYPERCALL_STR(name)				\
105185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2), 	\
106185386Sdfr		"=d" (__ign3)					\
107185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2)),		\
108185386Sdfr		"3" ((long)(a3))				\
109185386Sdfr		: "memory" );					\
110185386Sdfr	__res;							\
111183906Skmacy})
112183906Skmacy
113185386Sdfr#define _hypercall4(type, name, a1, a2, a3, a4)			\
114185386Sdfr({								\
115185386Sdfr	type __res;						\
116185386Sdfr	long __ign1, __ign2, __ign3;				\
117185386Sdfr	register long __arg4 __asm__("r10") = (long)(a4);		\
118185386Sdfr	__asm__ volatile (						\
119185386Sdfr		HYPERCALL_STR(name)				\
120185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
121185386Sdfr		  "=d" (__ign3), "+r" (__arg4)			\
122185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2)),		\
123185386Sdfr		  "3" ((long)(a3))				\
124185386Sdfr		: "memory" );					\
125185386Sdfr	__res;							\
126183906Skmacy})
127183906Skmacy
128185386Sdfr#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
129185386Sdfr({								\
130185386Sdfr	type __res;						\
131185386Sdfr	long __ign1, __ign2, __ign3;				\
132185386Sdfr	register long __arg4 __asm__("r10") = (long)(a4);		\
133185386Sdfr	register long __arg5 __asm__("r8") = (long)(a5);		\
134185386Sdfr	__asm__ volatile (						\
135185386Sdfr		HYPERCALL_STR(name)				\
136185386Sdfr		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
137185386Sdfr		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)	\
138185386Sdfr		: "1" ((long)(a1)), "2" ((long)(a2)),		\
139185386Sdfr		  "3" ((long)(a3))				\
140185386Sdfr		: "memory" );					\
141185386Sdfr	__res;							\
142185386Sdfr})
143183906Skmacy
144185386Sdfrstatic inline int __must_check
145183906SkmacyHYPERVISOR_set_trap_table(
146185386Sdfr	const trap_info_t *table)
147183906Skmacy{
148183906Skmacy	return _hypercall1(int, set_trap_table, table);
149183906Skmacy}
150183906Skmacy
151185386Sdfrstatic inline int __must_check
152183906SkmacyHYPERVISOR_mmu_update(
153185386Sdfr	mmu_update_t *req, unsigned int count, unsigned int *success_count,
154185386Sdfr	domid_t domid)
155183906Skmacy{
156183906Skmacy	return _hypercall4(int, mmu_update, req, count, success_count, domid);
157183906Skmacy}
158183906Skmacy
159185386Sdfrstatic inline int __must_check
160183906SkmacyHYPERVISOR_mmuext_op(
161185386Sdfr	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
162185386Sdfr	domid_t domid)
163183906Skmacy{
164183906Skmacy	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
165183906Skmacy}
166183906Skmacy
167185386Sdfrstatic inline int __must_check
168183906SkmacyHYPERVISOR_set_gdt(
169185386Sdfr	unsigned long *frame_list, unsigned int entries)
170183906Skmacy{
171183906Skmacy	return _hypercall2(int, set_gdt, frame_list, entries);
172183906Skmacy}
173183906Skmacy
174185386Sdfrstatic inline int __must_check
175183906SkmacyHYPERVISOR_stack_switch(
176183906Skmacy	unsigned long ss, unsigned long esp)
177183906Skmacy{
178183906Skmacy	return _hypercall2(int, stack_switch, ss, esp);
179183906Skmacy}
180183906Skmacy
181185386Sdfrstatic inline int __must_check
182183906SkmacyHYPERVISOR_set_callbacks(
183185386Sdfr	unsigned long event_address, unsigned long failsafe_address,
184185386Sdfr	unsigned long syscall_address)
185183906Skmacy{
186185386Sdfr	return _hypercall3(int, set_callbacks,
187185386Sdfr			   event_address, failsafe_address, syscall_address);
188183906Skmacy}
189183906Skmacy
190183906Skmacystatic inline int
191183906SkmacyHYPERVISOR_fpu_taskswitch(
192183906Skmacy	int set)
193183906Skmacy{
194183906Skmacy	return _hypercall1(int, fpu_taskswitch, set);
195183906Skmacy}
196183906Skmacy
197185386Sdfrstatic inline int __must_check
198183906SkmacyHYPERVISOR_sched_op_compat(
199183906Skmacy	int cmd, unsigned long arg)
200183906Skmacy{
201183906Skmacy	return _hypercall2(int, sched_op_compat, cmd, arg);
202183906Skmacy}
203183906Skmacy
204185386Sdfrstatic inline int __must_check
205183906SkmacyHYPERVISOR_sched_op(
206183906Skmacy	int cmd, void *arg)
207183906Skmacy{
208183906Skmacy	return _hypercall2(int, sched_op, cmd, arg);
209183906Skmacy}
210183906Skmacy
211185386Sdfrstatic inline long __must_check
212183906SkmacyHYPERVISOR_set_timer_op(
213183906Skmacy	uint64_t timeout)
214183906Skmacy{
215185386Sdfr	return _hypercall1(long, set_timer_op, timeout);
216183906Skmacy}
217185386Sdfr
218185386Sdfrstatic inline int __must_check
219183906SkmacyHYPERVISOR_platform_op(
220185386Sdfr	struct xen_platform_op *platform_op)
221183906Skmacy{
222185386Sdfr	platform_op->interface_version = XENPF_INTERFACE_VERSION;
223185386Sdfr	return _hypercall1(int, platform_op, platform_op);
224183906Skmacy}
225185386Sdfr
226185386Sdfrstatic inline int __must_check
227183906SkmacyHYPERVISOR_set_debugreg(
228185386Sdfr	unsigned int reg, unsigned long value)
229183906Skmacy{
230183906Skmacy	return _hypercall2(int, set_debugreg, reg, value);
231183906Skmacy}
232183906Skmacy
233185386Sdfrstatic inline unsigned long __must_check
234183906SkmacyHYPERVISOR_get_debugreg(
235185386Sdfr	unsigned int reg)
236183906Skmacy{
237183906Skmacy	return _hypercall1(unsigned long, get_debugreg, reg);
238183906Skmacy}
239183906Skmacy
240185386Sdfrstatic inline int __must_check
241183906SkmacyHYPERVISOR_update_descriptor(
242185386Sdfr	unsigned long ma, unsigned long word)
243183906Skmacy{
244185386Sdfr	return _hypercall2(int, update_descriptor, ma, word);
245183906Skmacy}
246183906Skmacy
247185386Sdfrstatic inline int __must_check
248183906SkmacyHYPERVISOR_memory_op(
249183906Skmacy	unsigned int cmd, void *arg)
250183906Skmacy{
251183906Skmacy	return _hypercall2(int, memory_op, cmd, arg);
252183906Skmacy}
253183906Skmacy
254185386Sdfrstatic inline int __must_check
255183906SkmacyHYPERVISOR_multicall(
256185386Sdfr	multicall_entry_t *call_list, unsigned int nr_calls)
257183906Skmacy{
258183906Skmacy	return _hypercall2(int, multicall, call_list, nr_calls);
259183906Skmacy}
260183906Skmacy
261185386Sdfrstatic inline int __must_check
262183906SkmacyHYPERVISOR_update_va_mapping(
263183906Skmacy	unsigned long va, uint64_t new_val, unsigned long flags)
264183906Skmacy{
265185386Sdfr	return _hypercall3(int, update_va_mapping, va, new_val, flags);
266183906Skmacy}
267183906Skmacy
268185386Sdfrstatic inline int __must_check
269183906SkmacyHYPERVISOR_event_channel_op(
270183906Skmacy	int cmd, void *arg)
271183906Skmacy{
272183906Skmacy	int rc = _hypercall2(int, event_channel_op, cmd, arg);
273183906Skmacy
274183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
275255040Sgibbs	if (__predict_false(rc == -ENOXENSYS)) {
276183906Skmacy		struct evtchn_op op;
277183906Skmacy		op.cmd = cmd;
278183906Skmacy		memcpy(&op.u, arg, sizeof(op.u));
279183906Skmacy		rc = _hypercall1(int, event_channel_op_compat, &op);
280183906Skmacy		memcpy(arg, &op.u, sizeof(op.u));
281183906Skmacy	}
282183906Skmacy#endif
283185386Sdfr
284185386Sdfr	return rc;
285183906Skmacy}
286183906Skmacy
287185386Sdfrstatic inline int __must_check
288183906SkmacyHYPERVISOR_xen_version(
289183906Skmacy	int cmd, void *arg)
290183906Skmacy{
291183906Skmacy	return _hypercall2(int, xen_version, cmd, arg);
292183906Skmacy}
293183906Skmacy
294185386Sdfrstatic inline int __must_check
295183906SkmacyHYPERVISOR_console_io(
296185386Sdfr	int cmd, unsigned int count, char *str)
297183906Skmacy{
298183906Skmacy	return _hypercall3(int, console_io, cmd, count, str);
299183906Skmacy}
300183906Skmacy
301185386Sdfrstatic inline int __must_check
302183906SkmacyHYPERVISOR_physdev_op(
303183906Skmacy	int cmd, void *arg)
304183906Skmacy{
305183906Skmacy	int rc = _hypercall2(int, physdev_op, cmd, arg);
306185386Sdfr
307183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
308255040Sgibbs	if (__predict_false(rc == -ENOXENSYS)) {
309183906Skmacy		struct physdev_op op;
310183906Skmacy		op.cmd = cmd;
311183906Skmacy		memcpy(&op.u, arg, sizeof(op.u));
312183906Skmacy		rc = _hypercall1(int, physdev_op_compat, &op);
313183906Skmacy		memcpy(arg, &op.u, sizeof(op.u));
314183906Skmacy	}
315183906Skmacy#endif
316185386Sdfr
317185386Sdfr	return rc;
318183906Skmacy}
319183906Skmacy
320185386Sdfrstatic inline int __must_check
321183906SkmacyHYPERVISOR_grant_table_op(
322183906Skmacy	unsigned int cmd, void *uop, unsigned int count)
323183906Skmacy{
324183906Skmacy	return _hypercall3(int, grant_table_op, cmd, uop, count);
325183906Skmacy}
326183906Skmacy
327185386Sdfrstatic inline int __must_check
328183906SkmacyHYPERVISOR_update_va_mapping_otherdomain(
329183906Skmacy	unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid)
330183906Skmacy{
331185386Sdfr	return _hypercall4(int, update_va_mapping_otherdomain, va,
332185386Sdfr			   new_val, flags, domid);
333183906Skmacy}
334183906Skmacy
335185386Sdfrstatic inline int __must_check
336183906SkmacyHYPERVISOR_vm_assist(
337183906Skmacy	unsigned int cmd, unsigned int type)
338183906Skmacy{
339183906Skmacy	return _hypercall2(int, vm_assist, cmd, type);
340183906Skmacy}
341183906Skmacy
342185386Sdfrstatic inline int __must_check
343183906SkmacyHYPERVISOR_vcpu_op(
344185386Sdfr	int cmd, unsigned int vcpuid, void *extra_args)
345183906Skmacy{
346183906Skmacy	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
347183906Skmacy}
348183906Skmacy
349185386Sdfrstatic inline int __must_check
350185386SdfrHYPERVISOR_set_segment_base(
351185386Sdfr	int reg, unsigned long value)
352185386Sdfr{
353185386Sdfr	return _hypercall2(int, set_segment_base, reg, value);
354185386Sdfr}
355185386Sdfr
356185386Sdfrstatic inline int __must_check
357183906SkmacyHYPERVISOR_suspend(
358183906Skmacy	unsigned long srec)
359183906Skmacy{
360183906Skmacy	struct sched_shutdown sched_shutdown = {
361183906Skmacy		.reason = SHUTDOWN_suspend
362183906Skmacy	};
363185386Sdfr
364183906Skmacy	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
365185386Sdfr			     &sched_shutdown, srec);
366185386Sdfr
367183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
368183906Skmacy	if (rc == -ENOXENSYS)
369183906Skmacy		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
370183906Skmacy				 SHUTDOWN_suspend, srec);
371185386Sdfr#endif
372185386Sdfr
373185386Sdfr	return rc;
374183906Skmacy}
375183906Skmacy
376183906Skmacy#if CONFIG_XEN_COMPAT <= 0x030002
377183906Skmacystatic inline int
378183906SkmacyHYPERVISOR_nmi_op(
379185386Sdfr	unsigned long op, void *arg)
380183906Skmacy{
381185386Sdfr	return _hypercall2(int, nmi_op, op, arg);
382183906Skmacy}
383183906Skmacy#endif
384183906Skmacy
385183906Skmacy#ifndef CONFIG_XEN
386185386Sdfrstatic inline unsigned long __must_check
387183906SkmacyHYPERVISOR_hvm_op(
388183906Skmacy    int op, void *arg)
389183906Skmacy{
390183906Skmacy    return _hypercall2(unsigned long, hvm_op, op, arg);
391183906Skmacy}
392183906Skmacy#endif
393183906Skmacy
394185386Sdfrstatic inline int __must_check
395185386SdfrHYPERVISOR_callback_op(
396185386Sdfr	int cmd, const void *arg)
397185386Sdfr{
398185386Sdfr	return _hypercall2(int, callback_op, cmd, arg);
399185386Sdfr}
400185386Sdfr
401185386Sdfrstatic inline int __must_check
402183906SkmacyHYPERVISOR_xenoprof_op(
403185386Sdfr	int op, void *arg)
404183906Skmacy{
405185386Sdfr	return _hypercall2(int, xenoprof_op, op, arg);
406183906Skmacy}
407183906Skmacy
408185386Sdfrstatic inline int __must_check
409183906SkmacyHYPERVISOR_kexec_op(
410185386Sdfr	unsigned long op, void *args)
411183906Skmacy{
412185386Sdfr	return _hypercall2(int, kexec_op, op, args);
413183906Skmacy}
414185386Sdfr
415185386Sdfr#undef __must_check
416185386Sdfr
417185637Sdfr#endif /* __MACHINE_XEN_HYPERCALL_H__ */
418