|
21 | 21 | #include <asm/cputype.h> |
22 | 22 | #include <asm/daifflags.h> |
23 | 23 | #include <asm/debug-monitors.h> |
| 24 | +#include <asm/kgdb.h> |
| 25 | +#include <asm/kprobes.h> |
24 | 26 | #include <asm/system_misc.h> |
25 | 27 | #include <asm/traps.h> |
| 28 | +#include <asm/uprobes.h> |
26 | 29 |
|
27 | 30 | /* Determine debug architecture. */ |
28 | 31 | u8 debug_monitors_arch(void) |
@@ -299,20 +302,47 @@ void unregister_kernel_break_hook(struct break_hook *hook) |
299 | 302 |
|
300 | 303 | static int call_break_hook(struct pt_regs *regs, unsigned long esr) |
301 | 304 | { |
302 | | - struct break_hook *hook; |
303 | | - struct list_head *list; |
| 305 | + if (user_mode(regs)) { |
| 306 | + if (IS_ENABLED(CONFIG_UPROBES) && |
| 307 | + esr_brk_comment(esr) == UPROBES_BRK_IMM) |
| 308 | + return uprobe_brk_handler(regs, esr); |
| 309 | + return DBG_HOOK_ERROR; |
| 310 | + } |
304 | 311 |
|
305 | | - list = user_mode(regs) ? &user_break_hook : &kernel_break_hook; |
| 312 | + if (esr_brk_comment(esr) == BUG_BRK_IMM) |
| 313 | + return bug_brk_handler(regs, esr); |
306 | 314 |
|
307 | | - /* |
308 | | - * Since brk exception disables interrupt, this function is |
309 | | - * entirely not preemptible, and we can use rcu list safely here. |
310 | | - */ |
311 | | - list_for_each_entry_rcu(hook, list, node) { |
312 | | - if ((esr_brk_comment(esr) & ~hook->mask) == hook->imm) |
313 | | - return hook->fn(regs, esr); |
| 315 | + if (IS_ENABLED(CONFIG_CFI_CLANG) && esr_is_cfi_brk(esr)) |
| 316 | + return cfi_brk_handler(regs, esr); |
| 317 | + |
| 318 | + if (esr_brk_comment(esr) == FAULT_BRK_IMM) |
| 319 | + return reserved_fault_brk_handler(regs, esr); |
| 320 | + |
| 321 | + if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && |
| 322 | + (esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM) |
| 323 | + return kasan_brk_handler(regs, esr); |
| 324 | + |
| 325 | + if (IS_ENABLED(CONFIG_UBSAN_TRAP) && esr_is_ubsan_brk(esr)) |
| 326 | + return ubsan_brk_handler(regs, esr); |
| 327 | + |
| 328 | + if (IS_ENABLED(CONFIG_KGDB)) { |
| 329 | + if (esr_brk_comment(esr) == KGDB_DYN_DBG_BRK_IMM) |
| 330 | + return kgdb_brk_handler(regs, esr); |
| 331 | + if (esr_brk_comment(esr) == KGDB_COMPILED_DBG_BRK_IMM) |
| 332 | + return kgdb_compiled_brk_handler(regs, esr); |
314 | 333 | } |
315 | 334 |
|
| 335 | + if (IS_ENABLED(CONFIG_KPROBES)) { |
| 336 | + if (esr_brk_comment(esr) == KPROBES_BRK_IMM) |
| 337 | + return kprobe_brk_handler(regs, esr); |
| 338 | + if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM) |
| 339 | + return kprobe_ss_brk_handler(regs, esr); |
| 340 | + } |
| 341 | + |
| 342 | + if (IS_ENABLED(CONFIG_KRETPROBES) && |
| 343 | + esr_brk_comment(esr) == KRETPROBES_BRK_IMM) |
| 344 | + return kretprobe_brk_handler(regs, esr); |
| 345 | + |
316 | 346 | return DBG_HOOK_ERROR; |
317 | 347 | } |
318 | 348 | NOKPROBE_SYMBOL(call_break_hook); |
|
0 commit comments