forked from mirrors/linux
		
	When using the frame pointer unwinder, it was found that the stack trace output of stack_trace_save() is incomplete if the stack contains call_with_stack(): [0x7f00002c] dump_stack_task+0x2c/0x90 [hrtimer] [0x7f0000a0] hrtimer_hander+0x10/0x18 [hrtimer] [0x801a67f0] __hrtimer_run_queues+0x1b0/0x3b4 [0x801a7350] hrtimer_run_queues+0xc4/0xd8 [0x801a597c] update_process_times+0x3c/0x88 [0x801b5a98] tick_periodic+0x50/0xd8 [0x801b5bf4] tick_handle_periodic+0x24/0x84 [0x8010ffc4] twd_handler+0x38/0x48 [0x8017d220] handle_percpu_devid_irq+0xa8/0x244 [0x80176e9c] generic_handle_domain_irq+0x2c/0x3c [0x8052e3a8] gic_handle_irq+0x7c/0x90 [0x808ab15c] generic_handle_arch_irq+0x60/0x80 [0x8051191c] call_with_stack+0x1c/0x20 For the frame pointer unwinder, unwind_frame() checks stackframe::fp by stackframe::sp. Since call_with_stack() switches the SP from one stack to another, stackframe::fp and stackframe: :sp will point to different stacks, so we can no longer check stackframe::fp by stackframe::sp. Skip checking stackframe::fp at this point to avoid this problem. Signed-off-by: Li Huafei <lihuafei1@huawei.com> Reviewed-by: Linus Waleij <linus.walleij@linaro.org> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
		
			
				
	
	
		
			51 lines
		
	
	
	
		
			1.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			51 lines
		
	
	
	
		
			1.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
						|
/*
 | 
						|
 * arch/arm/lib/call_with_stack.S
 | 
						|
 *
 | 
						|
 * Copyright (C) 2011 ARM Ltd.
 | 
						|
 * Written by Will Deacon <will.deacon@arm.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/linkage.h>
 | 
						|
#include <asm/assembler.h>
 | 
						|
#include <asm/unwind.h>
 | 
						|
 | 
						|
/*
 | 
						|
 * void call_with_stack(void (*fn)(void *), void *arg, void *sp)
 | 
						|
 *
 | 
						|
 * Change the stack to that pointed at by sp, then invoke fn(arg) with
 | 
						|
 * the new stack.
 | 
						|
 *
 | 
						|
 * The sequence below follows the APCS frame convention for frame pointer
 | 
						|
 * unwinding, and implements the unwinder annotations needed by the EABI
 | 
						|
 * unwinder.
 | 
						|
 */
 | 
						|
 | 
						|
ENTRY(call_with_stack)
 | 
						|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
 | 
						|
	mov	ip, sp
 | 
						|
	push	{fp, ip, lr, pc}
 | 
						|
	sub	fp, ip, #4
 | 
						|
#else
 | 
						|
UNWIND( .fnstart		)
 | 
						|
UNWIND( .save	{fpreg, lr}	)
 | 
						|
	push	{fpreg, lr}
 | 
						|
UNWIND( .setfp	fpreg, sp	)
 | 
						|
	mov	fpreg, sp
 | 
						|
#endif
 | 
						|
	mov	sp, r2
 | 
						|
	mov	r2, r0
 | 
						|
	mov	r0, r1
 | 
						|
 | 
						|
	bl_r	r2
 | 
						|
 | 
						|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
 | 
						|
	ldmdb	fp, {fp, sp, pc}
 | 
						|
#else
 | 
						|
	mov	sp, fpreg
 | 
						|
	pop	{fpreg, pc}
 | 
						|
UNWIND( .fnend			)
 | 
						|
#endif
 | 
						|
	.globl call_with_stack_end
 | 
						|
call_with_stack_end:
 | 
						|
ENDPROC(call_with_stack)
 |