Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm: add loglvl to unwind_backtrace()

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 unwind_backtrace() as a preparation for
introducing show_stack_loglvl().

As a good side-effect arm_syscall() is now printing errors with the same
log level as the backtrace.

[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-6-dima@arista.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Dmitry Safonov and committed by
Linus Torvalds
e8d7b735 5489ab50

+8 -6
+2 -1
arch/arm/include/asm/unwind.h
··· 36 36 unsigned long text_addr, 37 37 unsigned long text_size); 38 38 extern void unwind_table_del(struct unwind_table *tab); 39 - extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk); 39 + extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk, 40 + const char *loglvl); 40 41 41 42 #endif /* !__ASSEMBLY__ */ 42 43
+3 -3
arch/arm/kernel/traps.c
··· 204 204 #ifdef CONFIG_ARM_UNWIND 205 205 static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) 206 206 { 207 - unwind_backtrace(regs, tsk); 207 + unwind_backtrace(regs, tsk, KERN_DEFAULT); 208 208 } 209 209 #else 210 210 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) ··· 664 664 if (user_debug & UDBG_SYSCALL) { 665 665 pr_err("[%d] %s: arm syscall %d\n", 666 666 task_pid_nr(current), current->comm, no); 667 - dump_instr("", regs); 667 + dump_instr(KERN_ERR, regs); 668 668 if (user_mode(regs)) { 669 669 __show_regs(regs); 670 - c_backtrace(frame_pointer(regs), processor_mode(regs), NULL); 670 + c_backtrace(frame_pointer(regs), processor_mode(regs), KERN_ERR); 671 671 } 672 672 } 673 673 #endif
+3 -2
arch/arm/kernel/unwind.c
··· 455 455 return URC_OK; 456 456 } 457 457 458 - void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) 458 + void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk, 459 + const char *loglvl) 459 460 { 460 461 struct stackframe frame; 461 462 ··· 494 493 urc = unwind_frame(&frame); 495 494 if (urc < 0) 496 495 break; 497 - dump_backtrace_entry(where, frame.pc, frame.sp - 4, NULL); 496 + dump_backtrace_entry(where, frame.pc, frame.sp - 4, loglvl); 498 497 } 499 498 } 500 499