aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/kernel/hw_breakpoint.c28
-rw-r--r--arch/arm64/kernel/suspend.c23
2 files changed, 28 insertions, 23 deletions
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index bcaaac9e14d6..f17f581116fc 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -894,29 +894,10 @@ static struct notifier_block hw_breakpoint_reset_nb = {
894 .notifier_call = hw_breakpoint_reset_notify, 894 .notifier_call = hw_breakpoint_reset_notify,
895}; 895};
896 896
897#ifdef CONFIG_CPU_PM 897#ifdef CONFIG_ARM64_CPU_SUSPEND
898static int hw_breakpoint_cpu_pm_notify(struct notifier_block *self, 898extern void cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *));
899 unsigned long action,
900 void *v)
901{
902 if (action == CPU_PM_EXIT) {
903 hw_breakpoint_reset(NULL);
904 return NOTIFY_OK;
905 }
906
907 return NOTIFY_DONE;
908}
909
910static struct notifier_block hw_breakpoint_cpu_pm_nb = {
911 .notifier_call = hw_breakpoint_cpu_pm_notify,
912};
913
914static void __init hw_breakpoint_pm_init(void)
915{
916 cpu_pm_register_notifier(&hw_breakpoint_cpu_pm_nb);
917}
918#else 899#else
919static inline void hw_breakpoint_pm_init(void) 900static inline void cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *))
920{ 901{
921} 902}
922#endif 903#endif
@@ -947,7 +928,8 @@ static int __init arch_hw_breakpoint_init(void)
947 928
948 /* Register hotplug notifier. */ 929 /* Register hotplug notifier. */
949 register_cpu_notifier(&hw_breakpoint_reset_nb); 930 register_cpu_notifier(&hw_breakpoint_reset_nb);
950 hw_breakpoint_pm_init(); 931 /* Register cpu_suspend hw breakpoint restore hook */
932 cpu_suspend_set_dbg_restorer(hw_breakpoint_reset);
951 933
952 return 0; 934 return 0;
953} 935}
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index e074b1c32723..430344e2c989 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -38,6 +38,22 @@ int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr,
38 return cpu_ops[cpu]->cpu_suspend(arg); 38 return cpu_ops[cpu]->cpu_suspend(arg);
39} 39}
40 40
41/*
42 * This hook is provided so that cpu_suspend code can restore HW
43 * breakpoints as early as possible in the resume path, before reenabling
44 * debug exceptions. Code cannot be run from a CPU PM notifier since by the
45 * time the notifier runs debug exceptions might have been enabled already,
46 * with HW breakpoints registers content still in an unknown state.
47 */
48void (*hw_breakpoint_restore)(void *);
49void __init cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *))
50{
51 /* Prevent multiple restore hook initializations */
52 if (WARN_ON(hw_breakpoint_restore))
53 return;
54 hw_breakpoint_restore = hw_bp_restore;
55}
56
41/** 57/**
42 * cpu_suspend 58 * cpu_suspend
43 * 59 *
@@ -73,6 +89,13 @@ int cpu_suspend(unsigned long arg)
73 if (ret == 0) { 89 if (ret == 0) {
74 cpu_switch_mm(mm->pgd, mm); 90 cpu_switch_mm(mm->pgd, mm);
75 flush_tlb_all(); 91 flush_tlb_all();
92 /*
93 * Restore HW breakpoint registers to sane values
94 * before debug exceptions are possibly reenabled
95 * through local_dbg_restore.
96 */
97 if (hw_breakpoint_restore)
98 hw_breakpoint_restore(NULL);
76 } 99 }
77 100
78 /* 101 /*