mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
325cdacd03
Mike Galbraith reported a situation where a WARN_ON_ONCE() call in DRM code turned into an oops. As it turns out, WARN_ON_ONCE() seems to be completely broken when called from a module. The bug was introduced with the following commit:19d436268d
("debug: Add _ONCE() logic to report_bug()") That commit changed WARN_ON_ONCE() to move its 'once' logic into the bug trap handler. It requires a writable bug table so that the BUGFLAG_DONE bit can be written to the flags to indicate the first warning has occurred. The bug table was made writable for vmlinux, which relies on vmlinux.lds.S and vmlinux.lds.h for laying out the sections. However, it wasn't made writable for modules, which rely on the ELF section header flags. Reported-by: Mike Galbraith <efault@gmx.de> Tested-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Fixes:19d436268d
("debug: Add _ONCE() logic to report_bug()") Link: http://lkml.kernel.org/r/a53b04235a65478dd9afc51f5b329fdc65c84364.1500095401.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
91 lines
2.4 KiB
C
91 lines
2.4 KiB
C
#ifndef _ASMARM_BUG_H
|
|
#define _ASMARM_BUG_H
|
|
|
|
#include <linux/linkage.h>
|
|
#include <linux/types.h>
|
|
#include <asm/opcodes.h>
|
|
|
|
/*
|
|
* Use a suitable undefined instruction to use for ARM/Thumb2 bug handling.
|
|
* We need to be careful not to conflict with those used by other modules and
|
|
* the register_undef_hook() system.
|
|
*/
|
|
#ifdef CONFIG_THUMB2_KERNEL
|
|
#define BUG_INSTR_VALUE 0xde02
|
|
#define BUG_INSTR(__value) __inst_thumb16(__value)
|
|
#else
|
|
#define BUG_INSTR_VALUE 0xe7f001f2
|
|
#define BUG_INSTR(__value) __inst_arm(__value)
|
|
#endif
|
|
|
|
|
|
#define BUG() _BUG(__FILE__, __LINE__, BUG_INSTR_VALUE)
|
|
#define _BUG(file, line, value) __BUG(file, line, value)
|
|
|
|
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
|
|
|
/*
|
|
* The extra indirection is to ensure that the __FILE__ string comes through
|
|
* OK. Many version of gcc do not support the asm %c parameter which would be
|
|
* preferable to this unpleasantness. We use mergeable string sections to
|
|
* avoid multiple copies of the string appearing in the kernel image.
|
|
*/
|
|
|
|
#define __BUG(__file, __line, __value) \
|
|
do { \
|
|
asm volatile("1:\t" BUG_INSTR(__value) "\n" \
|
|
".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \
|
|
"2:\t.asciz " #__file "\n" \
|
|
".popsection\n" \
|
|
".pushsection __bug_table,\"aw\"\n" \
|
|
".align 2\n" \
|
|
"3:\t.word 1b, 2b\n" \
|
|
"\t.hword " #__line ", 0\n" \
|
|
".popsection"); \
|
|
unreachable(); \
|
|
} while (0)
|
|
|
|
#else
|
|
|
|
#define __BUG(__file, __line, __value) \
|
|
do { \
|
|
asm volatile(BUG_INSTR(__value) "\n"); \
|
|
unreachable(); \
|
|
} while (0)
|
|
#endif /* CONFIG_DEBUG_BUGVERBOSE */
|
|
|
|
#define HAVE_ARCH_BUG
|
|
|
|
#include <asm-generic/bug.h>
|
|
|
|
struct pt_regs;
|
|
void die(const char *msg, struct pt_regs *regs, int err);
|
|
|
|
struct siginfo;
|
|
void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
|
|
unsigned long err, unsigned long trap);
|
|
|
|
#ifdef CONFIG_ARM_LPAE
|
|
#define FAULT_CODE_ALIGNMENT 33
|
|
#define FAULT_CODE_DEBUG 34
|
|
#else
|
|
#define FAULT_CODE_ALIGNMENT 1
|
|
#define FAULT_CODE_DEBUG 2
|
|
#endif
|
|
|
|
void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
|
|
struct pt_regs *),
|
|
int sig, int code, const char *name);
|
|
|
|
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);
|
|
|
|
struct mm_struct;
|
|
extern void show_pte(struct mm_struct *mm, unsigned long addr);
|
|
extern void __show_regs(struct pt_regs *);
|
|
|
|
#endif
|