xref: /openbmc/linux/arch/arm/lib/backtrace.S (revision 24c66dfd)
11da177e4SLinus Torvalds/*
21da177e4SLinus Torvalds *  linux/arch/arm/lib/backtrace.S
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds *  Copyright (C) 1995, 1996 Russell King
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify
71da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as
81da177e4SLinus Torvalds * published by the Free Software Foundation.
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * 27/03/03 Ian Molton Clean up CONFIG_CPU
111da177e4SLinus Torvalds *
121da177e4SLinus Torvalds */
1324c66dfdSRussell King#include <linux/kern_levels.h>
141da177e4SLinus Torvalds#include <linux/linkage.h>
151da177e4SLinus Torvalds#include <asm/assembler.h>
161da177e4SLinus Torvalds		.text
171da177e4SLinus Torvalds
181da177e4SLinus Torvalds@ fp is 0 or stack frame
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds#define frame	r4
217ab3f8d5SRussell King#define sv_fp	r5
227ab3f8d5SRussell King#define sv_pc	r6
231da177e4SLinus Torvalds#define mask	r7
241da177e4SLinus Torvalds#define offset	r8
251da177e4SLinus Torvalds
261da177e4SLinus TorvaldsENTRY(c_backtrace)
271da177e4SLinus Torvalds
283ee357f0SMalcolm Parsons#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
296ebbf2ceSRussell King		ret	lr
3093ed3970SCatalin MarinasENDPROC(c_backtrace)
311da177e4SLinus Torvalds#else
321da177e4SLinus Torvalds		stmfd	sp!, {r4 - r8, lr}	@ Save an extra register so we have a location...
337ab3f8d5SRussell King		movs	frame, r0		@ if frame pointer is zero
347ab3f8d5SRussell King		beq	no_frame		@ we have no stack frames
351da177e4SLinus Torvalds
367ab3f8d5SRussell King		tst	r1, #0x10		@ 26 or 32-bit mode?
378b592783SCatalin Marinas ARM(		moveq	mask, #0xfc000003	)
388b592783SCatalin Marinas THUMB(		moveq	mask, #0xfc000000	)
398b592783SCatalin Marinas THUMB(		orreq	mask, #0x03		)
407ab3f8d5SRussell King		movne	mask, #0		@ mask for 32-bit
417ab3f8d5SRussell King
427ab3f8d5SRussell King1:		stmfd	sp!, {pc}		@ calculate offset of PC stored
437ab3f8d5SRussell King		ldr	r0, [sp], #4		@ by stmfd for this CPU
447ab3f8d5SRussell King		adr	r1, 1b
451da177e4SLinus Torvalds		sub	offset, r0, r1
461da177e4SLinus Torvalds
477ab3f8d5SRussell King/*
487ab3f8d5SRussell King * Stack frame layout:
497ab3f8d5SRussell King *             optionally saved caller registers (r4 - r10)
507ab3f8d5SRussell King *             saved fp
517ab3f8d5SRussell King *             saved sp
527ab3f8d5SRussell King *             saved lr
537ab3f8d5SRussell King *    frame => saved pc
547ab3f8d5SRussell King *             optionally saved arguments (r0 - r3)
557ab3f8d5SRussell King * saved sp => <next word>
567ab3f8d5SRussell King *
577ab3f8d5SRussell King * Functions start with the following code sequence:
587ab3f8d5SRussell King *                  mov   ip, sp
597ab3f8d5SRussell King *                  stmfd sp!, {r0 - r3} (optional)
607ab3f8d5SRussell King * corrected pc =>  stmfd sp!, {..., fp, ip, lr, pc}
617ab3f8d5SRussell King */
627ab3f8d5SRussell Kingfor_each_frame:	tst	frame, mask		@ Check for address exceptions
637ab3f8d5SRussell King		bne	no_frame
641da177e4SLinus Torvalds
657ab3f8d5SRussell King1001:		ldr	sv_pc, [frame, #0]	@ get saved pc
667ab3f8d5SRussell King1002:		ldr	sv_fp, [frame, #-12]	@ get saved fp
677ab3f8d5SRussell King
687ab3f8d5SRussell King		sub	sv_pc, sv_pc, offset	@ Correct PC for prefetching
697ab3f8d5SRussell King		bic	sv_pc, sv_pc, mask	@ mask PC/LR for the mode
707ab3f8d5SRussell King
717ab3f8d5SRussell King1003:		ldr	r2, [sv_pc, #-4]	@ if stmfd sp!, {args} exists,
727ab3f8d5SRussell King		ldr	r3, .Ldsi+4		@ adjust saved 'pc' back one
737ab3f8d5SRussell King		teq	r3, r2, lsr #10		@ instruction
747ab3f8d5SRussell King		subne	r0, sv_pc, #4		@ allow for mov
757ab3f8d5SRussell King		subeq	r0, sv_pc, #8		@ allow for mov + stmia
767ab3f8d5SRussell King
777ab3f8d5SRussell King		ldr	r1, [frame, #-4]	@ get saved lr
787ab3f8d5SRussell King		mov	r2, frame
797ab3f8d5SRussell King		bic	r1, r1, mask		@ mask PC/LR for the mode
801da177e4SLinus Torvalds		bl	dump_backtrace_entry
811da177e4SLinus Torvalds
827ab3f8d5SRussell King		ldr	r1, [sv_pc, #-4]	@ if stmfd sp!, {args} exists,
837ab3f8d5SRussell King		ldr	r3, .Ldsi+4
84ef41b5c9SRussell King		teq	r3, r1, lsr #11
857ab3f8d5SRussell King		ldreq	r0, [frame, #-8]	@ get sp
867ab3f8d5SRussell King		subeq	r0, r0, #4		@ point at the last arg
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
9324c66dfdSRussell King		bleq	dump_backtrace_stm	@ dump saved registers
941da177e4SLinus Torvalds
957ab3f8d5SRussell King		teq	sv_fp, #0		@ zero saved fp means
967ab3f8d5SRussell King		beq	no_frame		@ no further frames
971da177e4SLinus Torvalds
987ab3f8d5SRussell King		cmp	sv_fp, frame		@ next frame must be
997ab3f8d5SRussell King		mov	frame, sv_fp		@ above the current frame
1007ab3f8d5SRussell King		bhi	for_each_frame
1011da177e4SLinus Torvalds
1027ab3f8d5SRussell King1006:		adr	r0, .Lbad
1031da177e4SLinus Torvalds		mov	r1, frame
1041da177e4SLinus Torvalds		bl	printk
1057ab3f8d5SRussell Kingno_frame:	ldmfd	sp!, {r4 - r8, pc}
10693ed3970SCatalin MarinasENDPROC(c_backtrace)
1071da177e4SLinus Torvalds
1084260415fSRussell King		.pushsection __ex_table,"a"
1091da177e4SLinus Torvalds		.align	3
1107ab3f8d5SRussell King		.long	1001b, 1006b
1117ab3f8d5SRussell King		.long	1002b, 1006b
1127ab3f8d5SRussell King		.long	1003b, 1006b
1137ab3f8d5SRussell King		.long	1004b, 1006b
1144260415fSRussell King		.popsection
1151da177e4SLinus Torvalds
1161da177e4SLinus Torvalds.Lbad:		.asciz	"Backtrace aborted due to bad frame pointer <%p>\n"
1171da177e4SLinus Torvalds		.align
118ef41b5c9SRussell King.Ldsi:		.word	0xe92dd800 >> 11	@ stmfd sp!, {... fp, ip, lr, pc}
119ef41b5c9SRussell King		.word	0xe92d0000 >> 11	@ stmfd sp!, {}
1201da177e4SLinus Torvalds
1211da177e4SLinus Torvalds#endif
122