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 /arch/arm/kernel | |
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>
Diffstat (limited to 'arch/arm/kernel')
-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); |