Skip to content

Commit 2d2c395

Browse files
Youling Tangchenhuacai
Youling Tang
authored andcommitted
LoongArch: Use generic BUG() handler
Inspired by commit 9fb7410("arm64/BUG: Use BRK instruction for generic BUG traps"), do similar for 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: this limits the max kernel size to 2GB.) Before patch: [ 3018.338013] lkdtm: Performing direct entry BUG [ 3018.342445] Kernel bug detected[Rust-for-Linux#5]: [ 3018.345992] CPU: 2 PID: 865 Comm: cat Tainted: G D 6.0.0-rc6+ Rust-for-Linux#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[Rust-for-Linux#1]: [ 125.602980] CPU: 3 PID: 410 Comm: cat Not tainted 6.0.0-rc6+ Rust-for-Linux#36 Out-of-line file/line data information obtained compared to before. Signed-off-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent dea2df3 commit 2d2c395

File tree

4 files changed

+84
-12
lines changed

4 files changed

+84
-12
lines changed

arch/loongarch/Kconfig

+8
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ config CPU_HAS_PREFETCH
142142
bool
143143
default y
144144

145+
config GENERIC_BUG
146+
def_bool y
147+
depends on BUG
148+
149+
config GENERIC_BUG_RELATIVE_POINTERS
150+
def_bool y
151+
depends on GENERIC_BUG
152+
145153
config GENERIC_CALIBRATE_DELAY
146154
def_bool y
147155

arch/loongarch/include/asm/bug.h

+48-10
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,59 @@
22
#ifndef __ASM_BUG_H
33
#define __ASM_BUG_H
44

5-
#include <linux/compiler.h>
5+
#include <asm/break.h>
6+
#include <linux/stringify.h>
7+
8+
#ifndef CONFIG_DEBUG_BUGVERBOSE
9+
#define _BUGVERBOSE_LOCATION(file, line)
10+
#else
11+
#define __BUGVERBOSE_LOCATION(file, line) \
12+
.pushsection .rodata.str, "aMS", @progbits, 1; \
13+
10002: .string file; \
14+
.popsection; \
15+
\
16+
.long 10002b - .; \
17+
.short line;
18+
#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line)
19+
#endif
620

7-
#ifdef CONFIG_BUG
21+
#ifndef CONFIG_GENERIC_BUG
22+
#define __BUG_ENTRY(flags)
23+
#else
24+
#define __BUG_ENTRY(flags) \
25+
.pushsection __bug_table, "aw"; \
26+
.align 2; \
27+
10000: .long 10001f - .; \
28+
_BUGVERBOSE_LOCATION(__FILE__, __LINE__) \
29+
.short flags; \
30+
.popsection; \
31+
10001:
32+
#endif
833

9-
#include <asm/break.h>
34+
#define ASM_BUG_FLAGS(flags) \
35+
__BUG_ENTRY(flags) \
36+
break BRK_BUG
1037

11-
static inline void __noreturn BUG(void)
12-
{
13-
__asm__ __volatile__("break %0" : : "i" (BRK_BUG));
14-
unreachable();
15-
}
38+
#define ASM_BUG() ASM_BUG_FLAGS(0)
1639

17-
#define HAVE_ARCH_BUG
40+
#define __BUG_FLAGS(flags) \
41+
asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags)));
1842

19-
#endif
43+
#define __WARN_FLAGS(flags) \
44+
do { \
45+
instrumentation_begin(); \
46+
__BUG_FLAGS(BUGFLAG_WARNING|(flags)); \
47+
instrumentation_end(); \
48+
} while (0)
49+
50+
#define BUG() \
51+
do { \
52+
instrumentation_begin(); \
53+
__BUG_FLAGS(0); \
54+
unreachable(); \
55+
} while (0)
56+
57+
#define HAVE_ARCH_BUG
2058

2159
#include <asm-generic/bug.h>
2260

arch/loongarch/kernel/head.S

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <asm/addrspace.h>
99
#include <asm/asm.h>
1010
#include <asm/asmmacro.h>
11+
#include <asm/bug.h>
1112
#include <asm/regdef.h>
1213
#include <asm/loongarch.h>
1314
#include <asm/stackframe.h>
@@ -85,6 +86,7 @@ SYM_CODE_START(kernel_entry) # kernel entry point
8586
PTR_ADDI sp, sp, -4 * SZREG # init stack pointer
8687

8788
bl start_kernel
89+
ASM_BUG()
8890

8991
SYM_CODE_END(kernel_entry)
9092

@@ -116,6 +118,8 @@ SYM_CODE_START(smpboot_entry)
116118
ld.d tp, t0, CPU_BOOT_TINFO
117119

118120
bl start_secondary
121+
ASM_BUG()
122+
119123
SYM_CODE_END(smpboot_entry)
120124

121125
#endif /* CONFIG_SMP */

arch/loongarch/kernel/traps.c

+24-2
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,29 @@ asmlinkage void noinstr do_ale(struct pt_regs *regs)
374374
irqentry_exit(regs, state);
375375
}
376376

377+
#ifdef CONFIG_GENERIC_BUG
378+
int is_valid_bugaddr(unsigned long addr)
379+
{
380+
return 1;
381+
}
382+
#endif /* CONFIG_GENERIC_BUG */
383+
384+
static void bug_handler(struct pt_regs *regs)
385+
{
386+
switch (report_bug(regs->csr_era, regs)) {
387+
case BUG_TRAP_TYPE_BUG:
388+
case BUG_TRAP_TYPE_NONE:
389+
die_if_kernel("Oops - BUG", regs);
390+
force_sig(SIGTRAP);
391+
break;
392+
393+
case BUG_TRAP_TYPE_WARN:
394+
/* Skip the BUG instruction and continue */
395+
regs->csr_era += LOONGARCH_INSN_SIZE;
396+
break;
397+
}
398+
}
399+
377400
asmlinkage void noinstr do_bp(struct pt_regs *regs)
378401
{
379402
bool user = user_mode(regs);
@@ -427,8 +450,7 @@ asmlinkage void noinstr do_bp(struct pt_regs *regs)
427450

428451
switch (bcode) {
429452
case BRK_BUG:
430-
die_if_kernel("Kernel bug detected", regs);
431-
force_sig(SIGTRAP);
453+
bug_handler(regs);
432454
break;
433455
case BRK_DIVZERO:
434456
die_if_kernel("Break instruction in kernel code", regs);

0 commit comments

Comments
 (0)