diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index d240ea9..93e0d33 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -91,6 +91,18 @@ extern struct { char _entry[32]; } hypercall_page[]; #define __HYPERCALL_ARG3REG "edx" #define __HYPERCALL_ARG4REG "esi" #define __HYPERCALL_ARG5REG "edi" + +/* + * On 32b the xen api uses %ebp for the 6th argument + * the hypercall. %ebp is used by the compiler. The code + * below, has the compiler put the value in %eax. The + * inline assembly then saves %ebp, moves %eax to %ebp + * and restores %ebp after the hypercall. + */ + +#define __HYPERCALL_6PRE "push %%ebp ; mov %%eax, %%ebp ; " +#define __HYPERCALL_6POST ";" "pop %%ebp" +#define __HYPERCALL_DECLS6 unsigned long __arg6 = __arg6; #else #define __HYPERCALL_RETREG "rax" #define __HYPERCALL_ARG1REG "rdi" @@ -98,6 +110,13 @@ extern struct { char _entry[32]; } hypercall_page[]; #define __HYPERCALL_ARG3REG "rdx" #define __HYPERCALL_ARG4REG "r10" #define __HYPERCALL_ARG5REG "r8" +#define __HYPERCALL_ARG6REG "r9" + +#define __HYPERCALL_6PRE "" +#define __HYPERCALL_6POST "" + +#define __HYPERCALL_DECLS6 \ + register unsigned long __arg6 asm(__HYPERCALL_ARG6REG) = __arg6; #endif #define __HYPERCALL_DECLS \ @@ -106,7 +125,8 @@ extern struct { char _entry[32]; } hypercall_page[]; register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \ register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \ register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \ - register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; + register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; \ + __HYPERCALL_DECLS6 #define __HYPERCALL_0PARAM "=r" (__res) #define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1) @@ -114,6 +134,11 @@ extern struct { char _entry[32]; } hypercall_page[]; #define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3) #define __HYPERCALL_4PARAM __HYPERCALL_3PARAM, "+r" (__arg4) #define __HYPERCALL_5PARAM __HYPERCALL_4PARAM, "+r" (__arg5) +#ifdef CONFIG_X86_32 +#define __HYPERCALL_6PARAM __HYPERCALL_5PARAM +#else +#define __HYPERCALL_6PARAM __HYPERCALL_5PARAM, "+r" (__arg6) +#endif #define __HYPERCALL_0ARG() #define __HYPERCALL_1ARG(a1) \ @@ -126,7 +151,10 @@ extern struct { char _entry[32]; } hypercall_page[]; __HYPERCALL_3ARG(a1,a2,a3) __arg4 = (unsigned long)(a4); #define __HYPERCALL_5ARG(a1,a2,a3,a4,a5) \ __HYPERCALL_4ARG(a1,a2,a3,a4) __arg5 = (unsigned long)(a5); +#define __HYPERCALL_6ARG(a1, a2, a3, a4, a5, a6) \ + __HYPERCALL_5ARG(a1, a2, a3, a4, a5); __arg6 = (unsigned long)(a6); +#define __HYPERCALL_CLOBBER6 "memory" #define __HYPERCALL_CLOBBER5 "memory" #define __HYPERCALL_CLOBBER4 __HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG #define __HYPERCALL_CLOBBER3 __HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG @@ -200,6 +228,19 @@ extern struct { char _entry[32]; } hypercall_page[]; (type)__res; \ }) +#define _hypercall6(type, name, a1, a2, a3, a4, a5, a6) \ +({ \ + __HYPERCALL_DECLS; \ + __HYPERCALL_6ARG(a1, a2, a3, a4, a5, a6); \ + asm volatile ( __HYPERCALL_6PRE \ + __HYPERCALL \ + __HYPERCALL_6POST \ + : __HYPERCALL_6PARAM \ + : __HYPERCALL_ENTRY(name) , "0" ((long)(__arg6)) \ + : __HYPERCALL_CLOBBER6); \ + (type)__res; \ +}) + static inline long privcmd_call(unsigned call, unsigned long a1, unsigned long a2,