bc0ee7d961ca8d55ac98ebcfb9607a3be920603b
[linux-2.6.git] / include / asm-x86 / xen / hypercall.h
1 /******************************************************************************
2  * hypercall.h
3  *
4  * Linux-specific hypervisor handling.
5  *
6  * Copyright (c) 2002-2004, K A Fraser
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation; or, when distributed
11  * separately from the Linux kernel or incorporated into other
12  * software packages, subject to the following license:
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a copy
15  * of this source file (the "Software"), to deal in the Software without
16  * restriction, including without limitation the rights to use, copy, modify,
17  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18  * and to permit persons to whom the Software is furnished to do so, subject to
19  * the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in
22  * all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * IN THE SOFTWARE.
31  */
32
33 #ifndef __HYPERCALL_H__
34 #define __HYPERCALL_H__
35
36 #include <linux/errno.h>
37 #include <linux/string.h>
38
39 #include <xen/interface/xen.h>
40 #include <xen/interface/sched.h>
41 #include <xen/interface/physdev.h>
42
43 extern struct { char _entry[32]; } hypercall_page[];
44
45 #define _hypercall0(type, name)                                         \
46 ({                                                                      \
47         long __res;                                                     \
48         asm volatile (                                                  \
49                 "call %[call]"                                          \
50                 : "=a" (__res)                                          \
51                 : [call] "m" (hypercall_page[__HYPERVISOR_##name])      \
52                 : "memory" );                                           \
53         (type)__res;                                                    \
54 })
55
56 #define _hypercall1(type, name, a1)                                     \
57 ({                                                                      \
58         long __res, __ign1;                                             \
59         asm volatile (                                                  \
60                 "call %[call]"                                          \
61                 : "=a" (__res), "=b" (__ign1)                           \
62                 : "1" ((long)(a1)),                                     \
63                   [call] "m" (hypercall_page[__HYPERVISOR_##name])      \
64                 : "memory" );                                           \
65         (type)__res;                                                    \
66 })
67
68 #define _hypercall2(type, name, a1, a2)                                 \
69 ({                                                                      \
70         long __res, __ign1, __ign2;                                     \
71         asm volatile (                                                  \
72                 "call %[call]"                                          \
73                 : "=a" (__res), "=b" (__ign1), "=c" (__ign2)            \
74                 : "1" ((long)(a1)), "2" ((long)(a2)),                   \
75                   [call] "m" (hypercall_page[__HYPERVISOR_##name])      \
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                 "call %[call]"                                          \
85                 : "=a" (__res), "=b" (__ign1), "=c" (__ign2),           \
86                 "=d" (__ign3)                                           \
87                 : "1" ((long)(a1)), "2" ((long)(a2)),                   \
88                   "3" ((long)(a3)),                                     \
89                   [call] "m" (hypercall_page[__HYPERVISOR_##name])      \
90                 : "memory" );                                           \
91         (type)__res;                                                    \
92 })
93
94 #define _hypercall4(type, name, a1, a2, a3, a4)                         \
95 ({                                                                      \
96         long __res, __ign1, __ign2, __ign3, __ign4;                     \
97         asm volatile (                                                  \
98                 "call %[call]"                                          \
99                 : "=a" (__res), "=b" (__ign1), "=c" (__ign2),           \
100                 "=d" (__ign3), "=S" (__ign4)                            \
101                 : "1" ((long)(a1)), "2" ((long)(a2)),                   \
102                   "3" ((long)(a3)), "4" ((long)(a4)),                   \
103                   [call] "m" (hypercall_page[__HYPERVISOR_##name])      \
104                 : "memory" );                                           \
105         (type)__res;                                                    \
106 })
107
108 #define _hypercall5(type, name, a1, a2, a3, a4, a5)                     \
109 ({                                                                      \
110         long __res, __ign1, __ign2, __ign3, __ign4, __ign5;             \
111         asm volatile (                                                  \
112                 "call %[call]"                                          \
113                 : "=a" (__res), "=b" (__ign1), "=c" (__ign2),           \
114                 "=d" (__ign3), "=S" (__ign4), "=D" (__ign5)             \
115                 : "1" ((long)(a1)), "2" ((long)(a2)),                   \
116                   "3" ((long)(a3)), "4" ((long)(a4)),                   \
117                   "5" ((long)(a5)),                                     \
118                   [call] "m" (hypercall_page[__HYPERVISOR_##name])      \
119                 : "memory" );                                           \
120         (type)__res;                                                    \
121 })
122
123 static inline int
124 HYPERVISOR_set_trap_table(struct trap_info *table)
125 {
126         return _hypercall1(int, set_trap_table, table);
127 }
128
129 static inline int
130 HYPERVISOR_mmu_update(struct mmu_update *req, int count,
131                       int *success_count, domid_t domid)
132 {
133         return _hypercall4(int, mmu_update, req, count, success_count, domid);
134 }
135
136 static inline int
137 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
138                      int *success_count, domid_t domid)
139 {
140         return _hypercall4(int, mmuext_op, op, count, success_count, domid);
141 }
142
143 static inline int
144 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
145 {
146         return _hypercall2(int, set_gdt, frame_list, entries);
147 }
148
149 static inline int
150 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
151 {
152         return _hypercall2(int, stack_switch, ss, esp);
153 }
154
155 static inline int
156 HYPERVISOR_set_callbacks(unsigned long event_selector,
157                          unsigned long event_address,
158                          unsigned long failsafe_selector,
159                          unsigned long failsafe_address)
160 {
161         return _hypercall4(int, set_callbacks,
162                            event_selector, event_address,
163                            failsafe_selector, failsafe_address);
164 }
165
166 static inline int
167 HYPERVISOR_fpu_taskswitch(int set)
168 {
169         return _hypercall1(int, fpu_taskswitch, set);
170 }
171
172 static inline int
173 HYPERVISOR_sched_op(int cmd, unsigned long arg)
174 {
175         return _hypercall2(int, sched_op, cmd, arg);
176 }
177
178 static inline long
179 HYPERVISOR_set_timer_op(u64 timeout)
180 {
181         unsigned long timeout_hi = (unsigned long)(timeout>>32);
182         unsigned long timeout_lo = (unsigned long)timeout;
183         return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
184 }
185
186 static inline int
187 HYPERVISOR_set_debugreg(int reg, unsigned long value)
188 {
189         return _hypercall2(int, set_debugreg, reg, value);
190 }
191
192 static inline unsigned long
193 HYPERVISOR_get_debugreg(int reg)
194 {
195         return _hypercall1(unsigned long, get_debugreg, reg);
196 }
197
198 static inline int
199 HYPERVISOR_update_descriptor(u64 ma, u64 desc)
200 {
201         return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
202 }
203
204 static inline int
205 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
206 {
207         return _hypercall2(int, memory_op, cmd, arg);
208 }
209
210 static inline int
211 HYPERVISOR_multicall(void *call_list, int nr_calls)
212 {
213         return _hypercall2(int, multicall, call_list, nr_calls);
214 }
215
216 static inline int
217 HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
218                              unsigned long flags)
219 {
220         unsigned long pte_hi = 0;
221 #ifdef CONFIG_X86_PAE
222         pte_hi = new_val.pte_high;
223 #endif
224         return _hypercall4(int, update_va_mapping, va,
225                            new_val.pte_low, pte_hi, flags);
226 }
227
228 static inline int
229 HYPERVISOR_event_channel_op(int cmd, void *arg)
230 {
231         int rc = _hypercall2(int, event_channel_op, cmd, arg);
232         if (unlikely(rc == -ENOSYS)) {
233                 struct evtchn_op op;
234                 op.cmd = cmd;
235                 memcpy(&op.u, arg, sizeof(op.u));
236                 rc = _hypercall1(int, event_channel_op_compat, &op);
237                 memcpy(arg, &op.u, sizeof(op.u));
238         }
239         return rc;
240 }
241
242 static inline int
243 HYPERVISOR_xen_version(int cmd, void *arg)
244 {
245         return _hypercall2(int, xen_version, cmd, arg);
246 }
247
248 static inline int
249 HYPERVISOR_console_io(int cmd, int count, char *str)
250 {
251         return _hypercall3(int, console_io, cmd, count, str);
252 }
253
254 static inline int
255 HYPERVISOR_physdev_op(int cmd, void *arg)
256 {
257         int rc = _hypercall2(int, physdev_op, cmd, arg);
258         if (unlikely(rc == -ENOSYS)) {
259                 struct physdev_op op;
260                 op.cmd = cmd;
261                 memcpy(&op.u, arg, sizeof(op.u));
262                 rc = _hypercall1(int, physdev_op_compat, &op);
263                 memcpy(arg, &op.u, sizeof(op.u));
264         }
265         return rc;
266 }
267
268 static inline int
269 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
270 {
271         return _hypercall3(int, grant_table_op, cmd, uop, count);
272 }
273
274 static inline int
275 HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
276                                          unsigned long flags, domid_t domid)
277 {
278         unsigned long pte_hi = 0;
279 #ifdef CONFIG_X86_PAE
280         pte_hi = new_val.pte_high;
281 #endif
282         return _hypercall5(int, update_va_mapping_otherdomain, va,
283                            new_val.pte_low, pte_hi, flags, domid);
284 }
285
286 static inline int
287 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
288 {
289         return _hypercall2(int, vm_assist, cmd, type);
290 }
291
292 static inline int
293 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
294 {
295         return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
296 }
297
298 static inline int
299 HYPERVISOR_suspend(unsigned long srec)
300 {
301         return _hypercall3(int, sched_op, SCHEDOP_shutdown,
302                            SHUTDOWN_suspend, srec);
303 }
304
305 static inline int
306 HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
307 {
308         return _hypercall2(int, nmi_op, op, arg);
309 }
310
311 static inline void
312 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
313                         pte_t new_val, unsigned long flags)
314 {
315         mcl->op = __HYPERVISOR_update_va_mapping;
316         mcl->args[0] = va;
317 #ifdef CONFIG_X86_PAE
318         mcl->args[1] = new_val.pte_low;
319         mcl->args[2] = new_val.pte_high;
320 #else
321         mcl->args[1] = new_val.pte_low;
322         mcl->args[2] = 0;
323 #endif
324         mcl->args[3] = flags;
325 }
326
327 static inline void
328 MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
329                      void *uop, unsigned int count)
330 {
331         mcl->op = __HYPERVISOR_grant_table_op;
332         mcl->args[0] = cmd;
333         mcl->args[1] = (unsigned long)uop;
334         mcl->args[2] = count;
335 }
336
337 static inline void
338 MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
339                                     pte_t new_val, unsigned long flags,
340                                     domid_t domid)
341 {
342         mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
343         mcl->args[0] = va;
344 #ifdef CONFIG_X86_PAE
345         mcl->args[1] = new_val.pte_low;
346         mcl->args[2] = new_val.pte_high;
347 #else
348         mcl->args[1] = new_val.pte_low;
349         mcl->args[2] = 0;
350 #endif
351         mcl->args[3] = flags;
352         mcl->args[4] = domid;
353 }
354
355 static inline void
356 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
357                         struct desc_struct desc)
358 {
359         mcl->op = __HYPERVISOR_update_descriptor;
360         mcl->args[0] = maddr;
361         mcl->args[1] = maddr >> 32;
362         mcl->args[2] = desc.a;
363         mcl->args[3] = desc.b;
364 }
365
366 static inline void
367 MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
368 {
369         mcl->op = __HYPERVISOR_memory_op;
370         mcl->args[0] = cmd;
371         mcl->args[1] = (unsigned long)arg;
372 }
373
374 static inline void
375 MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
376                  int count, int *success_count, domid_t domid)
377 {
378         mcl->op = __HYPERVISOR_mmu_update;
379         mcl->args[0] = (unsigned long)req;
380         mcl->args[1] = count;
381         mcl->args[2] = (unsigned long)success_count;
382         mcl->args[3] = domid;
383 }
384
385 static inline void
386 MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
387                 int *success_count, domid_t domid)
388 {
389         mcl->op = __HYPERVISOR_mmuext_op;
390         mcl->args[0] = (unsigned long)op;
391         mcl->args[1] = count;
392         mcl->args[2] = (unsigned long)success_count;
393         mcl->args[3] = domid;
394 }
395
396 static inline void
397 MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
398 {
399         mcl->op = __HYPERVISOR_set_gdt;
400         mcl->args[0] = (unsigned long)frames;
401         mcl->args[1] = entries;
402 }
403
404 static inline void
405 MULTI_stack_switch(struct multicall_entry *mcl,
406                    unsigned long ss, unsigned long esp)
407 {
408         mcl->op = __HYPERVISOR_stack_switch;
409         mcl->args[0] = ss;
410         mcl->args[1] = esp;
411 }
412
413 #endif /* __HYPERCALL_H__ */