Skip to content

Commit

Permalink
LoongArch: Use generic BUG() handler
Browse files Browse the repository at this point in the history
Inspired by commit 9fb7410("arm64/BUG: Use BRK instruction for
generic BUG traps"), do similar to LoongArch to use generic BUG()
handler.

This patch uses the BREAK software breakpoint instruction to generate
a trap instead, similarly to most other arches, with the generic BUG
code generating the dmesg boilerplate.

This allows bug metadata to be moved to a separate table and reduces
the amount of inline code at BUG and WARN sites. This also avoids
clobbering any registers before they can be dumped.

To mitigate the size of the bug table further, this patch makes use
of the existing infrastructure for encoding addresses within the bug
table as 32-bit relative pointers instead of absolute pointers. (Note
that this limits the kernel size to 2GB.)

Before patch:
[ 3018.338013] lkdtm: Performing direct entry BUG
[ 3018.342445] Kernel bug detected[#5]:
[ 3018.345992] CPU: 2 PID: 865 Comm: cat Tainted: G D 6.0.0-rc6+ torvalds#35

After patch:
[  125.585985] lkdtm: Performing direct entry BUG
[  125.590433] ------------[ cut here ]------------
[  125.595020] kernel BUG at drivers/misc/lkdtm/bugs.c:78!
[  125.600211] Oops - BUG[#1]:
[  125.602980] CPU: 3 PID: 410 Comm: cat Not tainted 6.0.0-rc6+ torvalds#36

Out-of-line file/line data information obtained compared to before.

Signed-off-by: Youling Tang <tangyouling@loongson.cn>
  • Loading branch information
Youling Tang authored and intel-lab-lkp committed Sep 22, 2022
1 parent dc164f4 commit 233fbb6
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 13 deletions.
8 changes: 8 additions & 0 deletions arch/loongarch/Kconfig
Expand Up @@ -156,6 +156,14 @@ config LOCKDEP_SUPPORT
bool
default y

config GENERIC_BUG
def_bool y
depends on BUG

config GENERIC_BUG_RELATIVE_POINTERS
def_bool y
depends on GENERIC_BUG

config STACKTRACE_SUPPORT
bool
default y
Expand Down
60 changes: 49 additions & 11 deletions arch/loongarch/include/asm/bug.h
@@ -1,23 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef __ASM_BUG_H
#define __ASM_BUG_H

#include <linux/compiler.h>
#include <asm/break.h>
#include <linux/stringify.h>

#ifdef CONFIG_DEBUG_BUGVERBOSE
#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line)
#define __BUGVERBOSE_LOCATION(file, line) \
.pushsection .rodata.str, "aMS", @progbits, 1; \
10002: .string file; \
.popsection; \
\
.long 10002b - .; \
.short line;
#else
#define _BUGVERBOSE_LOCATION(file, line)
#endif

#ifdef CONFIG_BUG
#ifdef CONFIG_GENERIC_BUG

#define __BUG_ENTRY(flags) \
.pushsection __bug_table, "aw"; \
.align 2; \
10000: .long 10001f - .; \
_BUGVERBOSE_LOCATION(__FILE__, __LINE__) \
.short flags; \
.popsection; \
10001:
#else
#define __BUG_ENTRY(flags)
#endif

#include <asm/break.h>
#define ASM_BUG_FLAGS(flags) \
__BUG_ENTRY(flags) \
break BRK_BUG

static inline void __noreturn BUG(void)
{
__asm__ __volatile__("break %0" : : "i" (BRK_BUG));
unreachable();
}
#define ASM_BUG() ASM_BUG_FLAGS(0)

#define HAVE_ARCH_BUG
#define __BUG_FLAGS(flags) \
asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags)));

#endif
#define BUG() do { \
instrumentation_begin(); \
__BUG_FLAGS(0); \
unreachable(); \
} while (0)

#define __WARN_FLAGS(flags) do { \
instrumentation_begin(); \
__BUG_FLAGS(BUGFLAG_WARNING|(flags)); \
instrumentation_end(); \
} while (0)

#define HAVE_ARCH_BUG

#include <asm-generic/bug.h>

#endif /* __ASM_BUG_H */
#endif /* ! __ASM_BUG_H */
3 changes: 3 additions & 0 deletions arch/loongarch/kernel/head.S
Expand Up @@ -8,6 +8,7 @@
#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/bug.h>
#include <asm/regdef.h>
#include <asm/loongarch.h>
#include <asm/stackframe.h>
Expand Down Expand Up @@ -61,6 +62,7 @@ SYM_CODE_START(kernel_entry) # kernel entry point
PTR_ADDI sp, sp, -4 * SZREG # init stack pointer

bl start_kernel
ASM_BUG()

SYM_CODE_END(kernel_entry)

Expand Down Expand Up @@ -92,6 +94,7 @@ SYM_CODE_START(smpboot_entry)
ld.d tp, t0, CPU_BOOT_TINFO

bl start_secondary
ASM_BUG()
SYM_CODE_END(smpboot_entry)

#endif /* CONFIG_SMP */
Expand Down
26 changes: 24 additions & 2 deletions arch/loongarch/kernel/traps.c
Expand Up @@ -374,6 +374,29 @@ asmlinkage void noinstr do_ale(struct pt_regs *regs)
irqentry_exit(regs, state);
}

/* GENERIC_BUG traps */

int is_valid_bugaddr(unsigned long addr)
{
return 1;
}

static void bug_handler(struct pt_regs *regs)
{
switch (report_bug(regs->csr_era, regs)) {
case BUG_TRAP_TYPE_NONE:
case BUG_TRAP_TYPE_BUG:
die_if_kernel("Oops - BUG", regs);
force_sig(SIGTRAP);
break;

case BUG_TRAP_TYPE_WARN:
/* Skip the BUG instruction and continue */
regs->csr_era += LOONGARCH_INSN_SIZE;
break;
}
}

asmlinkage void noinstr do_bp(struct pt_regs *regs)
{
bool user = user_mode(regs);
Expand Down Expand Up @@ -427,8 +450,7 @@ asmlinkage void noinstr do_bp(struct pt_regs *regs)

switch (bcode) {
case BRK_BUG:
die_if_kernel("Kernel bug detected", regs);
force_sig(SIGTRAP);
bug_handler(regs);
break;
case BRK_DIVZERO:
die_if_kernel("Break instruction in kernel code", regs);
Expand Down

0 comments on commit 233fbb6

Please sign in to comment.