xref: /freebsd/sys/amd64/include/xen/hypercall.h (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
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 	if (op >= PAGE_SIZE / 32)
149 		return -EINVAL;
150 
151 	__asm__ volatile (
152 		"call *%[call]"
153 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),
154 		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)
155 		: "1" ((long)(a1)), "2" ((long)(a2)),
156 		  "3" ((long)(a3)), [call] "a" (__call)
157 		: "memory" );
158 
159 	return (__res);
160 }
161 
162 static inline int __must_check
163 HYPERVISOR_set_trap_table(
164 	const trap_info_t *table)
165 {
166 	return _hypercall1(int, set_trap_table, table);
167 }
168 
169 static inline int __must_check
170 HYPERVISOR_mmu_update(
171 	mmu_update_t *req, unsigned int count, unsigned int *success_count,
172 	domid_t domid)
173 {
174 	return _hypercall4(int, mmu_update, req, count, success_count, domid);
175 }
176 
177 static inline int __must_check
178 HYPERVISOR_mmuext_op(
179 	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
180 	domid_t domid)
181 {
182 	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
183 }
184 
185 static inline int __must_check
186 HYPERVISOR_set_gdt(
187 	unsigned long *frame_list, unsigned int entries)
188 {
189 	return _hypercall2(int, set_gdt, frame_list, entries);
190 }
191 
192 static inline int __must_check
193 HYPERVISOR_stack_switch(
194 	unsigned long ss, unsigned long esp)
195 {
196 	return _hypercall2(int, stack_switch, ss, esp);
197 }
198 
199 static inline int __must_check
200 HYPERVISOR_set_callbacks(
201 	unsigned long event_address, unsigned long failsafe_address,
202 	unsigned long syscall_address)
203 {
204 	return _hypercall3(int, set_callbacks,
205 			   event_address, failsafe_address, syscall_address);
206 }
207 
208 static inline int
209 HYPERVISOR_fpu_taskswitch(
210 	int set)
211 {
212 	return _hypercall1(int, fpu_taskswitch, set);
213 }
214 
215 static inline int __must_check
216 HYPERVISOR_sched_op_compat(
217 	int cmd, unsigned long arg)
218 {
219 	return _hypercall2(int, sched_op_compat, cmd, arg);
220 }
221 
222 static inline int __must_check
223 HYPERVISOR_sched_op(
224 	int cmd, void *arg)
225 {
226 	return _hypercall2(int, sched_op, cmd, arg);
227 }
228 
229 static inline long __must_check
230 HYPERVISOR_set_timer_op(
231 	uint64_t timeout)
232 {
233 	return _hypercall1(long, set_timer_op, timeout);
234 }
235 
236 static inline int __must_check
237 HYPERVISOR_platform_op(
238 	struct xen_platform_op *platform_op)
239 {
240 	platform_op->interface_version = XENPF_INTERFACE_VERSION;
241 	return _hypercall1(int, platform_op, platform_op);
242 }
243 
244 static inline int __must_check
245 HYPERVISOR_set_debugreg(
246 	unsigned int reg, unsigned long value)
247 {
248 	return _hypercall2(int, set_debugreg, reg, value);
249 }
250 
251 static inline unsigned long __must_check
252 HYPERVISOR_get_debugreg(
253 	unsigned int reg)
254 {
255 	return _hypercall1(unsigned long, get_debugreg, reg);
256 }
257 
258 static inline int __must_check
259 HYPERVISOR_update_descriptor(
260 	unsigned long ma, unsigned long word)
261 {
262 	return _hypercall2(int, update_descriptor, ma, word);
263 }
264 
265 static inline int __must_check
266 HYPERVISOR_memory_op(
267 	unsigned int cmd, void *arg)
268 {
269 	return _hypercall2(int, memory_op, cmd, arg);
270 }
271 
272 static inline int __must_check
273 HYPERVISOR_multicall(
274 	multicall_entry_t *call_list, unsigned int nr_calls)
275 {
276 	return _hypercall2(int, multicall, call_list, nr_calls);
277 }
278 
279 static inline int __must_check
280 HYPERVISOR_update_va_mapping(
281 	unsigned long va, uint64_t new_val, unsigned long flags)
282 {
283 	return _hypercall3(int, update_va_mapping, va, new_val, flags);
284 }
285 
286 static inline int __must_check
287 HYPERVISOR_event_channel_op(
288 	int cmd, void *arg)
289 {
290 	int rc = _hypercall2(int, event_channel_op, cmd, arg);
291 
292 #if CONFIG_XEN_COMPAT <= 0x030002
293 	if (__predict_false(rc == -ENOXENSYS)) {
294 		struct evtchn_op op;
295 		op.cmd = cmd;
296 		memcpy(&op.u, arg, sizeof(op.u));
297 		rc = _hypercall1(int, event_channel_op_compat, &op);
298 		memcpy(arg, &op.u, sizeof(op.u));
299 	}
300 #endif
301 
302 	return rc;
303 }
304 
305 static inline int __must_check
306 HYPERVISOR_xen_version(
307 	int cmd, void *arg)
308 {
309 	return _hypercall2(int, xen_version, cmd, arg);
310 }
311 
312 static inline int __must_check
313 HYPERVISOR_console_io(
314 	int cmd, unsigned int count, const char *str)
315 {
316 	return _hypercall3(int, console_io, cmd, count, str);
317 }
318 
319 static inline int __must_check
320 HYPERVISOR_physdev_op(
321 	int cmd, void *arg)
322 {
323 	int rc = _hypercall2(int, physdev_op, cmd, arg);
324 
325 #if CONFIG_XEN_COMPAT <= 0x030002
326 	if (__predict_false(rc == -ENOXENSYS)) {
327 		struct physdev_op op;
328 		op.cmd = cmd;
329 		memcpy(&op.u, arg, sizeof(op.u));
330 		rc = _hypercall1(int, physdev_op_compat, &op);
331 		memcpy(arg, &op.u, sizeof(op.u));
332 	}
333 #endif
334 
335 	return rc;
336 }
337 
338 static inline int __must_check
339 HYPERVISOR_grant_table_op(
340 	unsigned int cmd, void *uop, unsigned int count)
341 {
342 	return _hypercall3(int, grant_table_op, cmd, uop, count);
343 }
344 
345 static inline int __must_check
346 HYPERVISOR_update_va_mapping_otherdomain(
347 	unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid)
348 {
349 	return _hypercall4(int, update_va_mapping_otherdomain, va,
350 			   new_val, flags, domid);
351 }
352 
353 static inline int __must_check
354 HYPERVISOR_vm_assist(
355 	unsigned int cmd, unsigned int type)
356 {
357 	return _hypercall2(int, vm_assist, cmd, type);
358 }
359 
360 static inline int __must_check
361 HYPERVISOR_vcpu_op(
362 	int cmd, unsigned int vcpuid, void *extra_args)
363 {
364 	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
365 }
366 
367 static inline int __must_check
368 HYPERVISOR_set_segment_base(
369 	int reg, unsigned long value)
370 {
371 	return _hypercall2(int, set_segment_base, reg, value);
372 }
373 
374 static inline int __must_check
375 HYPERVISOR_suspend(
376 	unsigned long srec)
377 {
378 	struct sched_shutdown sched_shutdown = {
379 		.reason = SHUTDOWN_suspend
380 	};
381 
382 	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
383 			     &sched_shutdown, srec);
384 
385 #if CONFIG_XEN_COMPAT <= 0x030002
386 	if (rc == -ENOXENSYS)
387 		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
388 				 SHUTDOWN_suspend, srec);
389 #endif
390 
391 	return rc;
392 }
393 
394 #if CONFIG_XEN_COMPAT <= 0x030002
395 static inline int
396 HYPERVISOR_nmi_op(
397 	unsigned long op, void *arg)
398 {
399 	return _hypercall2(int, nmi_op, op, arg);
400 }
401 #endif
402 
403 #ifndef CONFIG_XEN
404 static inline unsigned long __must_check
405 HYPERVISOR_hvm_op(
406     int op, void *arg)
407 {
408     return _hypercall2(unsigned long, hvm_op, op, arg);
409 }
410 #endif
411 
412 static inline int __must_check
413 HYPERVISOR_callback_op(
414 	int cmd, const void *arg)
415 {
416 	return _hypercall2(int, callback_op, cmd, arg);
417 }
418 
419 static inline int __must_check
420 HYPERVISOR_xenoprof_op(
421 	int op, void *arg)
422 {
423 	return _hypercall2(int, xenoprof_op, op, arg);
424 }
425 
426 static inline int __must_check
427 HYPERVISOR_kexec_op(
428 	unsigned long op, void *args)
429 {
430 	return _hypercall2(int, kexec_op, op, args);
431 }
432 
433 static inline int __must_check
434 HYPERVISOR_dm_op(
435 	domid_t domid, unsigned int nr_bufs, const void *bufs)
436 {
437 	return _hypercall3(int, dm_op, domid, nr_bufs, bufs);
438 }
439 
440 #undef __must_check
441 
442 #endif /* __MACHINE_XEN_HYPERCALL_H__ */
443