]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/include/xen/hypercall.h
MFV ntp-4.2.8p4 (r289715)
[FreeBSD/FreeBSD.git] / sys / amd64 / include / xen / hypercall.h
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 <benjamin.liu@intel.com>
10  *   Jun Nakajima <jun.nakajima@intel.com>
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  * $FreeBSD$
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 ENOXENSYS       38
53 #define CONFIG_XEN_COMPAT       0x030002
54 #define __must_check
55
56 #define HYPERCALL_STR(name)                                     \
57         "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"
58
59 #define _hypercall0(type, name)                 \
60 ({                                              \
61         type __res;                             \
62         __asm__ volatile (                              \
63                 HYPERCALL_STR(name)             \
64                 : "=a" (__res)                  \
65                 :                               \
66                 : "memory" );                   \
67         __res;                                  \
68 })
69
70 #define _hypercall1(type, name, a1)                             \
71 ({                                                              \
72         type __res;                                             \
73         long __ign1;                                            \
74         __asm__ volatile (                                              \
75                 HYPERCALL_STR(name)                             \
76                 : "=a" (__res), "=D" (__ign1)                   \
77                 : "1" ((long)(a1))                              \
78                 : "memory" );                                   \
79         __res;                                                  \
80 })
81
82 #define _hypercall2(type, name, a1, a2)                         \
83 ({                                                              \
84         type __res;                                             \
85         long __ign1, __ign2;                                    \
86         __asm__ volatile (                                              \
87                 HYPERCALL_STR(name)                             \
88                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2)    \
89                 : "1" ((long)(a1)), "2" ((long)(a2))            \
90                 : "memory" );                                   \
91         __res;                                                  \
92 })
93
94 #define _hypercall3(type, name, a1, a2, a3)                     \
95 ({                                                              \
96         type __res;                                             \
97         long __ign1, __ign2, __ign3;                            \
98         __asm__ volatile (                                              \
99                 HYPERCALL_STR(name)                             \
100                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
101                 "=d" (__ign3)                                   \
102                 : "1" ((long)(a1)), "2" ((long)(a2)),           \
103                 "3" ((long)(a3))                                \
104                 : "memory" );                                   \
105         __res;                                                  \
106 })
107
108 #define _hypercall4(type, name, a1, a2, a3, a4)                 \
109 ({                                                              \
110         type __res;                                             \
111         long __ign1, __ign2, __ign3;                            \
112         register long __arg4 __asm__("r10") = (long)(a4);               \
113         __asm__ volatile (                                              \
114                 HYPERCALL_STR(name)                             \
115                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
116                   "=d" (__ign3), "+r" (__arg4)                  \
117                 : "1" ((long)(a1)), "2" ((long)(a2)),           \
118                   "3" ((long)(a3))                              \
119                 : "memory" );                                   \
120         __res;                                                  \
121 })
122
123 #define _hypercall5(type, name, a1, a2, a3, a4, a5)             \
124 ({                                                              \
125         type __res;                                             \
126         long __ign1, __ign2, __ign3;                            \
127         register long __arg4 __asm__("r10") = (long)(a4);               \
128         register long __arg5 __asm__("r8") = (long)(a5);                \
129         __asm__ volatile (                                              \
130                 HYPERCALL_STR(name)                             \
131                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
132                   "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)   \
133                 : "1" ((long)(a1)), "2" ((long)(a2)),           \
134                   "3" ((long)(a3))                              \
135                 : "memory" );                                   \
136         __res;                                                  \
137 })
138
139 static inline int
140 privcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5)
141 {
142         int __res;
143         long __ign1, __ign2, __ign3;
144         register long __arg4 __asm__("r10") = (long)(a4);
145         register long __arg5 __asm__("r8") = (long)(a5);
146         long __call = (long)&hypercall_page + (op * 32);
147
148         __asm__ volatile (
149                 "call *%[call]"
150                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2),
151                   "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)
152                 : "1" ((long)(a1)), "2" ((long)(a2)),
153                   "3" ((long)(a3)), [call] "a" (__call)
154                 : "memory" );
155
156         return (__res);
157 }
158
159 static inline int __must_check
160 HYPERVISOR_set_trap_table(
161         const trap_info_t *table)
162 {
163         return _hypercall1(int, set_trap_table, table);
164 }
165
166 static inline int __must_check
167 HYPERVISOR_mmu_update(
168         mmu_update_t *req, unsigned int count, unsigned int *success_count,
169         domid_t domid)
170 {
171         return _hypercall4(int, mmu_update, req, count, success_count, domid);
172 }
173
174 static inline int __must_check
175 HYPERVISOR_mmuext_op(
176         struct mmuext_op *op, unsigned int count, unsigned int *success_count,
177         domid_t domid)
178 {
179         return _hypercall4(int, mmuext_op, op, count, success_count, domid);
180 }
181
182 static inline int __must_check
183 HYPERVISOR_set_gdt(
184         unsigned long *frame_list, unsigned int entries)
185 {
186         return _hypercall2(int, set_gdt, frame_list, entries);
187 }
188
189 static inline int __must_check
190 HYPERVISOR_stack_switch(
191         unsigned long ss, unsigned long esp)
192 {
193         return _hypercall2(int, stack_switch, ss, esp);
194 }
195
196 static inline int __must_check
197 HYPERVISOR_set_callbacks(
198         unsigned long event_address, unsigned long failsafe_address, 
199         unsigned long syscall_address)
200 {
201         return _hypercall3(int, set_callbacks,
202                            event_address, failsafe_address, syscall_address);
203 }
204
205 static inline int
206 HYPERVISOR_fpu_taskswitch(
207         int set)
208 {
209         return _hypercall1(int, fpu_taskswitch, set);
210 }
211
212 static inline int __must_check
213 HYPERVISOR_sched_op_compat(
214         int cmd, unsigned long arg)
215 {
216         return _hypercall2(int, sched_op_compat, cmd, arg);
217 }
218
219 static inline int __must_check
220 HYPERVISOR_sched_op(
221         int cmd, void *arg)
222 {
223         return _hypercall2(int, sched_op, cmd, arg);
224 }
225
226 static inline long __must_check
227 HYPERVISOR_set_timer_op(
228         uint64_t timeout)
229 {
230         return _hypercall1(long, set_timer_op, timeout);
231 }
232
233 static inline int __must_check
234 HYPERVISOR_platform_op(
235         struct xen_platform_op *platform_op)
236 {
237         platform_op->interface_version = XENPF_INTERFACE_VERSION;
238         return _hypercall1(int, platform_op, platform_op);
239 }
240
241 static inline int __must_check
242 HYPERVISOR_set_debugreg(
243         unsigned int reg, unsigned long value)
244 {
245         return _hypercall2(int, set_debugreg, reg, value);
246 }
247
248 static inline unsigned long __must_check
249 HYPERVISOR_get_debugreg(
250         unsigned int reg)
251 {
252         return _hypercall1(unsigned long, get_debugreg, reg);
253 }
254
255 static inline int __must_check
256 HYPERVISOR_update_descriptor(
257         unsigned long ma, unsigned long word)
258 {
259         return _hypercall2(int, update_descriptor, ma, word);
260 }
261
262 static inline int __must_check
263 HYPERVISOR_memory_op(
264         unsigned int cmd, void *arg)
265 {
266         return _hypercall2(int, memory_op, cmd, arg);
267 }
268
269 static inline int __must_check
270 HYPERVISOR_multicall(
271         multicall_entry_t *call_list, unsigned int nr_calls)
272 {
273         return _hypercall2(int, multicall, call_list, nr_calls);
274 }
275
276 static inline int __must_check
277 HYPERVISOR_update_va_mapping(
278         unsigned long va, uint64_t new_val, unsigned long flags)
279 {
280         return _hypercall3(int, update_va_mapping, va, new_val, flags);
281 }
282
283 static inline int __must_check
284 HYPERVISOR_event_channel_op(
285         int cmd, void *arg)
286 {
287         int rc = _hypercall2(int, event_channel_op, cmd, arg);
288
289 #if CONFIG_XEN_COMPAT <= 0x030002
290         if (__predict_false(rc == -ENOXENSYS)) {
291                 struct evtchn_op op;
292                 op.cmd = cmd;
293                 memcpy(&op.u, arg, sizeof(op.u));
294                 rc = _hypercall1(int, event_channel_op_compat, &op);
295                 memcpy(arg, &op.u, sizeof(op.u));
296         }
297 #endif
298
299         return rc;
300 }
301
302 static inline int __must_check
303 HYPERVISOR_xen_version(
304         int cmd, void *arg)
305 {
306         return _hypercall2(int, xen_version, cmd, arg);
307 }
308
309 static inline int __must_check
310 HYPERVISOR_console_io(
311         int cmd, unsigned int count, const char *str)
312 {
313         return _hypercall3(int, console_io, cmd, count, str);
314 }
315
316 static inline int __must_check
317 HYPERVISOR_physdev_op(
318         int cmd, void *arg)
319 {
320         int rc = _hypercall2(int, physdev_op, cmd, arg);
321
322 #if CONFIG_XEN_COMPAT <= 0x030002
323         if (__predict_false(rc == -ENOXENSYS)) {
324                 struct physdev_op op;
325                 op.cmd = cmd;
326                 memcpy(&op.u, arg, sizeof(op.u));
327                 rc = _hypercall1(int, physdev_op_compat, &op);
328                 memcpy(arg, &op.u, sizeof(op.u));
329         }
330 #endif
331
332         return rc;
333 }
334
335 static inline int __must_check
336 HYPERVISOR_grant_table_op(
337         unsigned int cmd, void *uop, unsigned int count)
338 {
339         return _hypercall3(int, grant_table_op, cmd, uop, count);
340 }
341
342 static inline int __must_check
343 HYPERVISOR_update_va_mapping_otherdomain(
344         unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid)
345 {
346         return _hypercall4(int, update_va_mapping_otherdomain, va,
347                            new_val, flags, domid);
348 }
349
350 static inline int __must_check
351 HYPERVISOR_vm_assist(
352         unsigned int cmd, unsigned int type)
353 {
354         return _hypercall2(int, vm_assist, cmd, type);
355 }
356
357 static inline int __must_check
358 HYPERVISOR_vcpu_op(
359         int cmd, unsigned int vcpuid, void *extra_args)
360 {
361         return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
362 }
363
364 static inline int __must_check
365 HYPERVISOR_set_segment_base(
366         int reg, unsigned long value)
367 {
368         return _hypercall2(int, set_segment_base, reg, value);
369 }
370
371 static inline int __must_check
372 HYPERVISOR_suspend(
373         unsigned long srec)
374 {
375         struct sched_shutdown sched_shutdown = {
376                 .reason = SHUTDOWN_suspend
377         };
378
379         int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
380                              &sched_shutdown, srec);
381
382 #if CONFIG_XEN_COMPAT <= 0x030002
383         if (rc == -ENOXENSYS)
384                 rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
385                                  SHUTDOWN_suspend, srec);
386 #endif
387
388         return rc;
389 }
390
391 #if CONFIG_XEN_COMPAT <= 0x030002
392 static inline int
393 HYPERVISOR_nmi_op(
394         unsigned long op, void *arg)
395 {
396         return _hypercall2(int, nmi_op, op, arg);
397 }
398 #endif
399
400 #ifndef CONFIG_XEN
401 static inline unsigned long __must_check
402 HYPERVISOR_hvm_op(
403     int op, void *arg)
404 {
405     return _hypercall2(unsigned long, hvm_op, op, arg);
406 }
407 #endif
408
409 static inline int __must_check
410 HYPERVISOR_callback_op(
411         int cmd, const void *arg)
412 {
413         return _hypercall2(int, callback_op, cmd, arg);
414 }
415
416 static inline int __must_check
417 HYPERVISOR_xenoprof_op(
418         int op, void *arg)
419 {
420         return _hypercall2(int, xenoprof_op, op, arg);
421 }
422
423 static inline int __must_check
424 HYPERVISOR_kexec_op(
425         unsigned long op, void *args)
426 {
427         return _hypercall2(int, kexec_op, op, args);
428 }
429
430 #undef __must_check
431
432 #endif /* __MACHINE_XEN_HYPERCALL_H__ */