xref: /freebsd/sys/amd64/include/xen/hypercall.h (revision 7aa383846770374466b1dcb2cefd71bde9acf463)
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 
142 static inline int __must_check
143 HYPERVISOR_set_trap_table(
144 	const trap_info_t *table)
145 {
146 	return _hypercall1(int, set_trap_table, table);
147 }
148 
149 static inline int __must_check
150 HYPERVISOR_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 
157 static inline int __must_check
158 HYPERVISOR_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 
165 static inline int __must_check
166 HYPERVISOR_set_gdt(
167 	unsigned long *frame_list, unsigned int entries)
168 {
169 	return _hypercall2(int, set_gdt, frame_list, entries);
170 }
171 
172 static inline int __must_check
173 HYPERVISOR_stack_switch(
174 	unsigned long ss, unsigned long esp)
175 {
176 	return _hypercall2(int, stack_switch, ss, esp);
177 }
178 
179 static inline int __must_check
180 HYPERVISOR_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 
188 static inline int
189 HYPERVISOR_fpu_taskswitch(
190 	int set)
191 {
192 	return _hypercall1(int, fpu_taskswitch, set);
193 }
194 
195 static inline int __must_check
196 HYPERVISOR_sched_op_compat(
197 	int cmd, unsigned long arg)
198 {
199 	return _hypercall2(int, sched_op_compat, cmd, arg);
200 }
201 
202 static inline int __must_check
203 HYPERVISOR_sched_op(
204 	int cmd, void *arg)
205 {
206 	return _hypercall2(int, sched_op, cmd, arg);
207 }
208 
209 static inline long __must_check
210 HYPERVISOR_set_timer_op(
211 	uint64_t timeout)
212 {
213 	return _hypercall1(long, set_timer_op, timeout);
214 }
215 
216 static inline int __must_check
217 HYPERVISOR_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 
224 static inline int __must_check
225 HYPERVISOR_set_debugreg(
226 	unsigned int reg, unsigned long value)
227 {
228 	return _hypercall2(int, set_debugreg, reg, value);
229 }
230 
231 static inline unsigned long __must_check
232 HYPERVISOR_get_debugreg(
233 	unsigned int reg)
234 {
235 	return _hypercall1(unsigned long, get_debugreg, reg);
236 }
237 
238 static inline int __must_check
239 HYPERVISOR_update_descriptor(
240 	unsigned long ma, unsigned long word)
241 {
242 	return _hypercall2(int, update_descriptor, ma, word);
243 }
244 
245 static inline int __must_check
246 HYPERVISOR_memory_op(
247 	unsigned int cmd, void *arg)
248 {
249 	return _hypercall2(int, memory_op, cmd, arg);
250 }
251 
252 static inline int __must_check
253 HYPERVISOR_multicall(
254 	multicall_entry_t *call_list, unsigned int nr_calls)
255 {
256 	return _hypercall2(int, multicall, call_list, nr_calls);
257 }
258 
259 static inline int __must_check
260 HYPERVISOR_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 
266 static inline int __must_check
267 HYPERVISOR_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 
285 static inline int __must_check
286 HYPERVISOR_xen_version(
287 	int cmd, void *arg)
288 {
289 	return _hypercall2(int, xen_version, cmd, arg);
290 }
291 
292 static inline int __must_check
293 HYPERVISOR_console_io(
294 	int cmd, unsigned int count, char *str)
295 {
296 	return _hypercall3(int, console_io, cmd, count, str);
297 }
298 
299 static inline int __must_check
300 HYPERVISOR_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 
318 static inline int __must_check
319 HYPERVISOR_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 
325 static inline int __must_check
326 HYPERVISOR_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 
333 static inline int __must_check
334 HYPERVISOR_vm_assist(
335 	unsigned int cmd, unsigned int type)
336 {
337 	return _hypercall2(int, vm_assist, cmd, type);
338 }
339 
340 static inline int __must_check
341 HYPERVISOR_vcpu_op(
342 	int cmd, unsigned int vcpuid, void *extra_args)
343 {
344 	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
345 }
346 
347 static inline int __must_check
348 HYPERVISOR_set_segment_base(
349 	int reg, unsigned long value)
350 {
351 	return _hypercall2(int, set_segment_base, reg, value);
352 }
353 
354 static inline int __must_check
355 HYPERVISOR_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
375 static inline int
376 HYPERVISOR_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
384 static inline unsigned long __must_check
385 HYPERVISOR_hvm_op(
386     int op, void *arg)
387 {
388     return _hypercall2(unsigned long, hvm_op, op, arg);
389 }
390 #endif
391 
392 static inline int __must_check
393 HYPERVISOR_callback_op(
394 	int cmd, const void *arg)
395 {
396 	return _hypercall2(int, callback_op, cmd, arg);
397 }
398 
399 static inline int __must_check
400 HYPERVISOR_xenoprof_op(
401 	int op, void *arg)
402 {
403 	return _hypercall2(int, xenoprof_op, op, arg);
404 }
405 
406 static inline int __must_check
407 HYPERVISOR_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