diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index d240ea9..5c99ebc 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -74,8 +74,7 @@ * - clobber the rest * * The result certainly isn't pretty, and it really shows up cpp's - * weakness as as macro language. Sorry. (But let's just give thanks - * there aren't more than 5 arguments...) + * weakness as as macro language. Sorry. */ extern struct { char _entry[32]; } hypercall_page[]; @@ -91,6 +90,18 @@ extern struct { char _entry[32]; } hypercall_page[]; #define __HYPERCALL_ARG3REG "edx" #define __HYPERCALL_ARG4REG "esi" #define __HYPERCALL_ARG5REG "edi" + +/* + * On 32b we are out of free registers to pass in + * the 6th argument of the hypercall, the last one + * available is ebp. + * %ebp is already being used by linux so we save it + * then we move %eax which is the 6th argument in %ebp. + * On the way back of the hypercall we restore %ebp. + */ +#define __HYPERCALL_ARG6REG "eax" +#define __HYPERCALL6_PRE "push %%ebp ; mov %%eax, %%ebp ; " +#define __HYPERCALL6_POST ";" "pop %%ebp" #else #define __HYPERCALL_RETREG "rax" #define __HYPERCALL_ARG1REG "rdi" @@ -98,6 +109,9 @@ extern struct { char _entry[32]; } hypercall_page[]; #define __HYPERCALL_ARG3REG "rdx" #define __HYPERCALL_ARG4REG "r10" #define __HYPERCALL_ARG5REG "r8" +#define __HYPERCALL_ARG6REG "r9" +#define __HYPERCALL6_PRE "" +#define __HYPERCALL6_POST "" #endif #define __HYPERCALL_DECLS \ @@ -106,7 +120,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; \ + register unsigned long __arg6 asm(__HYPERCALL_ARG6REG) = __arg6; #define __HYPERCALL_0PARAM "=r" (__res) #define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1) @@ -114,6 +129,7 @@ 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) +#define __HYPERCALL_6PARAM __HYPERCALL_5PARAM, "+r" (__arg6) #define __HYPERCALL_0ARG() #define __HYPERCALL_1ARG(a1) \ @@ -126,7 +142,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 +219,17 @@ 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 (__HYPERCALL6_PRE __HYPERCALL __HYPERCALL6_POST \ + : __HYPERCALL_6PARAM \ + : __HYPERCALL_ENTRY(name) \ + : __HYPERCALL_CLOBBER6); \ + (type)__res; \ +}) + static inline long privcmd_call(unsigned call, unsigned long a1, unsigned long a2,