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
privcmd_hypercall(long op,long a1,long a2,long a3,long a4,long a5)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
HYPERVISOR_set_trap_table(trap_info_t * table)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
HYPERVISOR_mmu_update(mmu_update_t * req,int count,int * success_count,domid_t domid)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
HYPERVISOR_mmuext_op(mmuext_op_t * op,int count,int * success_count,domid_t domid)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
HYPERVISOR_set_gdt(unsigned long * frame_list,int entries)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
HYPERVISOR_stack_switch(unsigned long ss,unsigned long esp)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
HYPERVISOR_set_callbacks(unsigned long event_selector,unsigned long event_address,unsigned long failsafe_selector,unsigned long failsafe_address)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
HYPERVISOR_fpu_taskswitch(int set)187 HYPERVISOR_fpu_taskswitch(
188 int set)
189 {
190 return _hypercall1(int, fpu_taskswitch, set);
191 }
192
193 static inline int
HYPERVISOR_sched_op(int cmd,void * arg)194 HYPERVISOR_sched_op(
195 int cmd, void *arg)
196 {
197 return _hypercall2(int, sched_op, cmd, arg);
198 }
199
200 static inline long
HYPERVISOR_set_timer_op(uint64_t timeout)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
HYPERVISOR_platform_op(struct xen_platform_op * platform_op)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
HYPERVISOR_set_debugreg(int reg,unsigned long value)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
HYPERVISOR_get_debugreg(int reg)225 HYPERVISOR_get_debugreg(
226 int reg)
227 {
228 return _hypercall1(unsigned long, get_debugreg, reg);
229 }
230
231 static inline int
HYPERVISOR_update_descriptor(uint64_t ma,uint64_t desc)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
HYPERVISOR_memory_op(unsigned int cmd,void * arg)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
HYPERVISOR_multicall(void * call_list,int nr_calls)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
HYPERVISOR_update_va_mapping(unsigned long va,uint64_t new_val,unsigned long flags)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
HYPERVISOR_event_channel_op(int cmd,void * arg)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
HYPERVISOR_xen_version(int cmd,void * arg)273 HYPERVISOR_xen_version(
274 int cmd, void *arg)
275 {
276 return _hypercall2(int, xen_version, cmd, arg);
277 }
278
279 static inline int
HYPERVISOR_console_io(int cmd,int count,const char * str)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
HYPERVISOR_physdev_op(int cmd,void * arg)287 HYPERVISOR_physdev_op(
288 int cmd, void *arg)
289 {
290 return _hypercall2(int, physdev_op, cmd, arg);
291 }
292
293 static inline int
HYPERVISOR_grant_table_op(unsigned int cmd,void * uop,unsigned int count)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
HYPERVISOR_update_va_mapping_otherdomain(unsigned long va,uint64_t new_val,unsigned long flags,domid_t domid)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
HYPERVISOR_vm_assist(unsigned int cmd,unsigned int type)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
HYPERVISOR_vcpu_op(int cmd,int vcpuid,void * extra_args)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
HYPERVISOR_suspend(unsigned long srec)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
HYPERVISOR_callback_op(int cmd,void * arg)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
HYPERVISOR_hvm_op(int op,void * arg)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
HYPERVISOR_xenoprof_op(int op,void * arg)354 HYPERVISOR_xenoprof_op(
355 int op, void *arg)
356 {
357 return _hypercall2(int, xenoprof_op, op, arg);
358 }
359
360 static inline int
HYPERVISOR_kexec_op(unsigned long op,void * args)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
HYPERVISOR_dm_op(domid_t domid,unsigned int nr_bufs,const void * bufs)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