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