OSDN Git Service

arm/asm: add loglvl to c_backtrace()
authorDmitry Safonov <dima@arista.com>
Tue, 9 Jun 2020 04:30:07 +0000 (21:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jun 2020 16:39:10 +0000 (09:39 -0700)
Currently, the log-level of show_stack() depends on a platform
realization.  It creates situations where the headers are printed with
lower log level or higher than the stacktrace (depending on a platform or
user).

Furthermore, it forces the logic decision from user to an architecture
side.  In result, some users as sysrq/kdb/etc are doing tricks with
temporary rising console_loglevel while printing their messages.  And in
result it not only may print unwanted messages from other CPUs, but also
omit printing at all in the unlucky case where the printk() was deferred.

Introducing log-level parameter and KERN_UNSUPPRESSED [1] seems an easier
approach than introducing more printk buffers.  Also, it will consolidate
printings with headers.

Add log level argument to c_backtrace() as a preparation for introducing
show_stack_loglvl().

[1]: https://lore.kernel.org/lkml/20190528002412.1625-1-dima@arista.com/T/#u

Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Will Deacon <will@kernel.org>
Link: http://lkml.kernel.org/r/20200418201944.482088-5-dima@arista.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/arm/include/asm/bug.h
arch/arm/include/asm/traps.h
arch/arm/kernel/traps.c
arch/arm/kernel/unwind.c
arch/arm/lib/backtrace-clang.S
arch/arm/lib/backtrace.S

index deef4d0..673c7dd 100644 (file)
@@ -82,7 +82,8 @@ void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
                                       struct pt_regs *),
                     int sig, int code, const char *name);
 
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode,
+                                  const char *loglvl);
 
 struct mm_struct;
 void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr);
index 172b08f..987fefb 100644 (file)
@@ -29,7 +29,8 @@ static inline int __in_irqentry_text(unsigned long ptr)
 }
 
 extern void __init early_trap_init(void *);
-extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
+extern void dump_backtrace_entry(unsigned long where, unsigned long from,
+                                unsigned long frame, const char *loglvl);
 extern void ptrace_break(struct pt_regs *regs);
 
 extern void *vectors_page;
index 316a768..7bba15f 100644 (file)
@@ -62,7 +62,8 @@ __setup("user_debug=", user_debug_setup);
 
 static void dump_mem(const char *, const char *, unsigned long, unsigned long);
 
-void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
+void dump_backtrace_entry(unsigned long where, unsigned long from,
+                         unsigned long frame, const char *loglvl)
 {
        unsigned long end = frame + 4 + sizeof(struct pt_regs);
 
@@ -76,7 +77,7 @@ void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long
                dump_mem("", "Exception stack", frame + 4, end);
 }
 
-void dump_backtrace_stm(u32 *stack, u32 instruction)
+void dump_backtrace_stm(u32 *stack, u32 instruction, const char *loglvl)
 {
        char str[80], *p;
        unsigned int x;
@@ -238,7 +239,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
        pr_cont("\n");
 
        if (ok)
-               c_backtrace(fp, mode);
+               c_backtrace(fp, mode, NULL);
 }
 #endif
 
@@ -666,7 +667,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
                dump_instr("", regs);
                if (user_mode(regs)) {
                        __show_regs(regs);
-                       c_backtrace(frame_pointer(regs), processor_mode(regs));
+                       c_backtrace(frame_pointer(regs), processor_mode(regs), NULL);
                }
        }
 #endif
index 11a964f..343cc27 100644 (file)
@@ -493,7 +493,7 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
                urc = unwind_frame(&frame);
                if (urc < 0)
                        break;
-               dump_backtrace_entry(where, frame.pc, frame.sp - 4);
+               dump_backtrace_entry(where, frame.pc, frame.sp - 4, NULL);
        }
 }
 
index 2ff3751..6174c45 100644 (file)
@@ -17,6 +17,7 @@
 #define sv_pc  r6
 #define mask   r7
 #define sv_lr  r8
+#define loglvl r9
 
 ENTRY(c_backtrace)
 
@@ -99,6 +100,7 @@ ENDPROC(c_backtrace)
                                                @ to ensure 8 byte alignment
                movs    frame, r0               @ if frame pointer is zero
                beq     no_frame                @ we have no stack frames
+               mov     loglvl, r2
                tst     r1, #0x10               @ 26 or 32-bit mode?
                moveq   mask, #0xfc000003
                movne   mask, #0                @ mask for 32-bit
@@ -167,6 +169,7 @@ finished_setup:
                mov     r1, sv_lr
                mov     r2, frame
                bic     r1, r1, mask            @ mask PC/LR for the mode
+               mov     r3, loglvl
                bl      dump_backtrace_entry
 
 /*
@@ -183,6 +186,7 @@ finished_setup:
                ldr     r0, [frame]             @ locals are stored in
                                                @ the preceding frame
                subeq   r0, r0, #4
+               mov     r2, loglvl
                bleq    dump_backtrace_stm      @ dump saved registers
 
 /*
@@ -196,7 +200,8 @@ finished_setup:
                bhi     for_each_frame
 
 1006:          adr     r0, .Lbad
-               mov     r1, frame
+               mov     r1, loglvl
+               mov     r2, frame
                bl      printk
 no_frame:      ldmfd   sp!, {r4 - r9, fp, pc}
 ENDPROC(c_backtrace)
@@ -209,7 +214,7 @@ ENDPROC(c_backtrace)
                .long   1005b, 1006b
                .popsection
 
-.Lbad:         .asciz  "Backtrace aborted due to bad frame pointer <%p>\n"
+.Lbad:         .asciz  "%sBacktrace aborted due to bad frame pointer <%p>\n"
                .align
 .Lopcode:      .word   0xe92d4800 >> 11        @ stmfd sp!, {... fp, lr}
                .word   0x0b000000              @ bl if these bits are set
index 5829252..872f658 100644 (file)
@@ -18,6 +18,7 @@
 #define sv_pc  r6
 #define mask   r7
 #define offset r8
+#define loglvl r9
 
 ENTRY(c_backtrace)
 
@@ -25,9 +26,10 @@ ENTRY(c_backtrace)
                ret     lr
 ENDPROC(c_backtrace)
 #else
-               stmfd   sp!, {r4 - r8, lr}      @ Save an extra register so we have a location...
+               stmfd   sp!, {r4 - r9, lr}      @ Save an extra register so we have a location...
                movs    frame, r0               @ if frame pointer is zero
                beq     no_frame                @ we have no stack frames
+               mov     loglvl, r2
 
                tst     r1, #0x10               @ 26 or 32-bit mode?
  ARM(          moveq   mask, #0xfc000003       )
@@ -73,6 +75,7 @@ for_each_frame:       tst     frame, mask             @ Check for address exceptions
                ldr     r1, [frame, #-4]        @ get saved lr
                mov     r2, frame
                bic     r1, r1, mask            @ mask PC/LR for the mode
+               mov     r3, loglvl
                bl      dump_backtrace_entry
 
                ldr     r1, [sv_pc, #-4]        @ if stmfd sp!, {args} exists,
@@ -80,12 +83,14 @@ for_each_frame:     tst     frame, mask             @ Check for address exceptions
                teq     r3, r1, lsr #11
                ldreq   r0, [frame, #-8]        @ get sp
                subeq   r0, r0, #4              @ point at the last arg
+               mov     r2, loglvl
                bleq    dump_backtrace_stm      @ dump saved registers
 
 1004:          ldr     r1, [sv_pc, #0]         @ if stmfd sp!, {..., fp, ip, lr, pc}
                ldr     r3, .Ldsi               @ instruction exists,
                teq     r3, r1, lsr #11
                subeq   r0, frame, #16
+               mov     r2, loglvl
                bleq    dump_backtrace_stm      @ dump saved registers
 
                teq     sv_fp, #0               @ zero saved fp means
@@ -96,9 +101,10 @@ for_each_frame:     tst     frame, mask             @ Check for address exceptions
                bhi     for_each_frame
 
 1006:          adr     r0, .Lbad
-               mov     r1, frame
+               mov     r1, loglvl
+               mov     r2, frame
                bl      printk
-no_frame:      ldmfd   sp!, {r4 - r8, pc}
+no_frame:      ldmfd   sp!, {r4 - r9, pc}
 ENDPROC(c_backtrace)
                
                .pushsection __ex_table,"a"
@@ -109,7 +115,7 @@ ENDPROC(c_backtrace)
                .long   1004b, 1006b
                .popsection
 
-.Lbad:         .asciz  "Backtrace aborted due to bad frame pointer <%p>\n"
+.Lbad:         .asciz  "%sBacktrace aborted due to bad frame pointer <%p>\n"
                .align
 .Ldsi:         .word   0xe92dd800 >> 11        @ stmfd sp!, {... fp, ip, lr, pc}
                .word   0xe92d0000 >> 11        @ stmfd sp!, {}