aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index d600bd350704..87acc25d7a3e 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -238,8 +238,8 @@ static int enable_monitor_mode(void)
ARM_DBG_READ(c1, 0, dscr);
/* Ensure that halting mode is disabled. */
- if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
- "Unable to access hardware resources.")) {
+ if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
+ "halting debug mode enabled. Unable to access hardware resources.\n")) {
ret = -EPERM;
goto out;
}
@@ -377,7 +377,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
}
}
- if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
+ if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) {
ret = -EBUSY;
goto out;
}
@@ -423,7 +423,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
}
}
- if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+ if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
return;
/* Reset the control register. */
@@ -635,7 +635,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
if (WARN_ONCE(!bp->overflow_handler &&
(arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
|| !bp->hw.bp_target),
- "overflow handler required but none found")) {
+ "overflow handler required but none found\n")) {
ret = -EINVAL;
}
out:
@@ -836,9 +836,11 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
/*
* One-time initialisation.
*/
-static void reset_ctrl_regs(void *unused)
+static void reset_ctrl_regs(void *info)
{
- int i;
+ int i, cpu = smp_processor_id();
+ u32 dbg_power;
+ cpumask_t *cpumask = info;
/*
* v7 debug contains save and restore registers so that debug state
@@ -850,11 +852,29 @@ static void reset_ctrl_regs(void *unused)
*/
if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
/*
+ * Ensure sticky power-down is clear (i.e. debug logic is
+ * powered up).
+ */
+ asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
+ if ((dbg_power & 0x1) == 0) {
+ pr_warning("CPU %d debug is powered down!\n", cpu);
+ cpumask_or(cpumask, cpumask, cpumask_of(cpu));
+ return;
+ }
+
+ /*
* Unconditionally clear the lock by writing a value
* other than 0xC5ACCE55 to the access register.
*/
asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
isb();
+
+ /*
+ * Clear any configured vector-catch events before
+ * enabling monitor mode.
+ */
+ asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+ isb();
}
if (enable_monitor_mode())
@@ -887,6 +907,7 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
static int __init arch_hw_breakpoint_init(void)
{
u32 dscr;
+ cpumask_t cpumask = { CPU_BITS_NONE };
debug_arch = get_debug_arch();
@@ -911,13 +932,19 @@ static int __init arch_hw_breakpoint_init(void)
* Reset the breakpoint resources. We assume that a halting
* debugger will leave the world in a nice state for us.
*/
- on_each_cpu(reset_ctrl_regs, NULL, 1);
+ on_each_cpu(reset_ctrl_regs, &cpumask, 1);
+ if (!cpumask_empty(&cpumask)) {
+ core_num_brps = 0;
+ core_num_reserved_brps = 0;
+ core_num_wrps = 0;
+ return 0;
+ }
ARM_DBG_READ(c1, 0, dscr);
if (dscr & ARM_DSCR_HDBGEN) {
max_watchpoint_len = 4;
- pr_warning("halting debug mode enabled. Assuming maximum "
- "watchpoint size of %u bytes.", max_watchpoint_len);
+ pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n",
+ max_watchpoint_len);
} else {
/* Work out the maximum supported watchpoint length. */
max_watchpoint_len = get_max_wp_len();