aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86/xen/hypercall.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-x86/xen/hypercall.h')
-rw-r--r--include/asm-x86/xen/hypercall.h263
1 files changed, 182 insertions, 81 deletions
diff --git a/include/asm-x86/xen/hypercall.h b/include/asm-x86/xen/hypercall.h
index 2a4f9b41d684..91cb7fd5c123 100644
--- a/include/asm-x86/xen/hypercall.h
+++ b/include/asm-x86/xen/hypercall.h
@@ -40,83 +40,157 @@
40#include <xen/interface/sched.h> 40#include <xen/interface/sched.h>
41#include <xen/interface/physdev.h> 41#include <xen/interface/physdev.h>
42 42
43/*
44 * The hypercall asms have to meet several constraints:
45 * - Work on 32- and 64-bit.
46 * The two architectures put their arguments in different sets of
47 * registers.
48 *
49 * - Work around asm syntax quirks
50 * It isn't possible to specify one of the rNN registers in a
51 * constraint, so we use explicit register variables to get the
52 * args into the right place.
53 *
54 * - Mark all registers as potentially clobbered
55 * Even unused parameters can be clobbered by the hypervisor, so we
56 * need to make sure gcc knows it.
57 *
58 * - Avoid compiler bugs.
59 * This is the tricky part. Because x86_32 has such a constrained
60 * register set, gcc versions below 4.3 have trouble generating
61 * code when all the arg registers and memory are trashed by the
62 * asm. There are syntactically simpler ways of achieving the
63 * semantics below, but they cause the compiler to crash.
64 *
65 * The only combination I found which works is:
66 * - assign the __argX variables first
67 * - list all actually used parameters as "+r" (__argX)
68 * - clobber the rest
69 *
70 * The result certainly isn't pretty, and it really shows up cpp's
71 * weakness as as macro language. Sorry. (But let's just give thanks
72 * there aren't more than 5 arguments...)
73 */
74
43extern struct { char _entry[32]; } hypercall_page[]; 75extern struct { char _entry[32]; } hypercall_page[];
44 76
77#define __HYPERCALL "call hypercall_page+%c[offset]"
78#define __HYPERCALL_ENTRY(x) \
79 [offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
80
81#ifdef CONFIG_X86_32
82#define __HYPERCALL_RETREG "eax"
83#define __HYPERCALL_ARG1REG "ebx"
84#define __HYPERCALL_ARG2REG "ecx"
85#define __HYPERCALL_ARG3REG "edx"
86#define __HYPERCALL_ARG4REG "esi"
87#define __HYPERCALL_ARG5REG "edi"
88#else
89#define __HYPERCALL_RETREG "rax"
90#define __HYPERCALL_ARG1REG "rdi"
91#define __HYPERCALL_ARG2REG "rsi"
92#define __HYPERCALL_ARG3REG "rdx"
93#define __HYPERCALL_ARG4REG "r10"
94#define __HYPERCALL_ARG5REG "r8"
95#endif
96
97#define __HYPERCALL_DECLS \
98 register unsigned long __res asm(__HYPERCALL_RETREG); \
99 register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
100 register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
101 register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
102 register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
103 register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
104
105#define __HYPERCALL_0PARAM "=r" (__res)
106#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1)
107#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2)
108#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3)
109#define __HYPERCALL_4PARAM __HYPERCALL_3PARAM, "+r" (__arg4)
110#define __HYPERCALL_5PARAM __HYPERCALL_4PARAM, "+r" (__arg5)
111
112#define __HYPERCALL_0ARG()
113#define __HYPERCALL_1ARG(a1) \
114 __HYPERCALL_0ARG() __arg1 = (unsigned long)(a1);
115#define __HYPERCALL_2ARG(a1,a2) \
116 __HYPERCALL_1ARG(a1) __arg2 = (unsigned long)(a2);
117#define __HYPERCALL_3ARG(a1,a2,a3) \
118 __HYPERCALL_2ARG(a1,a2) __arg3 = (unsigned long)(a3);
119#define __HYPERCALL_4ARG(a1,a2,a3,a4) \
120 __HYPERCALL_3ARG(a1,a2,a3) __arg4 = (unsigned long)(a4);
121#define __HYPERCALL_5ARG(a1,a2,a3,a4,a5) \
122 __HYPERCALL_4ARG(a1,a2,a3,a4) __arg5 = (unsigned long)(a5);
123
124#define __HYPERCALL_CLOBBER5 "memory"
125#define __HYPERCALL_CLOBBER4 __HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
126#define __HYPERCALL_CLOBBER3 __HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
127#define __HYPERCALL_CLOBBER2 __HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
128#define __HYPERCALL_CLOBBER1 __HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
129#define __HYPERCALL_CLOBBER0 __HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
130
45#define _hypercall0(type, name) \ 131#define _hypercall0(type, name) \
46({ \ 132({ \
47 long __res; \ 133 __HYPERCALL_DECLS; \
48 asm volatile ( \ 134 __HYPERCALL_0ARG(); \
49 "call %[call]" \ 135 asm volatile (__HYPERCALL \
50 : "=a" (__res) \ 136 : __HYPERCALL_0PARAM \
51 : [call] "m" (hypercall_page[__HYPERVISOR_##name]) \ 137 : __HYPERCALL_ENTRY(name) \
52 : "memory" ); \ 138 : __HYPERCALL_CLOBBER0); \
53 (type)__res; \ 139 (type)__res; \
54}) 140})
55 141
56#define _hypercall1(type, name, a1) \ 142#define _hypercall1(type, name, a1) \
57({ \ 143({ \
58 long __res, __ign1; \ 144 __HYPERCALL_DECLS; \
59 asm volatile ( \ 145 __HYPERCALL_1ARG(a1); \
60 "call %[call]" \ 146 asm volatile (__HYPERCALL \
61 : "=a" (__res), "=b" (__ign1) \ 147 : __HYPERCALL_1PARAM \
62 : "1" ((long)(a1)), \ 148 : __HYPERCALL_ENTRY(name) \
63 [call] "m" (hypercall_page[__HYPERVISOR_##name]) \ 149 : __HYPERCALL_CLOBBER1); \
64 : "memory" ); \
65 (type)__res; \ 150 (type)__res; \
66}) 151})
67 152
68#define _hypercall2(type, name, a1, a2) \ 153#define _hypercall2(type, name, a1, a2) \
69({ \ 154({ \
70 long __res, __ign1, __ign2; \ 155 __HYPERCALL_DECLS; \
71 asm volatile ( \ 156 __HYPERCALL_2ARG(a1, a2); \
72 "call %[call]" \ 157 asm volatile (__HYPERCALL \
73 : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ 158 : __HYPERCALL_2PARAM \
74 : "1" ((long)(a1)), "2" ((long)(a2)), \ 159 : __HYPERCALL_ENTRY(name) \
75 [call] "m" (hypercall_page[__HYPERVISOR_##name]) \ 160 : __HYPERCALL_CLOBBER2); \
76 : "memory" ); \
77 (type)__res; \ 161 (type)__res; \
78}) 162})
79 163
80#define _hypercall3(type, name, a1, a2, a3) \ 164#define _hypercall3(type, name, a1, a2, a3) \
81({ \ 165({ \
82 long __res, __ign1, __ign2, __ign3; \ 166 __HYPERCALL_DECLS; \
83 asm volatile ( \ 167 __HYPERCALL_3ARG(a1, a2, a3); \
84 "call %[call]" \ 168 asm volatile (__HYPERCALL \
85 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 169 : __HYPERCALL_3PARAM \
86 "=d" (__ign3) \ 170 : __HYPERCALL_ENTRY(name) \
87 : "1" ((long)(a1)), "2" ((long)(a2)), \ 171 : __HYPERCALL_CLOBBER3); \
88 "3" ((long)(a3)), \
89 [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
90 : "memory" ); \
91 (type)__res; \ 172 (type)__res; \
92}) 173})
93 174
94#define _hypercall4(type, name, a1, a2, a3, a4) \ 175#define _hypercall4(type, name, a1, a2, a3, a4) \
95({ \ 176({ \
96 long __res, __ign1, __ign2, __ign3, __ign4; \ 177 __HYPERCALL_DECLS; \
97 asm volatile ( \ 178 __HYPERCALL_4ARG(a1, a2, a3, a4); \
98 "call %[call]" \ 179 asm volatile (__HYPERCALL \
99 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 180 : __HYPERCALL_4PARAM \
100 "=d" (__ign3), "=S" (__ign4) \ 181 : __HYPERCALL_ENTRY(name) \
101 : "1" ((long)(a1)), "2" ((long)(a2)), \ 182 : __HYPERCALL_CLOBBER4); \
102 "3" ((long)(a3)), "4" ((long)(a4)), \
103 [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
104 : "memory" ); \
105 (type)__res; \ 183 (type)__res; \
106}) 184})
107 185
108#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 186#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
109({ \ 187({ \
110 long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \ 188 __HYPERCALL_DECLS; \
111 asm volatile ( \ 189 __HYPERCALL_5ARG(a1, a2, a3, a4, a5); \
112 "call %[call]" \ 190 asm volatile (__HYPERCALL \
113 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 191 : __HYPERCALL_5PARAM \
114 "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \ 192 : __HYPERCALL_ENTRY(name) \
115 : "1" ((long)(a1)), "2" ((long)(a2)), \ 193 : __HYPERCALL_CLOBBER5); \
116 "3" ((long)(a3)), "4" ((long)(a4)), \
117 "5" ((long)(a5)), \
118 [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
119 : "memory" ); \
120 (type)__res; \ 194 (type)__res; \
121}) 195})
122 196
@@ -152,6 +226,7 @@ HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
152 return _hypercall2(int, stack_switch, ss, esp); 226 return _hypercall2(int, stack_switch, ss, esp);
153} 227}
154 228
229#ifdef CONFIG_X86_32
155static inline int 230static inline int
156HYPERVISOR_set_callbacks(unsigned long event_selector, 231HYPERVISOR_set_callbacks(unsigned long event_selector,
157 unsigned long event_address, 232 unsigned long event_address,
@@ -162,6 +237,17 @@ HYPERVISOR_set_callbacks(unsigned long event_selector,
162 event_selector, event_address, 237 event_selector, event_address,
163 failsafe_selector, failsafe_address); 238 failsafe_selector, failsafe_address);
164} 239}
240#else /* CONFIG_X86_64 */
241static inline int
242HYPERVISOR_set_callbacks(unsigned long event_address,
243 unsigned long failsafe_address,
244 unsigned long syscall_address)
245{
246 return _hypercall3(int, set_callbacks,
247 event_address, failsafe_address,
248 syscall_address);
249}
250#endif /* CONFIG_X86_{32,64} */
165 251
166static inline int 252static inline int
167HYPERVISOR_callback_op(int cmd, void *arg) 253HYPERVISOR_callback_op(int cmd, void *arg)
@@ -223,12 +309,12 @@ static inline int
223HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val, 309HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
224 unsigned long flags) 310 unsigned long flags)
225{ 311{
226 unsigned long pte_hi = 0; 312 if (sizeof(new_val) == sizeof(long))
227#ifdef CONFIG_X86_PAE 313 return _hypercall3(int, update_va_mapping, va,
228 pte_hi = new_val.pte_high; 314 new_val.pte, flags);
229#endif 315 else
230 return _hypercall4(int, update_va_mapping, va, 316 return _hypercall4(int, update_va_mapping, va,
231 new_val.pte_low, pte_hi, flags); 317 new_val.pte, new_val.pte >> 32, flags);
232} 318}
233 319
234static inline int 320static inline int
@@ -281,12 +367,13 @@ static inline int
281HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val, 367HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
282 unsigned long flags, domid_t domid) 368 unsigned long flags, domid_t domid)
283{ 369{
284 unsigned long pte_hi = 0; 370 if (sizeof(new_val) == sizeof(long))
285#ifdef CONFIG_X86_PAE 371 return _hypercall4(int, update_va_mapping_otherdomain, va,
286 pte_hi = new_val.pte_high; 372 new_val.pte, flags, domid);
287#endif 373 else
288 return _hypercall5(int, update_va_mapping_otherdomain, va, 374 return _hypercall5(int, update_va_mapping_otherdomain, va,
289 new_val.pte_low, pte_hi, flags, domid); 375 new_val.pte, new_val.pte >> 32,
376 flags, domid);
290} 377}
291 378
292static inline int 379static inline int
@@ -301,6 +388,14 @@ HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
301 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 388 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
302} 389}
303 390
391#ifdef CONFIG_X86_64
392static inline int
393HYPERVISOR_set_segment_base(int reg, unsigned long value)
394{
395 return _hypercall2(int, set_segment_base, reg, value);
396}
397#endif
398
304static inline int 399static inline int
305HYPERVISOR_suspend(unsigned long srec) 400HYPERVISOR_suspend(unsigned long srec)
306{ 401{
@@ -327,14 +422,14 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
327{ 422{
328 mcl->op = __HYPERVISOR_update_va_mapping; 423 mcl->op = __HYPERVISOR_update_va_mapping;
329 mcl->args[0] = va; 424 mcl->args[0] = va;
330#ifdef CONFIG_X86_PAE 425 if (sizeof(new_val) == sizeof(long)) {
331 mcl->args[1] = new_val.pte_low; 426 mcl->args[1] = new_val.pte;
332 mcl->args[2] = new_val.pte_high; 427 mcl->args[2] = flags;
333#else 428 } else {
334 mcl->args[1] = new_val.pte_low; 429 mcl->args[1] = new_val.pte;
335 mcl->args[2] = 0; 430 mcl->args[2] = new_val.pte >> 32;
336#endif 431 mcl->args[3] = flags;
337 mcl->args[3] = flags; 432 }
338} 433}
339 434
340static inline void 435static inline void
@@ -354,15 +449,16 @@ MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long v
354{ 449{
355 mcl->op = __HYPERVISOR_update_va_mapping_otherdomain; 450 mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
356 mcl->args[0] = va; 451 mcl->args[0] = va;
357#ifdef CONFIG_X86_PAE 452 if (sizeof(new_val) == sizeof(long)) {
358 mcl->args[1] = new_val.pte_low; 453 mcl->args[1] = new_val.pte;
359 mcl->args[2] = new_val.pte_high; 454 mcl->args[2] = flags;
360#else 455 mcl->args[3] = domid;
361 mcl->args[1] = new_val.pte_low; 456 } else {
362 mcl->args[2] = 0; 457 mcl->args[1] = new_val.pte;
363#endif 458 mcl->args[2] = new_val.pte >> 32;
364 mcl->args[3] = flags; 459 mcl->args[3] = flags;
365 mcl->args[4] = domid; 460 mcl->args[4] = domid;
461 }
366} 462}
367 463
368static inline void 464static inline void
@@ -370,10 +466,15 @@ MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
370 struct desc_struct desc) 466 struct desc_struct desc)
371{ 467{
372 mcl->op = __HYPERVISOR_update_descriptor; 468 mcl->op = __HYPERVISOR_update_descriptor;
373 mcl->args[0] = maddr; 469 if (sizeof(maddr) == sizeof(long)) {
374 mcl->args[1] = maddr >> 32; 470 mcl->args[0] = maddr;
375 mcl->args[2] = desc.a; 471 mcl->args[1] = *(unsigned long *)&desc;
376 mcl->args[3] = desc.b; 472 } else {
473 mcl->args[0] = maddr;
474 mcl->args[1] = maddr >> 32;
475 mcl->args[2] = desc.a;
476 mcl->args[3] = desc.b;
477 }
377} 478}
378 479
379static inline void 480static inline void