xref: /freebsd/sys/amd64/include/xen/hypercall.h (revision 1719886f6d08408b834d270c59ffcfd821c8f63a)
1 /******************************************************************************
2  * SPDX-License-Identifier: MIT OR GPL-2.0-only
3  *
4  * hypercall.h
5  *
6  * FreeBSD-specific hypervisor handling.
7  *
8  * Copyright (c) 2002-2004, K A Fraser
9  *
10  * 64-bit updates:
11  *   Benjamin Liu <benjamin.liu@intel.com>
12  *   Jun Nakajima <jun.nakajima@intel.com>
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License version 2
16  * as published by the Free Software Foundation; or, when distributed
17  * separately from the Linux kernel or incorporated into other
18  * software packages, subject to the following license:
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining a copy
21  * of this source file (the "Software"), to deal in the Software without
22  * restriction, including without limitation the rights to use, copy, modify,
23  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
24  * and to permit persons to whom the Software is furnished to do so, subject to
25  * the following conditions:
26  *
27  * The above copyright notice and this permission notice shall be included in
28  * all copies or substantial portions of the Software.
29  *
30  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
36  * IN THE SOFTWARE.
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 __must_check
53 
54 #define HYPERCALL_STR(name)					\
55 	"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"
56 
57 #define _hypercall0(type, name)					\
58 ({								\
59 	type __res;						\
60 	__asm__ volatile (					\
61 		HYPERCALL_STR(name)				\
62 		: "=a" (__res)					\
63 		:						\
64 		: "memory" );					\
65 	__res;							\
66 })
67 
68 #define _hypercall1(type, name, a1)				\
69 ({								\
70 	type __res;						\
71 	long __ign1;						\
72 	__asm__ volatile (					\
73 		HYPERCALL_STR(name)				\
74 		: "=a" (__res), "=D" (__ign1)			\
75 		: "1" ((long)(a1))				\
76 		: "memory" );					\
77 	__res;							\
78 })
79 
80 #define _hypercall2(type, name, a1, a2)				\
81 ({								\
82 	type __res;						\
83 	long __ign1, __ign2;					\
84 	__asm__ volatile (					\
85 		HYPERCALL_STR(name)				\
86 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
87 		: "1" ((long)(a1)), "2" ((long)(a2))		\
88 		: "memory" );					\
89 	__res;							\
90 })
91 
92 #define _hypercall3(type, name, a1, a2, a3)			\
93 ({								\
94 	type __res;						\
95 	long __ign1, __ign2, __ign3;				\
96 	__asm__ volatile (					\
97 		HYPERCALL_STR(name)				\
98 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
99 		"=d" (__ign3)					\
100 		: "1" ((long)(a1)), "2" ((long)(a2)),		\
101 		"3" ((long)(a3))				\
102 		: "memory" );					\
103 	__res;							\
104 })
105 
106 #define _hypercall4(type, name, a1, a2, a3, a4)			\
107 ({								\
108 	type __res;						\
109 	long __ign1, __ign2, __ign3;				\
110 	register long __arg4 __asm__("r10") = (long)(a4);	\
111 	__asm__ volatile (					\
112 		HYPERCALL_STR(name)				\
113 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
114 		  "=d" (__ign3), "+r" (__arg4)			\
115 		: "1" ((long)(a1)), "2" ((long)(a2)),		\
116 		  "3" ((long)(a3))				\
117 		: "memory" );					\
118 	__res;							\
119 })
120 
121 #define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
122 ({								\
123 	type __res;						\
124 	long __ign1, __ign2, __ign3;				\
125 	register long __arg4 __asm__("r10") = (long)(a4);	\
126 	register long __arg5 __asm__("r8") = (long)(a5);	\
127 	__asm__ volatile (					\
128 		HYPERCALL_STR(name)				\
129 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
130 		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)	\
131 		: "1" ((long)(a1)), "2" ((long)(a2)),		\
132 		  "3" ((long)(a3))				\
133 		: "memory" );					\
134 	__res;							\
135 })
136 
137 static inline int
138 privcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5)
139 {
140 	int __res;
141 	long __ign1, __ign2, __ign3;
142 	register long __arg4 __asm__("r10") = (long)(a4);
143 	register long __arg5 __asm__("r8") = (long)(a5);
144 	long __call = (long)&hypercall_page + (op * 32);
145 
146 	if (op >= PAGE_SIZE / 32)
147 		return -EINVAL;
148 
149 	__asm__ volatile (
150 		"call *%[call]"
151 		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),
152 		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)
153 		: "1" ((long)(a1)), "2" ((long)(a2)),
154 		  "3" ((long)(a3)), [call] "a" (__call)
155 		: "memory" );
156 
157 	return (__res);
158 }
159 
160 static inline int __must_check
161 HYPERVISOR_set_trap_table(
162 	const trap_info_t *table)
163 {
164 	return _hypercall1(int, set_trap_table, table);
165 }
166 
167 static inline int __must_check
168 HYPERVISOR_mmu_update(
169 	mmu_update_t *req, unsigned int count, unsigned int *success_count,
170 	domid_t domid)
171 {
172 	return _hypercall4(int, mmu_update, req, count, success_count, domid);
173 }
174 
175 static inline int __must_check
176 HYPERVISOR_mmuext_op(
177 	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
178 	domid_t domid)
179 {
180 	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
181 }
182 
183 static inline int __must_check
184 HYPERVISOR_set_gdt(
185 	unsigned long *frame_list, unsigned int entries)
186 {
187 	return _hypercall2(int, set_gdt, frame_list, entries);
188 }
189 
190 static inline int __must_check
191 HYPERVISOR_stack_switch(
192 	unsigned long ss, unsigned long esp)
193 {
194 	return _hypercall2(int, stack_switch, ss, esp);
195 }
196 
197 static inline int __must_check
198 HYPERVISOR_set_callbacks(
199 	unsigned long event_address, unsigned long failsafe_address,
200 	unsigned long syscall_address)
201 {
202 	return _hypercall3(int, set_callbacks,
203 			   event_address, failsafe_address, syscall_address);
204 }
205 
206 static inline int
207 HYPERVISOR_fpu_taskswitch(
208 	int set)
209 {
210 	return _hypercall1(int, fpu_taskswitch, set);
211 }
212 
213 static inline int __must_check
214 HYPERVISOR_sched_op(
215 	int cmd, void *arg)
216 {
217 	return _hypercall2(int, sched_op, cmd, arg);
218 }
219 
220 static inline long __must_check
221 HYPERVISOR_set_timer_op(
222 	uint64_t timeout)
223 {
224 	return _hypercall1(long, set_timer_op, timeout);
225 }
226 
227 static inline int __must_check
228 HYPERVISOR_platform_op(
229 	struct xen_platform_op *platform_op)
230 {
231 	platform_op->interface_version = XENPF_INTERFACE_VERSION;
232 	return _hypercall1(int, platform_op, platform_op);
233 }
234 
235 static inline int __must_check
236 HYPERVISOR_set_debugreg(
237 	unsigned int reg, unsigned long value)
238 {
239 	return _hypercall2(int, set_debugreg, reg, value);
240 }
241 
242 static inline unsigned long __must_check
243 HYPERVISOR_get_debugreg(
244 	unsigned int reg)
245 {
246 	return _hypercall1(unsigned long, get_debugreg, reg);
247 }
248 
249 static inline int __must_check
250 HYPERVISOR_update_descriptor(
251 	unsigned long ma, unsigned long word)
252 {
253 	return _hypercall2(int, update_descriptor, ma, word);
254 }
255 
256 static inline int __must_check
257 HYPERVISOR_memory_op(
258 	unsigned int cmd, void *arg)
259 {
260 	return _hypercall2(int, memory_op, cmd, arg);
261 }
262 
263 static inline int __must_check
264 HYPERVISOR_multicall(
265 	multicall_entry_t *call_list, unsigned int nr_calls)
266 {
267 	return _hypercall2(int, multicall, call_list, nr_calls);
268 }
269 
270 static inline int __must_check
271 HYPERVISOR_update_va_mapping(
272 	unsigned long va, uint64_t new_val, unsigned long flags)
273 {
274 	return _hypercall3(int, update_va_mapping, va, new_val, flags);
275 }
276 
277 static inline int __must_check
278 HYPERVISOR_event_channel_op(
279 	int cmd, void *arg)
280 {
281 	return _hypercall2(int, event_channel_op, cmd, arg);
282 }
283 
284 static inline int __must_check
285 HYPERVISOR_xen_version(
286 	int cmd, void *arg)
287 {
288 	return _hypercall2(int, xen_version, cmd, arg);
289 }
290 
291 static inline int __must_check
292 HYPERVISOR_console_io(
293 	int cmd, unsigned int count, const char *str)
294 {
295 	return _hypercall3(int, console_io, cmd, count, str);
296 }
297 
298 static inline int __must_check
299 HYPERVISOR_physdev_op(
300 	int cmd, void *arg)
301 {
302 	return _hypercall2(int, physdev_op, cmd, arg);
303 }
304 
305 static inline int __must_check
306 HYPERVISOR_grant_table_op(
307 	unsigned int cmd, void *uop, unsigned int count)
308 {
309 	return _hypercall3(int, grant_table_op, cmd, uop, count);
310 }
311 
312 static inline int __must_check
313 HYPERVISOR_update_va_mapping_otherdomain(
314 	unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid)
315 {
316 	return _hypercall4(int, update_va_mapping_otherdomain, va,
317 			   new_val, flags, domid);
318 }
319 
320 static inline int __must_check
321 HYPERVISOR_vm_assist(
322 	unsigned int cmd, unsigned int type)
323 {
324 	return _hypercall2(int, vm_assist, cmd, type);
325 }
326 
327 static inline int __must_check
328 HYPERVISOR_vcpu_op(
329 	int cmd, unsigned int vcpuid, void *extra_args)
330 {
331 	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
332 }
333 
334 static inline int __must_check
335 HYPERVISOR_set_segment_base(
336 	int reg, unsigned long value)
337 {
338 	return _hypercall2(int, set_segment_base, reg, value);
339 }
340 
341 static inline int __must_check
342 HYPERVISOR_suspend(
343 	unsigned long srec)
344 {
345 	struct sched_shutdown sched_shutdown = {
346 		.reason = SHUTDOWN_suspend
347 	};
348 
349 	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
350 			     &sched_shutdown, srec);
351 }
352 
353 static inline unsigned long __must_check
354 HYPERVISOR_hvm_op(
355 	int op, void *arg)
356 {
357 	return _hypercall2(unsigned long, hvm_op, op, arg);
358 }
359 
360 static inline int __must_check
361 HYPERVISOR_callback_op(
362 	int cmd, const void *arg)
363 {
364 	return _hypercall2(int, callback_op, cmd, arg);
365 }
366 
367 static inline int __must_check
368 HYPERVISOR_xenoprof_op(
369 	int op, void *arg)
370 {
371 	return _hypercall2(int, xenoprof_op, op, arg);
372 }
373 
374 static inline int __must_check
375 HYPERVISOR_kexec_op(
376 	unsigned long op, void *args)
377 {
378 	return _hypercall2(int, kexec_op, op, args);
379 }
380 
381 static inline int __must_check
382 HYPERVISOR_dm_op(
383 	domid_t domid, unsigned int nr_bufs, const void *bufs)
384 {
385 	return _hypercall3(int, dm_op, domid, nr_bufs, bufs);
386 }
387 
388 #undef __must_check
389 
390 #endif /* __MACHINE_XEN_HYPERCALL_H__ */
391