Commit 75794257 authored by Vasily Gorbik's avatar Vasily Gorbik
Browse files

s390: correct CALL_ON_STACK back_chain saving



Currently CALL_ON_STACK saves r15 as back_chain in the first stack frame of
the stack we about to switch to. But if a function which uses CALL_ON_STACK
calls other function it allocates a stack frame for a callee. In this
case r15 is pointing to a callee stack frame and not a stack frame of
function itself. This results in dummy unwinding entry with random
sp and ip values.

Introduce and utilize current_frame_address macro to get an address of
actual function stack frame.

Reviewed-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 103b4cca
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -62,6 +62,17 @@ struct stack_frame {
};
#endif

/*
 * Unlike current_stack_pointer() which simply returns current value of %r15
 * current_frame_address() returns function stack frame address, which matches
 * %r15 upon function invocation. It may differ from %r15 later if function
 * allocates stack for local variables or new stack frame to call other
 * functions.
 */
#define current_frame_address()						\
	((unsigned long)__builtin_frame_address(0) -			\
	 offsetof(struct stack_frame, back_chain))

#define CALL_ARGS_0()							\
	register unsigned long r2 asm("2")
#define CALL_ARGS_1(arg1)						\
@@ -95,18 +106,20 @@ struct stack_frame {

#define CALL_ON_STACK(fn, stack, nr, args...)				\
({									\
	unsigned long frame = current_frame_address();			\
	CALL_ARGS_##nr(args);						\
	unsigned long prev;						\
									\
	asm volatile(							\
		"	la	%[_prev],0(15)\n"			\
		"	la	15,0(%[_stack])\n"			\
		"	stg	%[_prev],%[_bc](15)\n"			\
		"	stg	%[_frame],%[_bc](15)\n"			\
		"	brasl	14,%[_fn]\n"				\
		"	la	15,0(%[_prev])\n"			\
		: [_prev] "=&a" (prev), CALL_FMT_##nr			\
		  [_stack] "a" (stack),					\
		  [_bc] "i" (offsetof(struct stack_frame, back_chain)),	\
		  [_frame] "d" (frame),					\
		  [_fn] "X" (fn) : CALL_CLOBBER_##nr);			\
	r2;								\
})