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