This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / include / asm-ia64 / 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/string.h> /* memcpy() */
37
38 #ifndef __HYPERVISOR_H__
39 # error "please don't include this file directly"
40 #endif
41
42 /*
43  * Assembler stubs for hyper-calls.
44  */
45
46 #define _hypercall0(type, name)                                 \
47 ({                                                              \
48         long __res;                                             \
49         __asm__ __volatile__ (";;\n"                            \
50                               "mov r2=%1\n"                     \
51                               "break 0x1000 ;;\n"               \
52                               "mov %0=r8 ;;\n"                  \
53                               : "=r" (__res)                    \
54                               : "J" (__HYPERVISOR_##name)       \
55                               : "r2","r8",                      \
56                                 "memory" );                     \
57         (type)__res;                                            \
58 })
59
60 #define _hypercall1(type, name, a1)                             \
61 ({                                                              \
62         long __res;                                             \
63         __asm__ __volatile__ (";;\n"                            \
64                               "mov r14=%2\n"                    \
65                               "mov r2=%1\n"                     \
66                               "break 0x1000 ;;\n"               \
67                               "mov %0=r8 ;;\n"                  \
68                               : "=r" (__res)                    \
69                               : "J" (__HYPERVISOR_##name),      \
70                                 "rI" ((unsigned long)(a1))      \
71                               : "r14","r2","r8",                \
72                                 "memory" );                     \
73         (type)__res;                                            \
74 })
75
76 #define _hypercall2(type, name, a1, a2)                         \
77 ({                                                              \
78         long __res;                                             \
79         __asm__ __volatile__ (";;\n"                            \
80                               "mov r14=%2\n"                    \
81                               "mov r15=%3\n"                    \
82                               "mov r2=%1\n"                     \
83                               "break 0x1000 ;;\n"               \
84                               "mov %0=r8 ;;\n"                  \
85                               : "=r" (__res)                    \
86                               : "J" (__HYPERVISOR_##name),      \
87                                 "rI" ((unsigned long)(a1)),     \
88                                 "rI" ((unsigned long)(a2))      \
89                               : "r14","r15","r2","r8",          \
90                                 "memory" );                     \
91         (type)__res;                                            \
92 })
93
94 #define _hypercall3(type, name, a1, a2, a3)                     \
95 ({                                                              \
96         long __res;                                             \
97         __asm__ __volatile__ (";;\n"                            \
98                               "mov r14=%2\n"                    \
99                               "mov r15=%3\n"                    \
100                               "mov r16=%4\n"                    \
101                               "mov r2=%1\n"                     \
102                               "break 0x1000 ;;\n"               \
103                               "mov %0=r8 ;;\n"                  \
104                               : "=r" (__res)                    \
105                               : "J" (__HYPERVISOR_##name),      \
106                                 "rI" ((unsigned long)(a1)),     \
107                                 "rI" ((unsigned long)(a2)),     \
108                                 "rI" ((unsigned long)(a3))      \
109                               : "r14","r15","r16","r2","r8",    \
110                                 "memory" );                     \
111         (type)__res;                                            \
112 })
113
114 #define _hypercall4(type, name, a1, a2, a3, a4)                 \
115 ({                                                              \
116         long __res;                                             \
117         __asm__ __volatile__ (";;\n"                            \
118                               "mov r14=%2\n"                    \
119                               "mov r15=%3\n"                    \
120                               "mov r16=%4\n"                    \
121                               "mov r17=%5\n"                    \
122                               "mov r2=%1\n"                     \
123                               "break 0x1000 ;;\n"               \
124                               "mov %0=r8 ;;\n"                  \
125                               : "=r" (__res)                    \
126                               : "J" (__HYPERVISOR_##name),      \
127                                 "rI" ((unsigned long)(a1)),     \
128                                 "rI" ((unsigned long)(a2)),     \
129                                 "rI" ((unsigned long)(a3)),     \
130                                 "rI" ((unsigned long)(a4))      \
131                               : "r14","r15","r16","r2","r8",    \
132                                 "r17","memory" );               \
133         (type)__res;                                            \
134 })
135
136 #define _hypercall5(type, name, a1, a2, a3, a4, a5)             \
137 ({                                                              \
138         long __res;                                             \
139         __asm__ __volatile__ (";;\n"                            \
140                               "mov r14=%2\n"                    \
141                               "mov r15=%3\n"                    \
142                               "mov r16=%4\n"                    \
143                               "mov r17=%5\n"                    \
144                               "mov r18=%6\n"                    \
145                               "mov r2=%1\n"                     \
146                               "break 0x1000 ;;\n"               \
147                               "mov %0=r8 ;;\n"                  \
148                               : "=r" (__res)                    \
149                               : "J" (__HYPERVISOR_##name),      \
150                                 "rI" ((unsigned long)(a1)),     \
151                                 "rI" ((unsigned long)(a2)),     \
152                                 "rI" ((unsigned long)(a3)),     \
153                                 "rI" ((unsigned long)(a4)),     \
154                                 "rI" ((unsigned long)(a5))      \
155                               : "r14","r15","r16","r2","r8",    \
156                                 "r17","r18","memory" );         \
157         (type)__res;                                            \
158 })
159
160 static inline int
161 HYPERVISOR_sched_op_compat(
162     int cmd, unsigned long arg)
163 {
164         return _hypercall2(int, sched_op_compat, cmd, arg);
165 }
166
167 static inline int
168 HYPERVISOR_sched_op(
169         int cmd, void *arg)
170 {
171         return _hypercall2(int, sched_op, cmd, arg);
172 }
173
174 static inline long
175 HYPERVISOR_set_timer_op(
176     u64 timeout)
177 {
178     unsigned long timeout_hi = (unsigned long)(timeout>>32);
179     unsigned long timeout_lo = (unsigned long)timeout;
180     return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
181 }
182
183 static inline int
184 HYPERVISOR_dom0_op(
185     dom0_op_t *dom0_op)
186 {
187     dom0_op->interface_version = DOM0_INTERFACE_VERSION;
188     return _hypercall1(int, dom0_op, dom0_op);
189 }
190
191 static inline int
192 HYPERVISOR_multicall(
193     void *call_list, int nr_calls)
194 {
195     return _hypercall2(int, multicall, call_list, nr_calls);
196 }
197
198 //XXX xen/ia64 copy_from_guest() is broken.
199 //    This is a temporal work around until it is fixed.
200 static inline int
201 ____HYPERVISOR_memory_op(
202     unsigned int cmd, void *arg)
203 {
204     return _hypercall2(int, memory_op, cmd, arg);
205 }
206
207 #include <xen/interface/memory.h>
208 #ifdef CONFIG_VMX_GUEST
209 # define ia64_xenmem_reservation_op(op, xmr) (0)
210 #else
211 int ia64_xenmem_reservation_op(unsigned long op,
212                    struct xen_memory_reservation* reservation__);
213 #endif
214 static inline int
215 HYPERVISOR_memory_op(
216     unsigned int cmd, void *arg)
217 {
218     switch (cmd) {
219     case XENMEM_increase_reservation:
220     case XENMEM_decrease_reservation:
221     case XENMEM_populate_physmap:
222         return ia64_xenmem_reservation_op(cmd, 
223                                           (struct xen_memory_reservation*)arg);
224     default:
225         return ____HYPERVISOR_memory_op(cmd, arg);
226     }
227     /* NOTREACHED */
228 }
229
230 static inline int
231 HYPERVISOR_event_channel_op(
232     int cmd, void *arg)
233 {
234     int rc = _hypercall2(int, event_channel_op, cmd, arg);
235     if (unlikely(rc == -ENOSYS)) {
236         struct evtchn_op op;
237         op.cmd = cmd;
238         memcpy(&op.u, arg, sizeof(op.u));
239         rc = _hypercall1(int, event_channel_op_compat, &op);
240     }
241     return rc;
242 }
243
244 static inline int
245 HYPERVISOR_acm_op(
246         unsigned int cmd, void *arg)
247 {
248     return _hypercall2(int, acm_op, cmd, arg);
249 }
250
251 static inline int
252 HYPERVISOR_xen_version(
253     int cmd, void *arg)
254 {
255     return _hypercall2(int, xen_version, cmd, arg);
256 }
257
258 static inline int
259 HYPERVISOR_console_io(
260     int cmd, int count, char *str)
261 {
262     return _hypercall3(int, console_io, cmd, count, str);
263 }
264
265 static inline int
266 HYPERVISOR_physdev_op(
267     int cmd, void *arg)
268 {
269     int rc = _hypercall2(int, physdev_op, cmd, arg);
270     if (unlikely(rc == -ENOSYS)) {
271         struct physdev_op op;
272         op.cmd = cmd;
273         memcpy(&op.u, arg, sizeof(op.u));
274         rc = _hypercall1(int, physdev_op_compat, &op);
275     }
276     return rc;
277 }
278
279 //XXX __HYPERVISOR_grant_table_op is used for this hypercall constant.
280 static inline int
281 ____HYPERVISOR_grant_table_op(
282     unsigned int cmd, void *uop, unsigned int count,
283     unsigned long pa1, unsigned long pa2)
284 {
285     return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2);
286 }
287
288 int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
289
290 static inline int
291 HYPERVISOR_vcpu_op(
292         int cmd, int vcpuid, void *extra_args)
293 {
294     return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
295 }
296
297 extern int HYPERVISOR_suspend(unsigned long srec);
298
299 static inline unsigned long
300 HYPERVISOR_hvm_op(
301         int cmd, void *arg)
302 {
303         return _hypercall2(unsigned long, hvm_op, cmd, arg);
304 }
305
306 static inline int
307 HYPERVISOR_callback_op(
308         int cmd, void *arg)
309 {
310         return _hypercall2(int, callback_op, cmd, arg);
311 }
312
313 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
314 static inline void exit_idle(void) {}
315 #define do_IRQ(irq, regs) ({                    \
316         irq_enter();                            \
317         __do_IRQ((irq), (regs));                \
318         irq_exit();                             \
319 })
320
321 #include <linux/err.h>
322 #ifdef CONFIG_XEN
323 #include <asm/xen/privop.h>
324 #endif /* CONFIG_XEN */
325
326 static inline unsigned long
327 __HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
328 {
329         return _hypercall3(unsigned long, ia64_dom0vp_op,
330                            IA64_DOM0VP_ioremap, ioaddr, size);
331 }
332
333 static inline unsigned long
334 HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
335 {
336         unsigned long ret = ioaddr;
337         if (is_running_on_xen()) {
338                 ret = __HYPERVISOR_ioremap(ioaddr, size);
339                 if (unlikely(ret == -ENOSYS))
340                         panic("hypercall %s failed with %ld. "
341                               "Please check Xen and Linux config mismatch\n",
342                               __func__, -ret);
343                 else if (unlikely(IS_ERR_VALUE(ret)))
344                         ret = ioaddr;
345         }
346         return ret;
347 }
348
349 static inline unsigned long
350 __HYPERVISOR_phystomach(unsigned long gpfn)
351 {
352         return _hypercall2(unsigned long, ia64_dom0vp_op,
353                            IA64_DOM0VP_phystomach, gpfn);
354 }
355
356 static inline unsigned long
357 HYPERVISOR_phystomach(unsigned long gpfn)
358 {
359         unsigned long ret = gpfn;
360         if (is_running_on_xen()) {
361                 ret = __HYPERVISOR_phystomach(gpfn);
362         }
363         return ret;
364 }
365
366 static inline unsigned long
367 __HYPERVISOR_machtophys(unsigned long mfn)
368 {
369         return _hypercall2(unsigned long, ia64_dom0vp_op,
370                            IA64_DOM0VP_machtophys, mfn);
371 }
372
373 static inline unsigned long
374 HYPERVISOR_machtophys(unsigned long mfn)
375 {
376         unsigned long ret = mfn;
377         if (is_running_on_xen()) {
378                 ret = __HYPERVISOR_machtophys(mfn);
379         }
380         return ret;
381 }
382
383 static inline unsigned long
384 __HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
385 {
386         return _hypercall3(unsigned long, ia64_dom0vp_op,
387                            IA64_DOM0VP_zap_physmap, gpfn, extent_order);
388 }
389
390 static inline unsigned long
391 HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
392 {
393         unsigned long ret = 0;
394         if (is_running_on_xen()) {
395                 ret = __HYPERVISOR_zap_physmap(gpfn, extent_order);
396         }
397         return ret;
398 }
399
400 static inline unsigned long
401 __HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
402                          unsigned long flags, domid_t domid)
403 {
404         return _hypercall5(unsigned long, ia64_dom0vp_op,
405                            IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid);
406 }
407
408 static inline unsigned long
409 HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
410                        unsigned long flags, domid_t domid)
411 {
412         unsigned long ret = 0;
413         BUG_ON(!is_running_on_xen());//XXX
414         if (is_running_on_xen()) {
415                 ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
416         }
417         return ret;
418 }
419
420 // for balloon driver
421 #define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
422
423 #endif /* __HYPERCALL_H__ */