|
17 | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18 | 18 | */
|
19 | 19 |
|
| 20 | +#include <linux/bug.h> |
20 | 21 | #include <linux/signal.h>
|
21 | 22 | #include <linux/personality.h>
|
22 | 23 | #include <linux/kallsyms.h>
|
|
32 | 33 | #include <linux/syscalls.h>
|
33 | 34 |
|
34 | 35 | #include <asm/atomic.h>
|
| 36 | +#include <asm/bug.h> |
35 | 37 | #include <asm/debug-monitors.h>
|
36 | 38 | #include <asm/esr.h>
|
| 39 | +#include <asm/insn.h> |
37 | 40 | #include <asm/traps.h>
|
38 | 41 | #include <asm/stacktrace.h>
|
39 | 42 | #include <asm/exception.h>
|
@@ -466,7 +469,61 @@ void __pgd_error(const char *file, int line, unsigned long val)
|
466 | 469 | pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val);
|
467 | 470 | }
|
468 | 471 |
|
| 472 | +/* GENERIC_BUG traps */ |
| 473 | + |
| 474 | +int is_valid_bugaddr(unsigned long addr) |
| 475 | +{ |
| 476 | + /* |
| 477 | + * bug_handler() only called for BRK #BUG_BRK_IMM. |
| 478 | + * So the answer is trivial -- any spurious instances with no |
| 479 | + * bug table entry will be rejected by report_bug() and passed |
| 480 | + * back to the debug-monitors code and handled as a fatal |
| 481 | + * unexpected debug exception. |
| 482 | + */ |
| 483 | + return 1; |
| 484 | +} |
| 485 | + |
| 486 | +static int bug_handler(struct pt_regs *regs, unsigned int esr) |
| 487 | +{ |
| 488 | + if (user_mode(regs)) |
| 489 | + return DBG_HOOK_ERROR; |
| 490 | + |
| 491 | + switch (report_bug(regs->pc, regs)) { |
| 492 | + case BUG_TRAP_TYPE_BUG: |
| 493 | + die("Oops - BUG", regs, 0); |
| 494 | + break; |
| 495 | + |
| 496 | + case BUG_TRAP_TYPE_WARN: |
| 497 | + break; |
| 498 | + |
| 499 | + default: |
| 500 | + /* unknown/unrecognised bug trap type */ |
| 501 | + return DBG_HOOK_ERROR; |
| 502 | + } |
| 503 | + |
| 504 | + /* If thread survives, skip over the BUG instruction and continue: */ |
| 505 | + regs->pc += AARCH64_INSN_SIZE; /* skip BRK and resume */ |
| 506 | + return DBG_HOOK_HANDLED; |
| 507 | +} |
| 508 | + |
| 509 | +static struct break_hook bug_break_hook = { |
| 510 | + .esr_val = 0xf2000000 | BUG_BRK_IMM, |
| 511 | + .esr_mask = 0xffffffff, |
| 512 | + .fn = bug_handler, |
| 513 | +}; |
| 514 | + |
| 515 | +/* |
| 516 | + * Initial handler for AArch64 BRK exceptions |
| 517 | + * This handler only used until debug_traps_init(). |
| 518 | + */ |
| 519 | +int __init early_brk64(unsigned long addr, unsigned int esr, |
| 520 | + struct pt_regs *regs) |
| 521 | +{ |
| 522 | + return bug_handler(regs, esr) != DBG_HOOK_HANDLED; |
| 523 | +} |
| 524 | + |
| 525 | +/* This registration must happen early, before debug_traps_init(). */ |
469 | 526 | void __init trap_init(void)
|
470 | 527 | {
|
471 |
| - return; |
| 528 | + register_break_hook(&bug_break_hook); |
472 | 529 | }
|
0 commit comments