diff options
| author | Dietmar Eggemann <dietmar.eggemann@arm.com> | 2012-10-14 17:25:37 -0400 |
|---|---|---|
| committer | Will Deacon <will.deacon@arm.com> | 2013-01-10 16:13:07 -0500 |
| commit | 9a6eb310eaa5336b89a27a0bbb78da4bba35f6f1 (patch) | |
| tree | 50975e4e50ffd1d91b44dfe2e389161697751a3c | |
| parent | 57ba899731156ab01cdb7dae8d1fe6430ef4957c (diff) | |
ARM: hw_breakpoint: Debug powerdown support for self-hosted debug
This patch introduces debug powerdown support for self-hosted debug for v7
and v7.1 debug architecture for a SinglePower system, i.e. a system without a
separate core and debug power domain. On a SinglePower system the OS Lock is
lost over a powerdown.
If CONFIG_CPU_PM is set the new function pm_init() registers hw_breakpoint
with CPU PM for a system supporting OS Save and Restore.
Receiving a CPU PM EXIT notifier indicates that a single CPU has exited a low
power state. A call to reset_ctrl_regs() is hooked into the CPU PM EXIT
notifier chain. This function makes sure that the sticky power-down is clear
(only v7 debug), the OS Double Lock is clear (only v7.1 debug) and it clears
the OS Lock for v7 debug (for a system supporting OS Save and Restore) and
v7.1 debug. Furthermore, it clears any vector-catch events and all
breakpoint/watchpoint control/value registers for v7 and v7.1 debug.
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
[will: removed redundant has_ossr check]
Signed-off-by: Will Deacon <will.deacon@arm.com>
| -rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 201d4406fe0d..5eae53e7a2e1 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/perf_event.h> | 28 | #include <linux/perf_event.h> |
| 29 | #include <linux/hw_breakpoint.h> | 29 | #include <linux/hw_breakpoint.h> |
| 30 | #include <linux/smp.h> | 30 | #include <linux/smp.h> |
| 31 | #include <linux/cpu_pm.h> | ||
| 31 | 32 | ||
| 32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
| 33 | #include <asm/cputype.h> | 34 | #include <asm/cputype.h> |
| @@ -1032,6 +1033,30 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = { | |||
| 1032 | .notifier_call = dbg_reset_notify, | 1033 | .notifier_call = dbg_reset_notify, |
| 1033 | }; | 1034 | }; |
| 1034 | 1035 | ||
| 1036 | #ifdef CONFIG_CPU_PM | ||
| 1037 | static int dbg_cpu_pm_notify(struct notifier_block *self, unsigned long action, | ||
| 1038 | void *v) | ||
| 1039 | { | ||
| 1040 | if (action == CPU_PM_EXIT) | ||
| 1041 | reset_ctrl_regs(NULL); | ||
| 1042 | |||
| 1043 | return NOTIFY_OK; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static struct notifier_block __cpuinitdata dbg_cpu_pm_nb = { | ||
| 1047 | .notifier_call = dbg_cpu_pm_notify, | ||
| 1048 | }; | ||
| 1049 | |||
| 1050 | static void __init pm_init(void) | ||
| 1051 | { | ||
| 1052 | cpu_pm_register_notifier(&dbg_cpu_pm_nb); | ||
| 1053 | } | ||
| 1054 | #else | ||
| 1055 | static inline void pm_init(void) | ||
| 1056 | { | ||
| 1057 | } | ||
| 1058 | #endif | ||
| 1059 | |||
| 1035 | static int __init arch_hw_breakpoint_init(void) | 1060 | static int __init arch_hw_breakpoint_init(void) |
| 1036 | { | 1061 | { |
| 1037 | debug_arch = get_debug_arch(); | 1062 | debug_arch = get_debug_arch(); |
| @@ -1081,8 +1106,9 @@ static int __init arch_hw_breakpoint_init(void) | |||
| 1081 | hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, | 1106 | hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, |
| 1082 | TRAP_HWBKPT, "breakpoint debug exception"); | 1107 | TRAP_HWBKPT, "breakpoint debug exception"); |
| 1083 | 1108 | ||
| 1084 | /* Register hotplug notifier. */ | 1109 | /* Register hotplug and PM notifiers. */ |
| 1085 | register_cpu_notifier(&dbg_reset_nb); | 1110 | register_cpu_notifier(&dbg_reset_nb); |
| 1111 | pm_init(); | ||
| 1086 | return 0; | 1112 | return 0; |
| 1087 | } | 1113 | } |
| 1088 | arch_initcall(arch_hw_breakpoint_init); | 1114 | arch_initcall(arch_hw_breakpoint_init); |
