exit_to_kernel_mode(regs);
}
----- ----static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
+++++ ++++static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
+++++ ++++{
+++++ ++++ arm64_enter_el1_dbg(regs);
+++++ ++++ debug_exception_enter(regs);
+++++ ++++ do_breakpoint(esr, regs);
+++++ ++++ debug_exception_exit(regs);
+++++ ++++ arm64_exit_el1_dbg(regs);
+++++ ++++}
+++++ ++++
+++++ ++++static void noinstr el1_softstp(struct pt_regs *regs, unsigned long esr)
+ {
+++++ ++++ arm64_enter_el1_dbg(regs);
+++++ ++++ if (!cortex_a76_erratum_1463225_debug_handler(regs)) {
+++++ ++++ debug_exception_enter(regs);
+++++ ++++ /*
+++++ ++++ * After handling a breakpoint, we suspend the breakpoint
+++++ ++++ * and use single-step to move to the next instruction.
+++++ ++++ * If we are stepping a suspended breakpoint there's nothing more to do:
+++++ ++++ * the single-step is complete.
+++++ ++++ */
+++++ ++++ if (!try_step_suspended_breakpoints(regs))
+++++ ++++ do_el1_softstep(esr, regs);
+++++ ++++ debug_exception_exit(regs);
+++++ ++++ }
+++++ ++++ arm64_exit_el1_dbg(regs);
+++++ ++++}
+++++ ++++
+++++ ++++static void noinstr el1_watchpt(struct pt_regs *regs, unsigned long esr)
+ +++ ++++{
+++++ ++++ /* Watchpoints are the only debug exception to write FAR_EL1 */
unsigned long far = read_sysreg(far_el1);
arm64_enter_el1_dbg(regs);
exit_to_user_mode(regs);
}
----- ----static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
+++++ ++++static void noinstr el0_breakpt(struct pt_regs *regs, unsigned long esr)
+ {
- --- ---- /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
+++++ ++++ if (!is_ttbr0_addr(regs->pc))
+++++ ++++ arm64_apply_bp_hardening();
+++++ ++++
+++++ ++++ enter_from_user_mode(regs);
+++++ ++++ debug_exception_enter(regs);
+++++ ++++ do_breakpoint(esr, regs);
+++++ ++++ debug_exception_exit(regs);
+++++ ++++ local_daif_restore(DAIF_PROCCTX);
+++++ ++++ exit_to_user_mode(regs);
+++++ ++++}
+++++ ++++
+++++ ++++static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
+++++ ++++{
+++++ ++++ if (!is_ttbr0_addr(regs->pc))
+++++ ++++ arm64_apply_bp_hardening();
+++++ ++++
+++++ ++++ enter_from_user_mode(regs);
+++++ ++++ /*
+++++ ++++ * After handling a breakpoint, we suspend the breakpoint
+++++ ++++ * and use single-step to move to the next instruction.
+++++ ++++ * If we are stepping a suspended breakpoint there's nothing more to do:
+++++ ++++ * the single-step is complete.
+++++ ++++ */
+++++ ++++ if (!try_step_suspended_breakpoints(regs)) {
+++++ ++++ local_daif_restore(DAIF_PROCCTX);
+++++ ++++ do_el0_softstep(esr, regs);
+++++ ++++ }
+++++ ++++ exit_to_user_mode(regs);
+++++ ++++}
+++++ ++++
+++++ ++++static void noinstr el0_watchpt(struct pt_regs *regs, unsigned long esr)
+ +++ ++++{
- /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
+++++ ++++ /* Watchpoints are the only debug exception to write FAR_EL1 */
unsigned long far = read_sysreg(far_el1);
enter_from_user_mode(regs);
die(report_ubsan_failure(esr & UBSAN_BRK_MASK), regs, esr);
return DBG_HOOK_HANDLED;
}
----- ----
----- ----static struct break_hook ubsan_break_hook = {
----- ---- .fn = ubsan_handler,
----- ---- .imm = UBSAN_BRK_IMM,
----- ---- .mask = UBSAN_BRK_MASK,
----- ----};
----- ----#endif
----- ----
----- ----/*
----- ---- * Initial handler for AArch64 BRK exceptions
----- ---- * This handler only used until debug_traps_init().
----- ---- */
----- ----int __init early_brk64(unsigned long addr, unsigned long esr,
----- ---- struct pt_regs *regs)
----- ----{
----- ----#ifdef CONFIG_CFI_CLANG
----- ---- if (esr_is_cfi_brk(esr))
----- ---- return cfi_handler(regs, esr) != DBG_HOOK_HANDLED;
----- ----#endif
----- ----#ifdef CONFIG_KASAN_SW_TAGS
----- ---- if ((esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
----- ---- return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
----- ----#endif
----- ----#ifdef CONFIG_UBSAN_TRAP
----- ---- if (esr_is_ubsan_brk(esr))
----- ---- return ubsan_handler(regs, esr) != DBG_HOOK_HANDLED;
----- ----#endif
----- ---- return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
----- ----}
----- ----
----- ----void __init trap_init(void)
----- ----{
----- ---- register_kernel_break_hook(&bug_break_hook);
----- ----#ifdef CONFIG_CFI_CLANG
----- ---- register_kernel_break_hook(&cfi_break_hook);
----- ----#endif
----- ---- register_kernel_break_hook(&fault_break_hook);
----- ----#ifdef CONFIG_KASAN_SW_TAGS
----- ---- register_kernel_break_hook(&kasan_break_hook);
----- --- #endif
----- --- #ifdef CONFIG_UBSAN_TRAP
----- --- register_kernel_break_hook(&ubsan_break_hook);
#endif
-#ifdef CONFIG_UBSAN_TRAP
- register_kernel_break_hook(&ubsan_break_hook);
-#endif
----- ---- debug_traps_init();
----- ----}