]> err.no Git - linux-2.6/blob - include/asm-x86/xen/hypercall.h
xen: fix 64-bit hypercall variants
[linux-2.6] / 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         if (sizeof(new_val) == sizeof(long))
227                 return _hypercall3(int, update_va_mapping, va,
228                                    new_val.pte, flags);
229         else
230                 return _hypercall4(int, update_va_mapping, va,
231                                    new_val.pte, new_val.pte >> 32, 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         if (sizeof(new_val) == sizeof(long))
285                 return _hypercall4(int, update_va_mapping_otherdomain, va,
286                                    new_val.pte, flags, domid);
287         else
288                 return _hypercall5(int, update_va_mapping_otherdomain, va,
289                                    new_val.pte, new_val.pte >> 32,
290                                    flags, domid);
291 }
292
293 static inline int
294 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
295 {
296         return _hypercall2(int, vm_assist, cmd, type);
297 }
298
299 static inline int
300 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
301 {
302         return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
303 }
304
305 static inline int
306 HYPERVISOR_suspend(unsigned long srec)
307 {
308         return _hypercall3(int, sched_op, SCHEDOP_shutdown,
309                            SHUTDOWN_suspend, srec);
310 }
311
312 static inline int
313 HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
314 {
315         return _hypercall2(int, nmi_op, op, arg);
316 }
317
318 static inline void
319 MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
320 {
321         mcl->op = __HYPERVISOR_fpu_taskswitch;
322         mcl->args[0] = set;
323 }
324
325 static inline void
326 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
327                         pte_t new_val, unsigned long flags)
328 {
329         mcl->op = __HYPERVISOR_update_va_mapping;
330         mcl->args[0] = va;
331         if (sizeof(new_val) == sizeof(long)) {
332                 mcl->args[1] = new_val.pte;
333                 mcl->args[2] = flags;
334         } else {
335                 mcl->args[1] = new_val.pte;
336                 mcl->args[2] = new_val.pte >> 32;
337                 mcl->args[3] = flags;
338         }
339 }
340
341 static inline void
342 MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
343                      void *uop, unsigned int count)
344 {
345         mcl->op = __HYPERVISOR_grant_table_op;
346         mcl->args[0] = cmd;
347         mcl->args[1] = (unsigned long)uop;
348         mcl->args[2] = count;
349 }
350
351 static inline void
352 MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
353                                     pte_t new_val, unsigned long flags,
354                                     domid_t domid)
355 {
356         mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
357         mcl->args[0] = va;
358         if (sizeof(new_val) == sizeof(long)) {
359                 mcl->args[1] = new_val.pte;
360                 mcl->args[2] = flags;
361                 mcl->args[3] = domid;
362         } else {
363                 mcl->args[1] = new_val.pte;
364                 mcl->args[2] = new_val.pte >> 32;
365                 mcl->args[3] = flags;
366                 mcl->args[4] = domid;
367         }
368 }
369
370 static inline void
371 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
372                         struct desc_struct desc)
373 {
374         mcl->op = __HYPERVISOR_update_descriptor;
375         mcl->args[0] = maddr;
376         mcl->args[1] = maddr >> 32;
377         mcl->args[2] = desc.a;
378         mcl->args[3] = desc.b;
379 }
380
381 static inline void
382 MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
383 {
384         mcl->op = __HYPERVISOR_memory_op;
385         mcl->args[0] = cmd;
386         mcl->args[1] = (unsigned long)arg;
387 }
388
389 static inline void
390 MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
391                  int count, int *success_count, domid_t domid)
392 {
393         mcl->op = __HYPERVISOR_mmu_update;
394         mcl->args[0] = (unsigned long)req;
395         mcl->args[1] = count;
396         mcl->args[2] = (unsigned long)success_count;
397         mcl->args[3] = domid;
398 }
399
400 static inline void
401 MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
402                 int *success_count, domid_t domid)
403 {
404         mcl->op = __HYPERVISOR_mmuext_op;
405         mcl->args[0] = (unsigned long)op;
406         mcl->args[1] = count;
407         mcl->args[2] = (unsigned long)success_count;
408         mcl->args[3] = domid;
409 }
410
411 static inline void
412 MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
413 {
414         mcl->op = __HYPERVISOR_set_gdt;
415         mcl->args[0] = (unsigned long)frames;
416         mcl->args[1] = entries;
417 }
418
419 static inline void
420 MULTI_stack_switch(struct multicall_entry *mcl,
421                    unsigned long ss, unsigned long esp)
422 {
423         mcl->op = __HYPERVISOR_stack_switch;
424         mcl->args[0] = ss;
425         mcl->args[1] = esp;
426 }
427
428 #endif /* __HYPERCALL_H__ */