| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/arch/arm/lib/backtrace.S |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 1995, 1996 Russell King |
|---|
| 5 | 6 | * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 8 | | - * published by the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | 7 | * 27/03/03 Ian Molton Clean up CONFIG_CPU |
|---|
| 11 | | - * |
|---|
| 12 | 8 | */ |
|---|
| 13 | 9 | #include <linux/kern_levels.h> |
|---|
| 14 | 10 | #include <linux/linkage.h> |
|---|
| .. | .. |
|---|
| 22 | 18 | #define sv_pc r6 |
|---|
| 23 | 19 | #define mask r7 |
|---|
| 24 | 20 | #define offset r8 |
|---|
| 21 | +#define loglvl r9 |
|---|
| 25 | 22 | |
|---|
| 26 | 23 | ENTRY(c_backtrace) |
|---|
| 27 | 24 | |
|---|
| .. | .. |
|---|
| 29 | 26 | ret lr |
|---|
| 30 | 27 | ENDPROC(c_backtrace) |
|---|
| 31 | 28 | #else |
|---|
| 32 | | - stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... |
|---|
| 29 | + stmfd sp!, {r4 - r9, lr} @ Save an extra register so we have a location... |
|---|
| 33 | 30 | movs frame, r0 @ if frame pointer is zero |
|---|
| 34 | 31 | beq no_frame @ we have no stack frames |
|---|
| 32 | + mov loglvl, r2 |
|---|
| 35 | 33 | |
|---|
| 36 | 34 | tst r1, #0x10 @ 26 or 32-bit mode? |
|---|
| 37 | 35 | ARM( moveq mask, #0xfc000003 ) |
|---|
| .. | .. |
|---|
| 70 | 68 | |
|---|
| 71 | 69 | 1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists, |
|---|
| 72 | 70 | ldr r3, .Ldsi+4 @ adjust saved 'pc' back one |
|---|
| 73 | | - teq r3, r2, lsr #10 @ instruction |
|---|
| 71 | + teq r3, r2, lsr #11 @ instruction |
|---|
| 74 | 72 | subne r0, sv_pc, #4 @ allow for mov |
|---|
| 75 | 73 | subeq r0, sv_pc, #8 @ allow for mov + stmia |
|---|
| 76 | 74 | |
|---|
| 77 | 75 | ldr r1, [frame, #-4] @ get saved lr |
|---|
| 78 | 76 | mov r2, frame |
|---|
| 79 | 77 | bic r1, r1, mask @ mask PC/LR for the mode |
|---|
| 78 | + mov r3, loglvl |
|---|
| 80 | 79 | bl dump_backtrace_entry |
|---|
| 81 | 80 | |
|---|
| 82 | 81 | ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists, |
|---|
| .. | .. |
|---|
| 84 | 83 | teq r3, r1, lsr #11 |
|---|
| 85 | 84 | ldreq r0, [frame, #-8] @ get sp |
|---|
| 86 | 85 | subeq r0, r0, #4 @ point at the last arg |
|---|
| 86 | + mov r2, loglvl |
|---|
| 87 | 87 | bleq dump_backtrace_stm @ dump saved registers |
|---|
| 88 | 88 | |
|---|
| 89 | 89 | 1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc} |
|---|
| 90 | 90 | ldr r3, .Ldsi @ instruction exists, |
|---|
| 91 | 91 | teq r3, r1, lsr #11 |
|---|
| 92 | 92 | subeq r0, frame, #16 |
|---|
| 93 | + mov r2, loglvl |
|---|
| 93 | 94 | bleq dump_backtrace_stm @ dump saved registers |
|---|
| 94 | 95 | |
|---|
| 95 | 96 | teq sv_fp, #0 @ zero saved fp means |
|---|
| .. | .. |
|---|
| 100 | 101 | bhi for_each_frame |
|---|
| 101 | 102 | |
|---|
| 102 | 103 | 1006: adr r0, .Lbad |
|---|
| 103 | | - mov r1, frame |
|---|
| 104 | + mov r1, loglvl |
|---|
| 105 | + mov r2, frame |
|---|
| 104 | 106 | bl printk |
|---|
| 105 | | -no_frame: ldmfd sp!, {r4 - r8, pc} |
|---|
| 107 | +no_frame: ldmfd sp!, {r4 - r9, pc} |
|---|
| 106 | 108 | ENDPROC(c_backtrace) |
|---|
| 107 | 109 | |
|---|
| 108 | 110 | .pushsection __ex_table,"a" |
|---|
| .. | .. |
|---|
| 113 | 115 | .long 1004b, 1006b |
|---|
| 114 | 116 | .popsection |
|---|
| 115 | 117 | |
|---|
| 116 | | -.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" |
|---|
| 118 | +.Lbad: .asciz "%sBacktrace aborted due to bad frame pointer <%p>\n" |
|---|
| 117 | 119 | .align |
|---|
| 118 | 120 | .Ldsi: .word 0xe92dd800 >> 11 @ stmfd sp!, {... fp, ip, lr, pc} |
|---|
| 119 | 121 | .word 0xe92d0000 >> 11 @ stmfd sp!, {} |
|---|