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
privcmd_hypercall(long op,long a1,long a2,long a3,long a4,long a5)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
HYPERVISOR_set_trap_table(const trap_info_t * table)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
HYPERVISOR_mmu_update(mmu_update_t * req,unsigned int count,unsigned int * success_count,domid_t domid)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
HYPERVISOR_mmuext_op(struct mmuext_op * op,unsigned int count,unsigned int * success_count,domid_t domid)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
HYPERVISOR_set_gdt(unsigned long * frame_list,unsigned int entries)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
HYPERVISOR_stack_switch(unsigned long ss,unsigned long esp)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
HYPERVISOR_set_callbacks(unsigned long event_address,unsigned long failsafe_address,unsigned long syscall_address)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
HYPERVISOR_fpu_taskswitch(int set)207 HYPERVISOR_fpu_taskswitch(
208 int set)
209 {
210 return _hypercall1(int, fpu_taskswitch, set);
211 }
212
213 static inline int __must_check
HYPERVISOR_sched_op(int cmd,void * arg)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
HYPERVISOR_set_timer_op(uint64_t timeout)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
HYPERVISOR_platform_op(struct xen_platform_op * platform_op)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
HYPERVISOR_set_debugreg(unsigned int reg,unsigned long value)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
HYPERVISOR_get_debugreg(unsigned int reg)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
HYPERVISOR_update_descriptor(unsigned long ma,unsigned long word)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
HYPERVISOR_memory_op(unsigned int cmd,void * arg)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
HYPERVISOR_multicall(multicall_entry_t * call_list,unsigned int nr_calls)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
HYPERVISOR_update_va_mapping(unsigned long va,uint64_t new_val,unsigned long flags)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
HYPERVISOR_event_channel_op(int cmd,void * arg)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
HYPERVISOR_xen_version(int cmd,void * arg)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
HYPERVISOR_console_io(int cmd,unsigned int count,const char * str)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
HYPERVISOR_physdev_op(int cmd,void * arg)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
HYPERVISOR_grant_table_op(unsigned int cmd,void * uop,unsigned int count)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
HYPERVISOR_update_va_mapping_otherdomain(unsigned long va,uint64_t new_val,unsigned long flags,domid_t domid)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
HYPERVISOR_vm_assist(unsigned int cmd,unsigned int type)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
HYPERVISOR_vcpu_op(int cmd,unsigned int vcpuid,void * extra_args)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
HYPERVISOR_set_segment_base(int reg,unsigned long value)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
HYPERVISOR_suspend(unsigned long srec)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
HYPERVISOR_hvm_op(int op,void * arg)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
HYPERVISOR_callback_op(int cmd,const void * arg)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
HYPERVISOR_xenoprof_op(int op,void * arg)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
HYPERVISOR_kexec_op(unsigned long op,void * args)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
HYPERVISOR_dm_op(domid_t domid,unsigned int nr_bufs,const void * bufs)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