Merge branch 'x86/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip...
[pandora-kernel.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_callback_op(int cmd, void *arg)
168 {
169         return _hypercall2(int, callback_op, cmd, arg);
170 }
171
172 static inline int
173 HYPERVISOR_fpu_taskswitch(int set)
174 {
175         return _hypercall1(int, fpu_taskswitch, set);
176 }
177
178 static inline int
179 HYPERVISOR_sched_op(int cmd, void *arg)
180 {
181         return _hypercall2(int, sched_op_new, cmd, arg);
182 }
183
184 static inline long
185 HYPERVISOR_set_timer_op(u64 timeout)
186 {
187         unsigned long timeout_hi = (unsigned long)(timeout>>32);
188         unsigned long timeout_lo = (unsigned long)timeout;
189         return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
190 }
191
192 static inline int
193 HYPERVISOR_set_debugreg(int reg, unsigned long value)
194 {
195         return _hypercall2(int, set_debugreg, reg, value);
196 }
197
198 static inline unsigned long
199 HYPERVISOR_get_debugreg(int reg)
200 {
201         return _hypercall1(unsigned long, get_debugreg, reg);
202 }
203
204 static inline int
205 HYPERVISOR_update_descriptor(u64 ma, u64 desc)
206 {
207         return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
208 }
209
210 static inline int
211 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
212 {
213         return _hypercall2(int, memory_op, cmd, arg);
214 }
215
216 static inline int
217 HYPERVISOR_multicall(void *call_list, int nr_calls)
218 {
219         return _hypercall2(int, multicall, call_list, nr_calls);
220 }
221
222 static inline int
223 HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
224                              unsigned long flags)
225 {
226         unsigned long pte_hi = 0;
227 #ifdef CONFIG_X86_PAE
228         pte_hi = new_val.pte_high;
229 #endif
230         return _hypercall4(int, update_va_mapping, va,
231                            new_val.pte_low, pte_hi, flags);
232 }
233
234 static inline int
235 HYPERVISOR_event_channel_op(int cmd, void *arg)
236 {
237         int rc = _hypercall2(int, event_channel_op, cmd, arg);
238         if (unlikely(rc == -ENOSYS)) {
239                 struct evtchn_op op;
240                 op.cmd = cmd;
241                 memcpy(&op.u, arg, sizeof(op.u));
242                 rc = _hypercall1(int, event_channel_op_compat, &op);
243                 memcpy(arg, &op.u, sizeof(op.u));
244         }
245         return rc;
246 }
247
248 static inline int
249 HYPERVISOR_xen_version(int cmd, void *arg)
250 {
251         return _hypercall2(int, xen_version, cmd, arg);
252 }
253
254 static inline int
255 HYPERVISOR_console_io(int cmd, int count, char *str)
256 {
257         return _hypercall3(int, console_io, cmd, count, str);
258 }
259
260 static inline int
261 HYPERVISOR_physdev_op(int cmd, void *arg)
262 {
263         int rc = _hypercall2(int, physdev_op, cmd, arg);
264         if (unlikely(rc == -ENOSYS)) {
265                 struct physdev_op op;
266                 op.cmd = cmd;
267                 memcpy(&op.u, arg, sizeof(op.u));
268                 rc = _hypercall1(int, physdev_op_compat, &op);
269                 memcpy(arg, &op.u, sizeof(op.u));
270         }
271         return rc;
272 }
273
274 static inline int
275 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
276 {
277         return _hypercall3(int, grant_table_op, cmd, uop, count);
278 }
279
280 static inline int
281 HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
282                                          unsigned long flags, domid_t domid)
283 {
284         unsigned long pte_hi = 0;
285 #ifdef CONFIG_X86_PAE
286         pte_hi = new_val.pte_high;
287 #endif
288         return _hypercall5(int, update_va_mapping_otherdomain, va,
289                            new_val.pte_low, pte_hi, flags, domid);
290 }
291
292 static inline int
293 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
294 {
295         return _hypercall2(int, vm_assist, cmd, type);
296 }
297
298 static inline int
299 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
300 {
301         return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
302 }
303
304 static inline int
305 HYPERVISOR_suspend(unsigned long srec)
306 {
307         return _hypercall3(int, sched_op, SCHEDOP_shutdown,
308                            SHUTDOWN_suspend, srec);
309 }
310
311 static inline int
312 HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
313 {
314         return _hypercall2(int, nmi_op, op, arg);
315 }
316
317 static inline void
318 MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
319 {
320         mcl->op = __HYPERVISOR_fpu_taskswitch;
321         mcl->args[0] = set;
322 }
323
324 static inline void
325 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
326                         pte_t new_val, unsigned long flags)
327 {
328         mcl->op = __HYPERVISOR_update_va_mapping;
329         mcl->args[0] = va;
330 #ifdef CONFIG_X86_PAE
331         mcl->args[1] = new_val.pte_low;
332         mcl->args[2] = new_val.pte_high;
333 #else
334         mcl->args[1] = new_val.pte_low;
335         mcl->args[2] = 0;
336 #endif
337         mcl->args[3] = flags;
338 }
339
340 static inline void
341 MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
342                      void *uop, unsigned int count)
343 {
344         mcl->op = __HYPERVISOR_grant_table_op;
345         mcl->args[0] = cmd;
346         mcl->args[1] = (unsigned long)uop;
347         mcl->args[2] = count;
348 }
349
350 static inline void
351 MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
352                                     pte_t new_val, unsigned long flags,
353                                     domid_t domid)
354 {
355         mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
356         mcl->args[0] = va;
357 #ifdef CONFIG_X86_PAE
358         mcl->args[1] = new_val.pte_low;
359         mcl->args[2] = new_val.pte_high;
360 #else
361         mcl->args[1] = new_val.pte_low;
362         mcl->args[2] = 0;
363 #endif
364         mcl->args[3] = flags;
365         mcl->args[4] = domid;
366 }
367
368 static inline void
369 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
370                         struct desc_struct desc)
371 {
372         mcl->op = __HYPERVISOR_update_descriptor;
373         mcl->args[0] = maddr;
374         mcl->args[1] = maddr >> 32;
375         mcl->args[2] = desc.a;
376         mcl->args[3] = desc.b;
377 }
378
379 static inline void
380 MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
381 {
382         mcl->op = __HYPERVISOR_memory_op;
383         mcl->args[0] = cmd;
384         mcl->args[1] = (unsigned long)arg;
385 }
386
387 static inline void
388 MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
389                  int count, int *success_count, domid_t domid)
390 {
391         mcl->op = __HYPERVISOR_mmu_update;
392         mcl->args[0] = (unsigned long)req;
393         mcl->args[1] = count;
394         mcl->args[2] = (unsigned long)success_count;
395         mcl->args[3] = domid;
396 }
397
398 static inline void
399 MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
400                 int *success_count, domid_t domid)
401 {
402         mcl->op = __HYPERVISOR_mmuext_op;
403         mcl->args[0] = (unsigned long)op;
404         mcl->args[1] = count;
405         mcl->args[2] = (unsigned long)success_count;
406         mcl->args[3] = domid;
407 }
408
409 static inline void
410 MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
411 {
412         mcl->op = __HYPERVISOR_set_gdt;
413         mcl->args[0] = (unsigned long)frames;
414         mcl->args[1] = entries;
415 }
416
417 static inline void
418 MULTI_stack_switch(struct multicall_entry *mcl,
419                    unsigned long ss, unsigned long esp)
420 {
421         mcl->op = __HYPERVISOR_stack_switch;
422         mcl->args[0] = ss;
423         mcl->args[1] = esp;
424 }
425
426 #endif /* __HYPERCALL_H__ */