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