// SPDX-License-Identifier: GPL-2.0 /* Generic support for BUG() This respects the following config options: CONFIG_BUG - emit BUG traps. Nothing happens without this. CONFIG_GENERIC_BUG - enable this code. CONFIG_GENERIC_BUG_RELATIVE_POINTERS - use 32-bit relative pointers for bug_addr and file CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable (though they're generally always on). CONFIG_GENERIC_BUG is set by each architecture using this code. To use this, your architecture must: 1. Set up the config options: - Enable CONFIG_GENERIC_BUG if CONFIG_BUG 2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON) - Define HAVE_ARCH_BUG - Implement BUG() to generate a faulting instruction - NOTE: struct bug_entry does not have "file" or "line" entries when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate the values accordingly. 3. Implement the trap - In the illegal instruction trap handler (typically), verify that the fault was in kernel mode, and call report_bug() - report_bug() will return whether it was a false alarm, a warning, or an actual bug. - You must implement the is_valid_bugaddr(bugaddr) callback which returns true if the eip is a real kernel address, and it points to the expected BUG trap instruction. Jeremy Fitzhardinge <[email protected]> 2006 */ #define pr_fmt(fmt) … #include <linux/list.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/bug.h> #include <linux/sched.h> #include <linux/rculist.h> #include <linux/ftrace.h> #include <linux/context_tracking.h> extern struct bug_entry __start___bug_table[], __stop___bug_table[]; static inline unsigned long bug_addr(const struct bug_entry *bug) { … } #ifdef CONFIG_MODULES /* Updates are protected by module mutex */ static LIST_HEAD(module_bug_list); static struct bug_entry *module_find_bug(unsigned long bugaddr) { … } void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) { … } void module_bug_cleanup(struct module *mod) { … } #else static inline struct bug_entry *module_find_bug(unsigned long bugaddr) { return NULL; } #endif void bug_get_file_line(struct bug_entry *bug, const char **file, unsigned int *line) { … } struct bug_entry *find_bug(unsigned long bugaddr) { … } static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *regs) { … } enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) { … } static void clear_once_table(struct bug_entry *start, struct bug_entry *end) { … } void generic_bug_clear_once(void) { … }