ia64/xen-unstable

view linux-2.6-xen-sparse/include/asm-ia64/hypercall.h @ 10146:83c0449db67a

[IA64] work around ENOSYS vs EINVAL in ioremap

We should not panic the domain for an EINVAL return from the ioremap
hyerpcall. This was only meant for ENOSYS. Long term this is probably
not the best place for this kind of sanity checking.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
author awilliam@xenbuild.aw
date Tue May 23 17:05:27 2006 -0600 (2006-05-23)
parents d8659e39ff3c
children 5674e4fe8f02
line source
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 */
33 #ifndef __HYPERCALL_H__
34 #define __HYPERCALL_H__
36 #include <linux/string.h> /* memcpy() */
38 #ifndef __HYPERVISOR_H__
39 # error "please don't include this file directly"
40 #endif
42 /*
43 * Assembler stubs for hyper-calls.
44 */
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 : "i" (__HYPERVISOR_##name) \
55 : "r2","r8", \
56 "memory" ); \
57 (type)__res; \
58 })
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 : "i" (__HYPERVISOR_##name), \
70 "r" ((unsigned long)(a1)) \
71 : "r14","r2","r8", \
72 "memory" ); \
73 (type)__res; \
74 })
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 : "i" (__HYPERVISOR_##name), \
87 "r" ((unsigned long)(a1)), \
88 "r" ((unsigned long)(a2)) \
89 : "r14","r15","r2","r8", \
90 "memory" ); \
91 (type)__res; \
92 })
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 : "i" (__HYPERVISOR_##name), \
106 "r" ((unsigned long)(a1)), \
107 "r" ((unsigned long)(a2)), \
108 "r" ((unsigned long)(a3)) \
109 : "r14","r15","r16","r2","r8", \
110 "memory" ); \
111 (type)__res; \
112 })
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 : "i" (__HYPERVISOR_##name), \
127 "r" ((unsigned long)(a1)), \
128 "r" ((unsigned long)(a2)), \
129 "r" ((unsigned long)(a3)), \
130 "r" ((unsigned long)(a4)) \
131 : "r14","r15","r16","r2","r8", \
132 "r17","memory" ); \
133 (type)__res; \
134 })
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 : "i" (__HYPERVISOR_##name), \
150 "r" ((unsigned long)(a1)), \
151 "r" ((unsigned long)(a2)), \
152 "r" ((unsigned long)(a3)), \
153 "r" ((unsigned long)(a4)), \
154 "r" ((unsigned long)(a5)) \
155 : "r14","r15","r16","r2","r8", \
156 "r17","r18","memory" ); \
157 (type)__res; \
158 })
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 }
167 static inline int
168 HYPERVISOR_sched_op(
169 int cmd, void *arg)
170 {
171 return _hypercall2(int, sched_op, cmd, arg);
172 }
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 }
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 }
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 }
198 #ifndef CONFIG_XEN_IA64_DOM0_VP
199 static inline int
200 HYPERVISOR_memory_op(
201 unsigned int cmd, void *arg)
202 {
203 return _hypercall2(int, memory_op, cmd, arg);
204 }
205 #else
206 //XXX xen/ia64 copy_from_guest() is broken.
207 // This is a temporal work around until it is fixed.
208 static inline int
209 ____HYPERVISOR_memory_op(
210 unsigned int cmd, void *arg)
211 {
212 return _hypercall2(int, memory_op, cmd, arg);
213 }
215 #include <xen/interface/memory.h>
216 int ia64_xenmem_reservation_op(unsigned long op,
217 struct xen_memory_reservation* reservation__);
218 static inline int
219 HYPERVISOR_memory_op(
220 unsigned int cmd, void *arg)
221 {
222 switch (cmd) {
223 case XENMEM_increase_reservation:
224 case XENMEM_decrease_reservation:
225 case XENMEM_populate_physmap:
226 return ia64_xenmem_reservation_op(cmd,
227 (struct xen_memory_reservation*)arg);
228 default:
229 return ____HYPERVISOR_memory_op(cmd, arg);
230 }
231 /* NOTREACHED */
232 }
233 #endif
235 static inline int
236 HYPERVISOR_event_channel_op(
237 int cmd, void *arg)
238 {
239 int rc = _hypercall2(int, event_channel_op, cmd, arg);
240 if (unlikely(rc == -ENOSYS)) {
241 struct evtchn_op op;
242 op.cmd = cmd;
243 memcpy(&op.u, arg, sizeof(op.u));
244 rc = _hypercall1(int, event_channel_op_compat, &op);
245 }
246 return rc;
247 }
249 static inline int
250 HYPERVISOR_xen_version(
251 int cmd, void *arg)
252 {
253 return _hypercall2(int, xen_version, cmd, arg);
254 }
256 static inline int
257 HYPERVISOR_console_io(
258 int cmd, int count, char *str)
259 {
260 return _hypercall3(int, console_io, cmd, count, str);
261 }
263 static inline int
264 HYPERVISOR_physdev_op(
265 int cmd, void *arg)
266 {
267 int rc = _hypercall2(int, physdev_op, cmd, arg);
268 if (unlikely(rc == -ENOSYS)) {
269 struct physdev_op op;
270 op.cmd = cmd;
271 memcpy(&op.u, arg, sizeof(op.u));
272 rc = _hypercall1(int, physdev_op_compat, &op);
273 }
274 return rc;
275 }
277 //XXX __HYPERVISOR_grant_table_op is used for this hypercall constant.
278 static inline int
279 ____HYPERVISOR_grant_table_op(
280 unsigned int cmd, void *uop, unsigned int count)
281 {
282 return _hypercall3(int, grant_table_op, cmd, uop, count);
283 }
284 #ifndef CONFIG_XEN_IA64_DOM0_VP
285 #define HYPERVISOR_grant_table_op(cmd, uop, count) \
286 ____HYPERVISOR_grant_table_op((cmd), (uop), (count))
287 #else
288 int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
289 #endif
291 static inline int
292 HYPERVISOR_vcpu_op(
293 int cmd, int vcpuid, void *extra_args)
294 {
295 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
296 }
298 static inline int
299 HYPERVISOR_suspend(
300 unsigned long srec)
301 {
302 struct sched_shutdown sched_shutdown = {
303 .reason = SHUTDOWN_suspend
304 };
306 int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
307 &sched_shutdown, srec);
309 if (rc == -ENOSYS)
310 rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
311 SHUTDOWN_suspend, srec);
313 return rc;
314 }
316 static inline int
317 HYPERVISOR_callback_op(
318 int cmd, void *arg)
319 {
320 return _hypercall2(int, callback_op, cmd, arg);
321 }
323 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
324 static inline void exit_idle(void) {}
325 #define do_IRQ(irq, regs) ({ \
326 irq_enter(); \
327 __do_IRQ((irq), (regs)); \
328 irq_exit(); \
329 })
331 #ifdef CONFIG_XEN_IA64_DOM0_VP
332 #include <linux/err.h>
333 #include <asm/xen/privop.h>
335 #define _hypercall_imm1(type, name, imm, a1) \
336 ({ \
337 long __res; \
338 __asm__ __volatile__ (";;\n" \
339 "mov r14=%2\n" \
340 "mov r15=%3\n" \
341 "mov r2=%1\n" \
342 "break 0x1000 ;;\n" \
343 "mov %0=r8 ;;\n" \
344 : "=r" (__res) \
345 : "i" (__HYPERVISOR_##name), \
346 "i" (imm), \
347 "r" ((unsigned long)(a1)) \
348 : "r14","r15","r2","r8", \
349 "memory" ); \
350 (type)__res; \
351 })
353 #define _hypercall_imm2(type, name, imm, a1, a2) \
354 ({ \
355 long __res; \
356 __asm__ __volatile__ (";;\n" \
357 "mov r14=%2\n" \
358 "mov r15=%3\n" \
359 "mov r16=%4\n" \
360 "mov r2=%1\n" \
361 "break 0x1000 ;;\n" \
362 "mov %0=r8 ;;\n" \
363 : "=r" (__res) \
364 : "i" (__HYPERVISOR_##name), \
365 "i" (imm), \
366 "r" ((unsigned long)(a1)), \
367 "r" ((unsigned long)(a2)) \
368 : "r14","r15","r16","r2","r8", \
369 "memory" ); \
370 (type)__res; \
371 })
373 #define _hypercall_imm3(type, name, imm, a1, a2, a3) \
374 ({ \
375 long __res; \
376 __asm__ __volatile__ (";;\n" \
377 "mov r14=%2\n" \
378 "mov r15=%3\n" \
379 "mov r16=%4\n" \
380 "mov r17=%5\n" \
381 "mov r2=%1\n" \
382 "break 0x1000 ;;\n" \
383 "mov %0=r8 ;;\n" \
384 : "=r" (__res) \
385 : "i" (__HYPERVISOR_##name), \
386 "i" (imm), \
387 "r" ((unsigned long)(a1)), \
388 "r" ((unsigned long)(a2)), \
389 "r" ((unsigned long)(a3)) \
390 : "r14","r15","r16","r17", \
391 "r2","r8", \
392 "memory" ); \
393 (type)__res; \
394 })
396 #define _hypercall_imm4(type, name, imm, a1, a2, a3, a4) \
397 ({ \
398 long __res; \
399 __asm__ __volatile__ (";;\n" \
400 "mov r14=%2\n" \
401 "mov r15=%3\n" \
402 "mov r16=%4\n" \
403 "mov r17=%5\n" \
404 "mov r18=%6\n" \
405 "mov r2=%1\n" \
406 "break 0x1000 ;;\n" \
407 "mov %0=r8 ;;\n" \
408 : "=r" (__res) \
409 : "i" (__HYPERVISOR_##name), \
410 "i" (imm), \
411 "r" ((unsigned long)(a1)), \
412 "r" ((unsigned long)(a2)), \
413 "r" ((unsigned long)(a3)), \
414 "r" ((unsigned long)(a4)) \
415 : "r14","r15","r16","r17","r18", \
416 "r2","r8", \
417 "memory" ); \
418 (type)__res; \
419 })
421 static inline unsigned long
422 __HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
423 {
424 return _hypercall_imm2(unsigned long, ia64_dom0vp_op,
425 IA64_DOM0VP_ioremap, ioaddr, size);
426 }
428 static inline unsigned long
429 HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
430 {
431 unsigned long ret = ioaddr;
432 if (running_on_xen) {
433 ret = __HYPERVISOR_ioremap(ioaddr, size);
434 if (unlikely(ret == -ENOSYS))
435 panic("hypercall %s failed with %ld. "
436 "Please check Xen and Linux config mismatch\n",
437 __func__, -ret);
438 else if (unlikely(IS_ERR_VALUE(ret)))
439 ret = ioaddr;
440 }
441 return ret;
442 }
444 static inline unsigned long
445 __HYPERVISOR_phystomach(unsigned long gpfn)
446 {
447 return _hypercall_imm1(unsigned long, ia64_dom0vp_op,
448 IA64_DOM0VP_phystomach, gpfn);
449 }
451 static inline unsigned long
452 HYPERVISOR_phystomach(unsigned long gpfn)
453 {
454 unsigned long ret = gpfn;
455 if (running_on_xen) {
456 ret = __HYPERVISOR_phystomach(gpfn);
457 }
458 return ret;
459 }
461 static inline unsigned long
462 __HYPERVISOR_machtophys(unsigned long mfn)
463 {
464 return _hypercall_imm1(unsigned long, ia64_dom0vp_op,
465 IA64_DOM0VP_machtophys, mfn);
466 }
468 static inline unsigned long
469 HYPERVISOR_machtophys(unsigned long mfn)
470 {
471 unsigned long ret = mfn;
472 if (running_on_xen) {
473 ret = __HYPERVISOR_machtophys(mfn);
474 }
475 return ret;
476 }
478 static inline unsigned long
479 __HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
480 {
481 return _hypercall_imm2(unsigned long, ia64_dom0vp_op,
482 IA64_DOM0VP_zap_physmap, gpfn, extent_order);
483 }
485 static inline unsigned long
486 HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
487 {
488 unsigned long ret = 0;
489 if (running_on_xen) {
490 ret = __HYPERVISOR_zap_physmap(gpfn, extent_order);
491 }
492 return ret;
493 }
495 static inline unsigned long
496 __HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
497 unsigned int flags, domid_t domid)
498 {
499 return _hypercall_imm4(unsigned long, ia64_dom0vp_op,
500 IA64_DOM0VP_add_physmap, gpfn, mfn, flags,
501 domid);
502 }
504 static inline unsigned long
505 HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
506 unsigned int flags, domid_t domid)
507 {
508 unsigned long ret = 0;
509 BUG_ON(!running_on_xen);//XXX
510 if (running_on_xen) {
511 ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
512 }
513 return ret;
514 }
516 // for balloon driver
517 #define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
519 #else
520 #define HYPERVISOR_ioremap(ioaddr, size) (ioaddr)
521 #define HYPERVISOR_phystomach(gpfn) (gpfn)
522 #define HYPERVISOR_machtophys(mfn) (mfn)
523 #define HYPERVISOR_zap_physmap(gpfn, extent_order) (0)
524 #define HYPERVISOR_add_physmap(gpfn, mfn, flags) (0)
525 #endif
526 #endif /* __HYPERCALL_H__ */