This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / include / asm-x86_64 / 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 #include <linux/string.h> /* memcpy() */
41
42 #ifndef __HYPERVISOR_H__
43 # error "please don't include this file directly"
44 #endif
45
46 #define __STR(x) #x
47 #define STR(x) __STR(x)
48
49 #define _hypercall0(type, name)                 \
50 ({                                              \
51         long __res;                             \
52         asm volatile (                          \
53                 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
54                 : "=a" (__res)                  \
55                 :                               \
56                 : "memory" );                   \
57         (type)__res;                            \
58 })
59
60 #define _hypercall1(type, name, a1)                             \
61 ({                                                              \
62         long __res, __ign1;                                     \
63         asm volatile (                                          \
64                 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
65                 : "=a" (__res), "=D" (__ign1)                   \
66                 : "1" ((long)(a1))                              \
67                 : "memory" );                                   \
68         (type)__res;                                            \
69 })
70
71 #define _hypercall2(type, name, a1, a2)                         \
72 ({                                                              \
73         long __res, __ign1, __ign2;                             \
74         asm volatile (                                          \
75                 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
76                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2)    \
77                 : "1" ((long)(a1)), "2" ((long)(a2))            \
78                 : "memory" );                                   \
79         (type)__res;                                            \
80 })
81
82 #define _hypercall3(type, name, a1, a2, a3)                     \
83 ({                                                              \
84         long __res, __ign1, __ign2, __ign3;                     \
85         asm volatile (                                          \
86                 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
87                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
88                 "=d" (__ign3)                                   \
89                 : "1" ((long)(a1)), "2" ((long)(a2)),           \
90                 "3" ((long)(a3))                                \
91                 : "memory" );                                   \
92         (type)__res;                                            \
93 })
94
95 #define _hypercall4(type, name, a1, a2, a3, a4)                 \
96 ({                                                              \
97         long __res, __ign1, __ign2, __ign3;                     \
98         asm volatile (                                          \
99                 "movq %7,%%r10; "                               \
100                 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
101                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
102                 "=d" (__ign3)                                   \
103                 : "1" ((long)(a1)), "2" ((long)(a2)),           \
104                 "3" ((long)(a3)), "g" ((long)(a4))              \
105                 : "memory", "r10" );                            \
106         (type)__res;                                            \
107 })
108
109 #define _hypercall5(type, name, a1, a2, a3, a4, a5)             \
110 ({                                                              \
111         long __res, __ign1, __ign2, __ign3;                     \
112         asm volatile (                                          \
113                 "movq %7,%%r10; movq %8,%%r8; "                 \
114                 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
115                 : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
116                 "=d" (__ign3)                                   \
117                 : "1" ((long)(a1)), "2" ((long)(a2)),           \
118                 "3" ((long)(a3)), "g" ((long)(a4)),             \
119                 "g" ((long)(a5))                                \
120                 : "memory", "r10", "r8" );                      \
121         (type)__res;                                            \
122 })
123
124 static inline int
125 HYPERVISOR_set_trap_table(
126         trap_info_t *table)
127 {
128         return _hypercall1(int, set_trap_table, table);
129 }
130
131 static inline int
132 HYPERVISOR_mmu_update(
133         mmu_update_t *req, int count, int *success_count, domid_t domid)
134 {
135         return _hypercall4(int, mmu_update, req, count, success_count, domid);
136 }
137
138 static inline int
139 HYPERVISOR_mmuext_op(
140         struct mmuext_op *op, int count, int *success_count, domid_t domid)
141 {
142         return _hypercall4(int, mmuext_op, op, count, success_count, domid);
143 }
144
145 static inline int
146 HYPERVISOR_set_gdt(
147         unsigned long *frame_list, int entries)
148 {
149         return _hypercall2(int, set_gdt, frame_list, entries);
150 }
151
152 static inline int
153 HYPERVISOR_stack_switch(
154         unsigned long ss, unsigned long esp)
155 {
156         return _hypercall2(int, stack_switch, ss, esp);
157 }
158
159 static inline int
160 HYPERVISOR_set_callbacks(
161         unsigned long event_address, unsigned long failsafe_address, 
162         unsigned long syscall_address)
163 {
164         return _hypercall3(int, set_callbacks,
165                            event_address, failsafe_address, syscall_address);
166 }
167
168 static inline int
169 HYPERVISOR_fpu_taskswitch(
170         int set)
171 {
172         return _hypercall1(int, fpu_taskswitch, set);
173 }
174
175 static inline int
176 HYPERVISOR_sched_op_compat(
177         int cmd, unsigned long arg)
178 {
179         return _hypercall2(int, sched_op_compat, cmd, arg);
180 }
181
182 static inline int
183 HYPERVISOR_sched_op(
184         int cmd, void *arg)
185 {
186         return _hypercall2(int, sched_op, cmd, arg);
187 }
188
189 static inline long
190 HYPERVISOR_set_timer_op(
191         u64 timeout)
192 {
193         return _hypercall1(long, set_timer_op, timeout);
194 }
195
196 static inline int
197 HYPERVISOR_dom0_op(
198         dom0_op_t *dom0_op)
199 {
200         dom0_op->interface_version = DOM0_INTERFACE_VERSION;
201         return _hypercall1(int, dom0_op, dom0_op);
202 }
203
204 static inline int
205 HYPERVISOR_set_debugreg(
206         int reg, unsigned long value)
207 {
208         return _hypercall2(int, set_debugreg, reg, value);
209 }
210
211 static inline unsigned long
212 HYPERVISOR_get_debugreg(
213         int reg)
214 {
215         return _hypercall1(unsigned long, get_debugreg, reg);
216 }
217
218 static inline int
219 HYPERVISOR_update_descriptor(
220         unsigned long ma, unsigned long word)
221 {
222         return _hypercall2(int, update_descriptor, ma, word);
223 }
224
225 static inline int
226 HYPERVISOR_memory_op(
227         unsigned int cmd, void *arg)
228 {
229         return _hypercall2(int, memory_op, cmd, arg);
230 }
231
232 static inline int
233 HYPERVISOR_multicall(
234         void *call_list, int nr_calls)
235 {
236         return _hypercall2(int, multicall, call_list, nr_calls);
237 }
238
239 static inline int
240 HYPERVISOR_update_va_mapping(
241         unsigned long va, pte_t new_val, unsigned long flags)
242 {
243         return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
244 }
245
246 static inline int
247 HYPERVISOR_event_channel_op(
248         int cmd, void *arg)
249 {
250         int rc = _hypercall2(int, event_channel_op, cmd, arg);
251         if (unlikely(rc == -ENOSYS)) {
252                 struct evtchn_op op;
253                 op.cmd = cmd;
254                 memcpy(&op.u, arg, sizeof(op.u));
255                 rc = _hypercall1(int, event_channel_op_compat, &op);
256                 memcpy(arg, &op.u, sizeof(op.u));
257         }
258         return rc;
259 }
260
261 static inline int
262 HYPERVISOR_acm_op(
263         int cmd, void *arg)
264 {
265         return _hypercall2(int, acm_op, cmd, arg);
266 }
267
268 static inline int
269 HYPERVISOR_xen_version(
270         int cmd, void *arg)
271 {
272         return _hypercall2(int, xen_version, cmd, arg);
273 }
274
275 static inline int
276 HYPERVISOR_console_io(
277         int cmd, int count, char *str)
278 {
279         return _hypercall3(int, console_io, cmd, count, str);
280 }
281
282 static inline int
283 HYPERVISOR_physdev_op(
284         int cmd, void *arg)
285 {
286         int rc = _hypercall2(int, physdev_op, cmd, arg);
287         if (unlikely(rc == -ENOSYS)) {
288                 struct physdev_op op;
289                 op.cmd = cmd;
290                 memcpy(&op.u, arg, sizeof(op.u));
291                 rc = _hypercall1(int, physdev_op_compat, &op);
292                 memcpy(arg, &op.u, sizeof(op.u));
293         }
294         return rc;
295 }
296
297 static inline int
298 HYPERVISOR_grant_table_op(
299         unsigned int cmd, void *uop, unsigned int count)
300 {
301         return _hypercall3(int, grant_table_op, cmd, uop, count);
302 }
303
304 static inline int
305 HYPERVISOR_update_va_mapping_otherdomain(
306         unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
307 {
308         return _hypercall4(int, update_va_mapping_otherdomain, va,
309                            new_val.pte, flags, domid);
310 }
311
312 static inline int
313 HYPERVISOR_vm_assist(
314         unsigned int cmd, unsigned int type)
315 {
316         return _hypercall2(int, vm_assist, cmd, type);
317 }
318
319 static inline int
320 HYPERVISOR_vcpu_op(
321         int cmd, int vcpuid, void *extra_args)
322 {
323         return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
324 }
325
326 static inline int
327 HYPERVISOR_set_segment_base(
328         int reg, unsigned long value)
329 {
330         return _hypercall2(int, set_segment_base, reg, value);
331 }
332
333 static inline int
334 HYPERVISOR_suspend(
335         unsigned long srec)
336 {
337         struct sched_shutdown sched_shutdown = {
338                 .reason = SHUTDOWN_suspend
339         };
340
341         int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
342                              &sched_shutdown, srec);
343
344         if (rc == -ENOSYS)
345                 rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
346                                  SHUTDOWN_suspend, srec);
347
348         return rc;
349 }
350
351 static inline int
352 HYPERVISOR_nmi_op(
353         unsigned long op, void *arg)
354 {
355         return _hypercall2(int, nmi_op, op, arg);
356 }
357
358 static inline int
359 HYPERVISOR_callback_op(
360         int cmd, void *arg)
361 {
362         return _hypercall2(int, callback_op, cmd, arg);
363 }
364
365 static inline int
366 HYPERVISOR_xenoprof_op(
367         int op, void *arg)
368 {
369         return _hypercall2(int, xenoprof_op, op, arg);
370 }
371
372 #endif /* __HYPERCALL_H__ */