Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / arch / x86 / include / mach-xen / asm / hypercall.h
1 /******************************************************************************
2  * hypercall.h
3  *
4  * Linux-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
37 #ifndef __HYPERCALL_H__
38 #define __HYPERCALL_H__
39
40 #ifndef __HYPERVISOR_H__
41 # error "please don't include this file directly"
42 #endif
43
44 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
45 # include <xen/interface/platform.h>
46 # include <xen/interface/arch-x86/xen-mca.h>
47 #endif
48 #if CONFIG_XEN_COMPAT <= 0x030002
49 # include <linux/string.h> /* memcpy() */
50 # include <xen/interface/event_channel.h>
51 # include <xen/interface/physdev.h>
52 #endif
53
54 #ifdef CONFIG_XEN
55 #define HYPERCALL_ASM_OPERAND "%c"
56 #define HYPERCALL_LOCATION(op) (hypercall_page + (op) * 32)
57 #define HYPERCALL_C_OPERAND(name) "i" (HYPERCALL_LOCATION(__HYPERVISOR_##name))
58 #else
59 #define HYPERCALL_ASM_OPERAND "*%"
60 #define HYPERCALL_LOCATION(op) (hypercall_stubs + (op) * 32)
61 #define HYPERCALL_C_OPERAND(name) "g" (HYPERCALL_LOCATION(__HYPERVISOR_##name))
62 #endif
63
64 #define HYPERCALL_ARG(arg, n) \
65         register typeof((arg)+0) __arg##n asm(HYPERCALL_arg##n) = (arg)
66
67 #define _hypercall0(type, name)                                 \
68 ({                                                              \
69         type __res;                                             \
70         asm volatile (                                          \
71                 "call " HYPERCALL_ASM_OPERAND "1"               \
72                 : "=a" (__res)                                  \
73                 : HYPERCALL_C_OPERAND(name)                     \
74                 : "memory" );                                   \
75         __res;                                                  \
76 })
77
78 #define _hypercall1(type, name, arg)                            \
79 ({                                                              \
80         type __res;                                             \
81         HYPERCALL_ARG(arg, 1);                                  \
82         asm volatile (                                          \
83                 "call " HYPERCALL_ASM_OPERAND "2"               \
84                 : "=a" (__res), "+r" (__arg1)                   \
85                 : HYPERCALL_C_OPERAND(name)                     \
86                 : "memory" );                                   \
87         __res;                                                  \
88 })
89
90 #define _hypercall2(type, name, a1, a2)                         \
91 ({                                                              \
92         type __res;                                             \
93         HYPERCALL_ARG(a1, 1);                                   \
94         HYPERCALL_ARG(a2, 2);                                   \
95         asm volatile (                                          \
96                 "call " HYPERCALL_ASM_OPERAND "3"               \
97                 : "=a" (__res), "+r" (__arg1), "+r" (__arg2)    \
98                 : HYPERCALL_C_OPERAND(name)                     \
99                 : "memory" );                                   \
100         __res;                                                  \
101 })
102
103 #define _hypercall3(type, name, a1, a2, a3)                     \
104 ({                                                              \
105         type __res;                                             \
106         HYPERCALL_ARG(a1, 1);                                   \
107         HYPERCALL_ARG(a2, 2);                                   \
108         HYPERCALL_ARG(a3, 3);                                   \
109         asm volatile (                                          \
110                 "call " HYPERCALL_ASM_OPERAND "4"               \
111                 : "=a" (__res), "+r" (__arg1),                  \
112                   "+r" (__arg2), "+r" (__arg3)                  \
113                 : HYPERCALL_C_OPERAND(name)                     \
114                 : "memory" );                                   \
115         __res;                                                  \
116 })
117
118 #define _hypercall4(type, name, a1, a2, a3, a4)                 \
119 ({                                                              \
120         type __res;                                             \
121         HYPERCALL_ARG(a1, 1);                                   \
122         HYPERCALL_ARG(a2, 2);                                   \
123         HYPERCALL_ARG(a3, 3);                                   \
124         HYPERCALL_ARG(a4, 4);                                   \
125         asm volatile (                                          \
126                 "call " HYPERCALL_ASM_OPERAND "5"               \
127                 : "=a" (__res), "+r" (__arg1), "+r" (__arg2),   \
128                   "+r" (__arg3), "+r" (__arg4)                  \
129                 : HYPERCALL_C_OPERAND(name)                     \
130                 : "memory" );                                   \
131         __res;                                                  \
132 })
133
134 #define _hypercall5(type, name, a1, a2, a3, a4, a5)             \
135 ({                                                              \
136         type __res;                                             \
137         HYPERCALL_ARG(a1, 1);                                   \
138         HYPERCALL_ARG(a2, 2);                                   \
139         HYPERCALL_ARG(a3, 3);                                   \
140         HYPERCALL_ARG(a4, 4);                                   \
141         HYPERCALL_ARG(a5, 5);                                   \
142         asm volatile (                                          \
143                 "call " HYPERCALL_ASM_OPERAND "6"               \
144                 : "=a" (__res), "+r" (__arg1), "+r" (__arg2),   \
145                   "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)   \
146                 : HYPERCALL_C_OPERAND(name)                     \
147                 : "memory" );                                   \
148         __res;                                                  \
149 })
150
151 #define _hypercall(type, op, a1, a2, a3, a4, a5)                \
152 ({                                                              \
153         type __res;                                             \
154         HYPERCALL_ARG(a1, 1);                                   \
155         HYPERCALL_ARG(a2, 2);                                   \
156         HYPERCALL_ARG(a3, 3);                                   \
157         HYPERCALL_ARG(a4, 4);                                   \
158         HYPERCALL_ARG(a5, 5);                                   \
159         asm volatile (                                          \
160                 "call *%6"                                      \
161                 : "=a" (__res), "+r" (__arg1), "+r" (__arg2),   \
162                   "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)   \
163                 : "g" (HYPERCALL_LOCATION(op))                  \
164                 : "memory" );                                   \
165         __res;                                                  \
166 })
167
168 #ifdef CONFIG_X86_32
169 # include "hypercall_32.h"
170 #else
171 # include "hypercall_64.h"
172 #endif
173
174 static inline int __must_check
175 HYPERVISOR_set_trap_table(
176         const trap_info_t *table)
177 {
178         return _hypercall1(int, set_trap_table, table);
179 }
180
181 static inline int __must_check
182 HYPERVISOR_mmu_update(
183         mmu_update_t *req, unsigned int count, unsigned int *success_count,
184         domid_t domid)
185 {
186         if (arch_use_lazy_mmu_mode())
187                 return xen_multi_mmu_update(req, count, success_count, domid);
188         return _hypercall4(int, mmu_update, req, count, success_count, domid);
189 }
190
191 static inline int __must_check
192 HYPERVISOR_mmuext_op(
193         struct mmuext_op *op, unsigned int count, unsigned int *success_count,
194         domid_t domid)
195 {
196         if (arch_use_lazy_mmu_mode())
197                 return xen_multi_mmuext_op(op, count, success_count, domid);
198         return _hypercall4(int, mmuext_op, op, count, success_count, domid);
199 }
200
201 static inline int __must_check
202 HYPERVISOR_set_gdt(
203         unsigned long *frame_list, unsigned int entries)
204 {
205         return _hypercall2(int, set_gdt, frame_list, entries);
206 }
207
208 static inline int __must_check
209 HYPERVISOR_stack_switch(
210         unsigned long ss, unsigned long esp)
211 {
212         return _hypercall2(int, stack_switch, ss, esp);
213 }
214
215 static inline int
216 HYPERVISOR_fpu_taskswitch(
217         int set)
218 {
219         return _hypercall1(int, fpu_taskswitch, set);
220 }
221
222 #if CONFIG_XEN_COMPAT <= 0x030002
223 static inline int __must_check
224 HYPERVISOR_sched_op_compat(
225         int cmd, unsigned long arg)
226 {
227         return _hypercall2(int, sched_op_compat, cmd, arg);
228 }
229 #endif
230
231 static inline int __must_check
232 HYPERVISOR_sched_op(
233         int cmd, void *arg)
234 {
235         return _hypercall2(int, sched_op, cmd, arg);
236 }
237
238 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
239 static inline int __must_check
240 HYPERVISOR_platform_op(
241         struct xen_platform_op *platform_op)
242 {
243         platform_op->interface_version = XENPF_INTERFACE_VERSION;
244         return _hypercall1(int, platform_op, platform_op);
245 }
246
247 static inline int __must_check
248 HYPERVISOR_mca(
249         struct xen_mc *mc_op)
250 {
251         mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
252         return _hypercall1(int, mca, mc_op);
253 }
254 #endif
255
256 static inline int __must_check
257 HYPERVISOR_set_debugreg(
258         unsigned int reg, unsigned long value)
259 {
260         return _hypercall2(int, set_debugreg, reg, value);
261 }
262
263 static inline unsigned long __must_check
264 HYPERVISOR_get_debugreg(
265         unsigned int reg)
266 {
267         return _hypercall1(unsigned long, get_debugreg, reg);
268 }
269
270 static inline int __must_check
271 HYPERVISOR_memory_op(
272         unsigned int cmd, void *arg)
273 {
274         if (arch_use_lazy_mmu_mode())
275                 xen_multicall_flush();
276         return _hypercall2(int, memory_op, cmd, arg);
277 }
278
279 static inline int __must_check
280 HYPERVISOR_multicall(
281         multicall_entry_t *call_list, unsigned int nr_calls)
282 {
283         return _hypercall2(int, multicall, call_list, nr_calls);
284 }
285
286 static inline int __must_check
287 HYPERVISOR_event_channel_op(
288         int cmd, void *arg)
289 {
290         int rc = _hypercall2(int, event_channel_op, cmd, arg);
291
292 #if CONFIG_XEN_COMPAT <= 0x030002
293         if (unlikely(rc == -ENOSYS)) {
294                 struct evtchn_op op;
295                 op.cmd = cmd;
296                 memcpy(&op.u, arg, sizeof(op.u));
297                 rc = _hypercall1(int, event_channel_op_compat, &op);
298                 memcpy(arg, &op.u, sizeof(op.u));
299         }
300 #endif
301
302         return rc;
303 }
304
305 static inline int __must_check
306 HYPERVISOR_xen_version(
307         int cmd, void *arg)
308 {
309         return _hypercall2(int, xen_version, cmd, arg);
310 }
311
312 static inline int __must_check
313 HYPERVISOR_console_io(
314         int cmd, unsigned int count, char *str)
315 {
316         return _hypercall3(int, console_io, cmd, count, str);
317 }
318
319 static inline int __must_check
320 HYPERVISOR_physdev_op(
321         int cmd, void *arg)
322 {
323         int rc = _hypercall2(int, physdev_op, cmd, arg);
324
325 #if CONFIG_XEN_COMPAT <= 0x030002
326         if (unlikely(rc == -ENOSYS)) {
327                 struct physdev_op op;
328                 op.cmd = cmd;
329                 memcpy(&op.u, arg, sizeof(op.u));
330                 rc = _hypercall1(int, physdev_op_compat, &op);
331                 memcpy(arg, &op.u, sizeof(op.u));
332         }
333 #endif
334
335         return rc;
336 }
337
338 static inline int __must_check
339 HYPERVISOR_grant_table_op(
340         unsigned int cmd, void *uop, unsigned int count)
341 {
342         bool fixup = false;
343         int rc;
344
345         if (arch_use_lazy_mmu_mode())
346                 xen_multicall_flush();
347 #ifdef GNTTABOP_map_grant_ref
348         if (cmd == GNTTABOP_map_grant_ref)
349 #endif
350                 fixup = gnttab_pre_map_adjust(cmd, uop, count);
351         rc = _hypercall3(int, grant_table_op, cmd, uop, count);
352         if (rc == 0 && fixup)
353                 rc = gnttab_post_map_adjust(uop, count);
354         return rc;
355 }
356
357 static inline int __must_check
358 HYPERVISOR_vm_assist(
359         unsigned int cmd, unsigned int type)
360 {
361         return _hypercall2(int, vm_assist, cmd, type);
362 }
363
364 static inline int __must_check
365 HYPERVISOR_vcpu_op(
366         int cmd, unsigned int vcpuid, void *extra_args)
367 {
368         return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
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 == -ENOSYS)
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 struct tmem_op;
431
432 static inline int __must_check
433 HYPERVISOR_tmem_op(
434         struct tmem_op *op)
435 {
436         return _hypercall1(int, tmem_op, (void *)op);
437 }
438
439 #endif /* __HYPERCALL_H__ */