aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-11-24 11:51:17 -0500
committerWill Deacon <will.deacon@arm.com>2010-12-06 06:55:56 -0500
commitac88e07122fc0eb5cbad403be97ef02c317a06b7 (patch)
tree0cddfd29474fc4ff5a1be95d2273d3a1e626055f
parente8a7e48bb248a1196484d3f8afa53bded2b24e71 (diff)
ARM: hw_breakpoint: ensure OS lock is clear before writing to debug registers
ARMv7 architects a system for saving and restoring the debug registers across low-power modes. At the heart of this system is a lock register which, when set, forbids writes to the debug registers. While locked, writes to debug registers via the co-processor interface will result in undefined instruction traps. Linux currently doesn't make use of this feature because we update the debug registers on context switch anyway, however the status of the lock is IMPLEMENTATION DEFINED on reset. This patch ensures that the lock is cleared during boot so that we can write to the debug registers safely. Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm/kernel/hw_breakpoint.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 21e3a4ab3b8c..793959ec8982 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -768,6 +768,23 @@ static void __init reset_ctrl_regs(void *unused)
768{ 768{
769 int i; 769 int i;
770 770
771 /*
772 * v7 debug contains save and restore registers so that debug state
773 * can be maintained across low-power modes without leaving
774 * the debug logic powered up. It is IMPLEMENTATION DEFINED whether
775 * we can write to the debug registers out of reset, so we must
776 * unlock the OS Lock Access Register to avoid taking undefined
777 * instruction exceptions later on.
778 */
779 if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
780 /*
781 * Unconditionally clear the lock by writing a value
782 * other than 0xC5ACCE55 to the access register.
783 */
784 asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
785 isb();
786 }
787
771 if (enable_monitor_mode()) 788 if (enable_monitor_mode())
772 return; 789 return;
773 790
@@ -810,17 +827,17 @@ static int __init arch_hw_breakpoint_init(void)
810 pr_warning("halting debug mode enabled. Assuming maximum " 827 pr_warning("halting debug mode enabled. Assuming maximum "
811 "watchpoint size of 4 bytes."); 828 "watchpoint size of 4 bytes.");
812 } else { 829 } else {
813 /* Work out the maximum supported watchpoint length. */
814 max_watchpoint_len = get_max_wp_len();
815 pr_info("maximum watchpoint size is %u bytes.\n",
816 max_watchpoint_len);
817
818 /* 830 /*
819 * Reset the breakpoint resources. We assume that a halting 831 * Reset the breakpoint resources. We assume that a halting
820 * debugger will leave the world in a nice state for us. 832 * debugger will leave the world in a nice state for us.
821 */ 833 */
822 smp_call_function(reset_ctrl_regs, NULL, 1); 834 smp_call_function(reset_ctrl_regs, NULL, 1);
823 reset_ctrl_regs(NULL); 835 reset_ctrl_regs(NULL);
836
837 /* Work out the maximum supported watchpoint length. */
838 max_watchpoint_len = get_max_wp_len();
839 pr_info("maximum watchpoint size is %u bytes.\n",
840 max_watchpoint_len);
824 } 841 }
825 842
826 /* Register debug fault handler. */ 843 /* Register debug fault handler. */