aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2011-08-08 09:26:53 -0400
committerWill Deacon <will.deacon@arm.com>2011-08-31 05:42:48 -0400
commit0d352e3d006c9589f22580212c3822cf62b6d775 (patch)
tree3bfaf9313cab84333380789471b7a9329f3f60fd /arch/arm/kernel/hw_breakpoint.c
parent6f26aa05c9edffff6a4c2cd71774bc659a5cceec (diff)
ARM: hw_breakpoint: trap undef instruction exceptions in reset_ctrl_regs
The ARM debug registers can only be accessed if the DBGSWENABLE signal to the core is driven HIGH by the DAP. The architecture does not provide a way to detect the value of this signal, so the best we can do is register an undef_hook to trap debug register co-processor accesses and then fail if the trap is taken. Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel/hw_breakpoint.c')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 448143e44b65..64ac5c672396 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -857,11 +857,31 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
857/* 857/*
858 * One-time initialisation. 858 * One-time initialisation.
859 */ 859 */
860static void reset_ctrl_regs(void *info) 860static cpumask_t debug_err_mask;
861
862static int debug_reg_trap(struct pt_regs *regs, unsigned int instr)
863{
864 int cpu = smp_processor_id();
865
866 pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n",
867 instr, cpu);
868
869 /* Set the error flag for this CPU and skip the faulting instruction. */
870 cpumask_set_cpu(cpu, &debug_err_mask);
871 instruction_pointer(regs) += 4;
872 return 0;
873}
874
875static struct undef_hook debug_reg_hook = {
876 .instr_mask = 0x0fe80f10,
877 .instr_val = 0x0e000e10,
878 .fn = debug_reg_trap,
879};
880
881static void reset_ctrl_regs(void *unused)
861{ 882{
862 int i, raw_num_brps, err = 0, cpu = smp_processor_id(); 883 int i, raw_num_brps, err = 0, cpu = smp_processor_id();
863 u32 dbg_power; 884 u32 dbg_power;
864 cpumask_t *cpumask = info;
865 885
866 /* 886 /*
867 * v7 debug contains save and restore registers so that debug state 887 * v7 debug contains save and restore registers so that debug state
@@ -893,7 +913,7 @@ static void reset_ctrl_regs(void *info)
893 913
894 if (err) { 914 if (err) {
895 pr_warning("CPU %d debug is powered down!\n", cpu); 915 pr_warning("CPU %d debug is powered down!\n", cpu);
896 cpumask_or(cpumask, cpumask, cpumask_of(cpu)); 916 cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
897 return; 917 return;
898 } 918 }
899 919
@@ -932,6 +952,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self,
932{ 952{
933 if (action == CPU_ONLINE) 953 if (action == CPU_ONLINE)
934 smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1); 954 smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
955
935 return NOTIFY_OK; 956 return NOTIFY_OK;
936} 957}
937 958
@@ -942,7 +963,6 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
942static int __init arch_hw_breakpoint_init(void) 963static int __init arch_hw_breakpoint_init(void)
943{ 964{
944 u32 dscr; 965 u32 dscr;
945 cpumask_t cpumask = { CPU_BITS_NONE };
946 966
947 debug_arch = get_debug_arch(); 967 debug_arch = get_debug_arch();
948 968
@@ -955,21 +975,29 @@ static int __init arch_hw_breakpoint_init(void)
955 core_num_brps = get_num_brps(); 975 core_num_brps = get_num_brps();
956 core_num_wrps = get_num_wrps(); 976 core_num_wrps = get_num_wrps();
957 977
958 pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n", 978 /*
959 core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " : 979 * We need to tread carefully here because DBGSWENABLE may be
960 "", core_num_wrps); 980 * driven low on this core and there isn't an architected way to
981 * determine that.
982 */
983 register_undef_hook(&debug_reg_hook);
961 984
962 /* 985 /*
963 * Reset the breakpoint resources. We assume that a halting 986 * Reset the breakpoint resources. We assume that a halting
964 * debugger will leave the world in a nice state for us. 987 * debugger will leave the world in a nice state for us.
965 */ 988 */
966 on_each_cpu(reset_ctrl_regs, &cpumask, 1); 989 on_each_cpu(reset_ctrl_regs, NULL, 1);
967 if (!cpumask_empty(&cpumask)) { 990 unregister_undef_hook(&debug_reg_hook);
991 if (!cpumask_empty(&debug_err_mask)) {
968 core_num_brps = 0; 992 core_num_brps = 0;
969 core_num_wrps = 0; 993 core_num_wrps = 0;
970 return 0; 994 return 0;
971 } 995 }
972 996
997 pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",
998 core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
999 "", core_num_wrps);
1000
973 ARM_DBG_READ(c1, 0, dscr); 1001 ARM_DBG_READ(c1, 0, dscr);
974 if (dscr & ARM_DSCR_HDBGEN) { 1002 if (dscr & ARM_DSCR_HDBGEN) {
975 max_watchpoint_len = 4; 1003 max_watchpoint_len = 4;