summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-10-26 16:49:01 +0530
committerJonas ABERG <jonas.aberg@stericsson.com>2011-10-27 11:35:17 +0200
commit61ba02cb47304cd486811ae5377f399a8ecd1eb4 (patch)
treed3e671e15f4e9a4246a4b955380627a7fd8069c4 /arch
parent47d191541803bf372b744b5ba6d28b181e42c430 (diff)
ARM: hw_breakpoint: don't fault when debug is not powered
If the debug logic is not powered, the processor can unfortunately raise an undefined instruction exception on the instruction that we use to check if the debug logic is powered up or not. Handle this with an undef hook, so that the kernel doesn't crash on boot on such setups. ST-Ericsson ID: 370131 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I5802811ac0676d3d13782897b6941dcaee3e4721 Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35326 Reviewed-by: QABUILD Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 87acc25d7a3..3c7ac7d9932 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -833,6 +833,25 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
return ret;
}
+static int hw_breakpoint_undef(struct pt_regs *regs, unsigned int instr)
+{
+ int reg = (instr >> 12) & 15;
+
+ /* Fake sticky power-down cleared */
+ regs->uregs[reg] = 0;
+ regs->ARM_pc += 4;
+
+ return 0;
+}
+
+static struct undef_hook hw_breakpoint_hook = {
+ .instr_mask = 0xffff0fff,
+ .instr_val = 0xee110e95,
+ .cpsr_mask = MODE_MASK,
+ .cpsr_val = SVC_MODE,
+ .fn = hw_breakpoint_undef,
+};
+
/*
* One-time initialisation.
*/
@@ -854,6 +873,10 @@ static void reset_ctrl_regs(void *info)
/*
* Ensure sticky power-down is clear (i.e. debug logic is
* powered up).
+ *
+ * This could raise an undefined instruction exception. If it
+ * does, it is fixed up with an undef hook which constructs
+ * a fake value with the sticky power-down bit cleared.
*/
asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
if ((dbg_power & 0x1) == 0) {
@@ -928,6 +951,8 @@ static int __init arch_hw_breakpoint_init(void)
pr_info("%d breakpoint(s) reserved for watchpoint "
"single-step.\n", core_num_reserved_brps);
+ register_undef_hook(&hw_breakpoint_hook);
+
/*
* Reset the breakpoint resources. We assume that a halting
* debugger will leave the world in a nice state for us.