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