xref: /openbmc/linux/arch/arm/lib/backtrace.S (revision d4664b6c)
1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
21da177e4SLinus Torvalds/*
31da177e4SLinus Torvalds *  linux/arch/arm/lib/backtrace.S
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds *  Copyright (C) 1995, 1996 Russell King
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * 27/03/03 Ian Molton Clean up CONFIG_CPU
81da177e4SLinus Torvalds */
924c66dfdSRussell King#include <linux/kern_levels.h>
101da177e4SLinus Torvalds#include <linux/linkage.h>
111da177e4SLinus Torvalds#include <asm/assembler.h>
121da177e4SLinus Torvalds		.text
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds@ fp is 0 or stack frame
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds#define frame	r4
177ab3f8d5SRussell King#define sv_fp	r5
187ab3f8d5SRussell King#define sv_pc	r6
191da177e4SLinus Torvalds#define mask	r7
201da177e4SLinus Torvalds#define offset	r8
215489ab50SDmitry Safonov#define loglvl	r9
221da177e4SLinus Torvalds
231da177e4SLinus TorvaldsENTRY(c_backtrace)
241da177e4SLinus Torvalds
253ee357f0SMalcolm Parsons#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
266ebbf2ceSRussell King		ret	lr
2793ed3970SCatalin MarinasENDPROC(c_backtrace)
281da177e4SLinus Torvalds#else
295489ab50SDmitry Safonov		stmfd	sp!, {r4 - r9, lr}	@ Save an extra register so we have a location...
307ab3f8d5SRussell King		movs	frame, r0		@ if frame pointer is zero
317ab3f8d5SRussell King		beq	no_frame		@ we have no stack frames
325489ab50SDmitry Safonov		mov	loglvl, r2
331da177e4SLinus Torvalds
347ab3f8d5SRussell King		tst	r1, #0x10		@ 26 or 32-bit mode?
358b592783SCatalin Marinas ARM(		moveq	mask, #0xfc000003	)
368b592783SCatalin Marinas THUMB(		moveq	mask, #0xfc000000	)
378b592783SCatalin Marinas THUMB(		orreq	mask, #0x03		)
387ab3f8d5SRussell King		movne	mask, #0		@ mask for 32-bit
397ab3f8d5SRussell King
407ab3f8d5SRussell King1:		stmfd	sp!, {pc}		@ calculate offset of PC stored
417ab3f8d5SRussell King		ldr	r0, [sp], #4		@ by stmfd for this CPU
427ab3f8d5SRussell King		adr	r1, 1b
431da177e4SLinus Torvalds		sub	offset, r0, r1
441da177e4SLinus Torvalds
457ab3f8d5SRussell King/*
467ab3f8d5SRussell King * Stack frame layout:
477ab3f8d5SRussell King *             optionally saved caller registers (r4 - r10)
487ab3f8d5SRussell King *             saved fp
497ab3f8d5SRussell King *             saved sp
507ab3f8d5SRussell King *             saved lr
517ab3f8d5SRussell King *    frame => saved pc
527ab3f8d5SRussell King *             optionally saved arguments (r0 - r3)
537ab3f8d5SRussell King * saved sp => <next word>
547ab3f8d5SRussell King *
557ab3f8d5SRussell King * Functions start with the following code sequence:
567ab3f8d5SRussell King *                  mov   ip, sp
577ab3f8d5SRussell King *                  stmfd sp!, {r0 - r3} (optional)
587ab3f8d5SRussell King * corrected pc =>  stmfd sp!, {..., fp, ip, lr, pc}
597ab3f8d5SRussell King */
607ab3f8d5SRussell Kingfor_each_frame:	tst	frame, mask		@ Check for address exceptions
617ab3f8d5SRussell King		bne	no_frame
621da177e4SLinus Torvalds
637ab3f8d5SRussell King1001:		ldr	sv_pc, [frame, #0]	@ get saved pc
647ab3f8d5SRussell King1002:		ldr	sv_fp, [frame, #-12]	@ get saved fp
657ab3f8d5SRussell King
667ab3f8d5SRussell King		sub	sv_pc, sv_pc, offset	@ Correct PC for prefetching
677ab3f8d5SRussell King		bic	sv_pc, sv_pc, mask	@ mask PC/LR for the mode
687ab3f8d5SRussell King
697ab3f8d5SRussell King1003:		ldr	r2, [sv_pc, #-4]	@ if stmfd sp!, {args} exists,
707ab3f8d5SRussell King		ldr	r3, .Ldsi+4		@ adjust saved 'pc' back one
7169389837SLvqiang Huang		teq	r3, r2, lsr #11		@ instruction
727ab3f8d5SRussell King		subne	r0, sv_pc, #4		@ allow for mov
737ab3f8d5SRussell King		subeq	r0, sv_pc, #8		@ allow for mov + stmia
747ab3f8d5SRussell King
757ab3f8d5SRussell King		ldr	r1, [frame, #-4]	@ get saved lr
767ab3f8d5SRussell King		mov	r2, frame
777ab3f8d5SRussell King		bic	r1, r1, mask		@ mask PC/LR for the mode
785489ab50SDmitry Safonov		mov	r3, loglvl
791da177e4SLinus Torvalds		bl	dump_backtrace_entry
801da177e4SLinus Torvalds
817ab3f8d5SRussell King		ldr	r1, [sv_pc, #-4]	@ if stmfd sp!, {args} exists,
827ab3f8d5SRussell King		ldr	r3, .Ldsi+4
83ef41b5c9SRussell King		teq	r3, r1, lsr #11
847ab3f8d5SRussell King		ldreq	r0, [frame, #-8]	@ get sp
857ab3f8d5SRussell King		subeq	r0, r0, #4		@ point at the last arg
865489ab50SDmitry Safonov		mov	r2, loglvl
8724c66dfdSRussell King		bleq	dump_backtrace_stm	@ dump saved registers
881da177e4SLinus Torvalds
897ab3f8d5SRussell King1004:		ldr	r1, [sv_pc, #0]		@ if stmfd sp!, {..., fp, ip, lr, pc}
907ab3f8d5SRussell King		ldr	r3, .Ldsi		@ instruction exists,
91ef41b5c9SRussell King		teq	r3, r1, lsr #11
927ab3f8d5SRussell King		subeq	r0, frame, #16
935489ab50SDmitry Safonov		mov	r2, loglvl
9424c66dfdSRussell King		bleq	dump_backtrace_stm	@ dump saved registers
951da177e4SLinus Torvalds
967ab3f8d5SRussell King		teq	sv_fp, #0		@ zero saved fp means
977ab3f8d5SRussell King		beq	no_frame		@ no further frames
981da177e4SLinus Torvalds
997ab3f8d5SRussell King		cmp	sv_fp, frame		@ next frame must be
1007ab3f8d5SRussell King		mov	frame, sv_fp		@ above the current frame
101*d4664b6cSArd Biesheuvel#ifdef CONFIG_IRQSTACKS
102*d4664b6cSArd Biesheuvel		@
103*d4664b6cSArd Biesheuvel		@ Kernel stacks may be discontiguous in memory. If the next
104*d4664b6cSArd Biesheuvel		@ frame is below the previous frame, accept it as long as it
105*d4664b6cSArd Biesheuvel		@ lives in kernel memory.
106*d4664b6cSArd Biesheuvel		@
107*d4664b6cSArd Biesheuvel		cmpls	sv_fp, #PAGE_OFFSET
108*d4664b6cSArd Biesheuvel#endif
1097ab3f8d5SRussell King		bhi	for_each_frame
1101da177e4SLinus Torvalds
1117ab3f8d5SRussell King1006:		adr	r0, .Lbad
1125489ab50SDmitry Safonov		mov	r1, loglvl
1135489ab50SDmitry Safonov		mov	r2, frame
11433701557SChris Down		bl	_printk
1155489ab50SDmitry Safonovno_frame:	ldmfd	sp!, {r4 - r9, pc}
11693ed3970SCatalin MarinasENDPROC(c_backtrace)
1171da177e4SLinus Torvalds
1184260415fSRussell King		.pushsection __ex_table,"a"
1191da177e4SLinus Torvalds		.align	3
1207ab3f8d5SRussell King		.long	1001b, 1006b
1217ab3f8d5SRussell King		.long	1002b, 1006b
1227ab3f8d5SRussell King		.long	1003b, 1006b
1237ab3f8d5SRussell King		.long	1004b, 1006b
1244260415fSRussell King		.popsection
1251da177e4SLinus Torvalds
1265489ab50SDmitry Safonov.Lbad:		.asciz	"%sBacktrace aborted due to bad frame pointer <%p>\n"
1271da177e4SLinus Torvalds		.align
128ef41b5c9SRussell King.Ldsi:		.word	0xe92dd800 >> 11	@ stmfd sp!, {... fp, ip, lr, pc}
129ef41b5c9SRussell King		.word	0xe92d0000 >> 11	@ stmfd sp!, {}
1301da177e4SLinus Torvalds
1311da177e4SLinus Torvalds#endif
132