54a0151041
The prevent_tail_call() macro works around the problem of the compiler clobbering argument words on the stack, which for asmlinkage functions is the caller's (user's) struct pt_regs. The tail/sibling-call optimization is not the only way that the compiler can decide to use stack argument words as scratch space, which we have to prevent. Other optimizations can do it too. Until we have new compiler support to make "asmlinkage" binding on the compiler's own use of the stack argument frame, we have work around all the manifestations of this issue that crop up. More cases seem to be prevented by also keeping the incoming argument variables live at the end of the function. This makes their original stack slots attractive places to leave those variables, so the compiler tends not clobber them for something else. It's still no guarantee, but it handles some observed cases that prevent_tail_call() did not. Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
47 lines
1.5 KiB
C
47 lines
1.5 KiB
C
#ifndef __ASM_LINKAGE_H
|
|
#define __ASM_LINKAGE_H
|
|
|
|
#ifdef CONFIG_X86_64
|
|
#define __ALIGN .p2align 4,,15
|
|
#define __ALIGN_STR ".p2align 4,,15"
|
|
#endif
|
|
|
|
#ifdef CONFIG_X86_32
|
|
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
|
|
/*
|
|
* For 32-bit UML - mark functions implemented in assembly that use
|
|
* regparm input parameters:
|
|
*/
|
|
#define asmregparm __attribute__((regparm(3)))
|
|
|
|
#define asmlinkage_protect(n, ret, args...) \
|
|
__asmlinkage_protect##n(ret, ##args)
|
|
#define __asmlinkage_protect_n(ret, args...) \
|
|
__asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args)
|
|
#define __asmlinkage_protect0(ret) \
|
|
__asmlinkage_protect_n(ret)
|
|
#define __asmlinkage_protect1(ret, arg1) \
|
|
__asmlinkage_protect_n(ret, "g" (arg1))
|
|
#define __asmlinkage_protect2(ret, arg1, arg2) \
|
|
__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2))
|
|
#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \
|
|
__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3))
|
|
#define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \
|
|
__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
|
|
"g" (arg4))
|
|
#define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \
|
|
__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
|
|
"g" (arg4), "g" (arg5))
|
|
#define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \
|
|
__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
|
|
"g" (arg4), "g" (arg5), "g" (arg6))
|
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_X86_ALIGNMENT_16
|
|
#define __ALIGN .align 16,0x90
|
|
#define __ALIGN_STR ".align 16,0x90"
|
|
#endif
|
|
|
|
#endif
|
|
|