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