Jeremy Fitzhardinge
2007-Apr-18 13:02 UTC
[PATCH] paravirt_ops: Clean up paravirt patchable wrappers
Replace all the open-coded macros for generating calls with a pair of more general macros (__PVOP_CALL/VCALL), and redefine all the PVOP_V?CALL[0-4] in terms of them. [ Andrew, Andi: this should slot in immediately after "Document asm-i386/paravirt.h" (paravirt_ops-document-asm-i386-paravirth.patch) ] Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Ingo Molnar <mingo@elte.hu> --- include/asm-i386/paravirt.h | 252 ++++++++++--------------------------------- 1 file changed, 62 insertions(+), 190 deletions(-) ==================================================================--- a/include/asm-i386/paravirt.h +++ b/include/asm-i386/paravirt.h @@ -332,210 +332,80 @@ unsigned paravirt_patch_insns(void *site * means that all uses must be wrapped in inline functions. This also * makes sure the incoming and outgoing types are always correct. */ -#define PVOP_CALL0(__rettype, __op) \ +#define __PVOP_CALL(rettype, op, pre, post, ...) \ ({ \ - __rettype __ret; \ - if (sizeof(__rettype) > sizeof(unsigned long)) { \ - unsigned long long __tmp; \ - unsigned long __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=A" (__tmp), "=c" (__ecx) \ - : paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ + rettype __ret; \ + unsigned long __eax, __edx, __ecx; \ + if (sizeof(rettype) > sizeof(unsigned long)) { \ + asm volatile(pre \ + paravirt_alt(PARAVIRT_CALL) \ + post \ + : "=a" (__eax), "=d" (__edx), \ + "=c" (__ecx) \ + : paravirt_type(op), \ + paravirt_clobber(CLBR_ANY), \ + ##__VA_ARGS__ \ : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ + __ret = (rettype)((((u64)__edx) << 32) | __eax); \ } else { \ - unsigned long __tmp, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=a" (__tmp), "=d" (__edx), \ + asm volatile(pre \ + paravirt_alt(PARAVIRT_CALL) \ + post \ + : "=a" (__eax), "=d" (__edx), \ "=c" (__ecx) \ - : paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ + : paravirt_type(op), \ + paravirt_clobber(CLBR_ANY), \ + ##__VA_ARGS__ \ : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ + __ret = (rettype)__eax; \ } \ __ret; \ }) -#define PVOP_VCALL0(__op) \ +#define __PVOP_VCALL(op, pre, post, ...) \ ({ \ unsigned long __eax, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ + asm volatile(pre \ + paravirt_alt(PARAVIRT_CALL) \ + post \ : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ - : paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ + : paravirt_type(op), \ + paravirt_clobber(CLBR_ANY), \ + ##__VA_ARGS__ \ : "memory", "cc"); \ }) -#define PVOP_CALL1(__rettype, __op, arg1) \ - ({ \ - __rettype __ret; \ - if (sizeof(__rettype) > sizeof(unsigned long)) { \ - unsigned long long __tmp; \ - unsigned long __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=A" (__tmp), "=c" (__ecx) \ - : "a" ((u32)(arg1)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ - } else { \ - unsigned long __tmp, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=a" (__tmp), "=d" (__edx), \ - "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ - } \ - __ret; \ - }) -#define PVOP_VCALL1(__op, arg1) \ - ({ \ - unsigned long __eax, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - }) - -#define PVOP_CALL2(__rettype, __op, arg1, arg2) \ - ({ \ - __rettype __ret; \ - if (sizeof(__rettype) > sizeof(unsigned long)) { \ - unsigned long long __tmp; \ - unsigned long __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=A" (__tmp), "=c" (__ecx) \ - : "a" ((u32)(arg1)), \ - "d" ((u32)(arg2)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ - } else { \ - unsigned long __tmp, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=a" (__tmp), "=d" (__edx), \ - "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - "1" ((u32)(arg2)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ - } \ - __ret; \ - }) -#define PVOP_VCALL2(__op, arg1, arg2) \ - ({ \ - unsigned long __eax, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - "1" ((u32)(arg2)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - }) - -#define PVOP_CALL3(__rettype, __op, arg1, arg2, arg3) \ - ({ \ - __rettype __ret; \ - if (sizeof(__rettype) > sizeof(unsigned long)) { \ - unsigned long long __tmp; \ - unsigned long __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=A" (__tmp), "=c" (__ecx) \ - : "a" ((u32)(arg1)), \ - "d" ((u32)(arg2)), \ - "1" ((u32)(arg3)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ - } else { \ - unsigned long __tmp, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=a" (__tmp), "=d" (__edx), \ - "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - "1" ((u32)(arg2)), \ - "2" ((u32)(arg3)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ - } \ - __ret; \ - }) -#define PVOP_VCALL3(__op, arg1, arg2, arg3) \ - ({ \ - unsigned long __eax, __edx, __ecx; \ - asm volatile(paravirt_alt(PARAVIRT_CALL) \ - : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - "1" ((u32)(arg2)), \ - "2" ((u32)(arg3)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - }) - -#define PVOP_CALL4(__rettype, __op, arg1, arg2, arg3, arg4) \ - ({ \ - __rettype __ret; \ - if (sizeof(__rettype) > sizeof(unsigned long)) { \ - unsigned long long __tmp; \ - unsigned long __ecx; \ - asm volatile("push %[_arg4]; " \ - paravirt_alt(PARAVIRT_CALL) \ - "lea 4(%%esp),%%esp" \ - : "=A" (__tmp), "=c" (__ecx) \ - : "a" ((u32)(arg1)), \ - "d" ((u32)(arg2)), \ - "1" ((u32)(arg3)), \ - [_arg4] "mr" ((u32)(arg4)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc",); \ - __ret = (__rettype)__tmp; \ - } else { \ - unsigned long __tmp, __edx, __ecx; \ - asm volatile("push %[_arg4]; " \ - paravirt_alt(PARAVIRT_CALL) \ - "lea 4(%%esp),%%esp" \ - : "=a" (__tmp), "=d" (__edx), "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - "1" ((u32)(arg2)), \ - "2" ((u32)(arg3)), \ - [_arg4]"mr" ((u32)(arg4)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - __ret = (__rettype)__tmp; \ - } \ - __ret; \ - }) -#define PVOP_VCALL4(__op, arg1, arg2, arg3, arg4) \ - ({ \ - unsigned long __eax, __edx, __ecx; \ - asm volatile("push %[_arg4]; " \ - paravirt_alt(PARAVIRT_CALL) \ - "lea 4(%%esp),%%esp" \ - : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ - : "0" ((u32)(arg1)), \ - "1" ((u32)(arg2)), \ - "2" ((u32)(arg3)), \ - [_arg4]"mr" ((u32)(arg4)), \ - paravirt_type(__op), \ - paravirt_clobber(CLBR_ANY) \ - : "memory", "cc"); \ - }) +#define PVOP_CALL0(rettype, op) \ + __PVOP_CALL(rettype, op, "", "") +#define PVOP_VCALL0(op) \ + __PVOP_VCALL(op, "", "") + +#define PVOP_CALL1(rettype, op, arg1) \ + __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1))) +#define PVOP_VCALL1(op, arg1) \ + __PVOP_VCALL(op, "", "", "0" ((u32)(arg1))) + +#define PVOP_CALL2(rettype, op, arg1, arg2) \ + __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) +#define PVOP_VCALL2(op, arg1, arg2) \ + __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) + +#define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ + __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), \ + "1"((u32)(arg2)), "2"((u32)(arg3))) +#define PVOP_VCALL3(op, arg1, arg2, arg3) \ + __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1"((u32)(arg2)), \ + "2"((u32)(arg3))) + +#define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ + __PVOP_CALL(rettype, op, \ + "push %[_arg4];", "lea 4(%%esp),%%esp;", \ + "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ + "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) +#define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ + __PVOP_VCALL(op, \ + "push %[_arg4];", "lea 4(%%esp),%%esp;", \ + "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ + "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) static inline int paravirt_enabled(void) { @@ -1164,6 +1034,8 @@ static inline unsigned long __raw_local_ /* Make sure as little as possible of this mess escapes. */ #undef PARAVIRT_CALL +#undef __PVOP_CALL +#undef __PVOP_VCALL #undef PVOP_VCALL0 #undef PVOP_CALL0 #undef PVOP_VCALL1
Reasonably Related Threads
- [PATCH] paravirt_ops: Clean up paravirt patchable wrappers
- [PATCH 08/13] x86/paravirt: Clean up paravirt_types.h
- [PATCH 07/13] x86/paravirt: Simplify ____PVOP_CALL()
- [PATCH v3 04/12] Revert "x86/paravirt: Work around GCC inlining bugs when compiling paravirt ops"
- [PATCH 02/13] x86/paravirt: Fix output constraint macro names