aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-12-01 12:37:45 -0500
committerWill Deacon <will.deacon@arm.com>2010-12-15 07:31:03 -0500
commit8fbf397c3389c1dedfa9ee412715046ab28fd82d (patch)
treeb363718fb46602f882cfb58d372ec6746e3f92c5 /arch/arm/kernel/hw_breakpoint.c
parent4a55c18e2023096c8684fae5fa1cfa96a03172ff (diff)
ARM: hw_breakpoint: do not fail initcall if monitor mode is disabled
The debug registers can only be manipulated from software if monitor debug mode is enabled. On some cores, this can never be enabled (i.e. the corresponding bit in the DSCR is RAZ/WI). This patch ensures we can handle this hardware configuration and fail gracefully, rather than blow up the kernel during boot. Reported-by: Cyril Chemparathy <cyril@ti.com> 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.c54
1 files changed, 25 insertions, 29 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 56ed9a62013b..c9f3f0467570 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -219,23 +219,6 @@ static int get_num_brps(void)
219 return brps; 219 return brps;
220} 220}
221 221
222int hw_breakpoint_slots(int type)
223{
224 /*
225 * We can be called early, so don't rely on
226 * our static variables being initialised.
227 */
228 switch (type) {
229 case TYPE_INST:
230 return get_num_brps();
231 case TYPE_DATA:
232 return get_num_wrps();
233 default:
234 pr_warning("unknown slot type: %d\n", type);
235 return 0;
236 }
237}
238
239/* 222/*
240 * In order to access the breakpoint/watchpoint control registers, 223 * In order to access the breakpoint/watchpoint control registers,
241 * we must be running in debug monitor mode. Unfortunately, we can 224 * we must be running in debug monitor mode. Unfortunately, we can
@@ -256,8 +239,12 @@ static int enable_monitor_mode(void)
256 goto out; 239 goto out;
257 } 240 }
258 241
242 /* If monitor mode is already enabled, just return. */
243 if (dscr & ARM_DSCR_MDBGEN)
244 goto out;
245
259 /* Write to the corresponding DSCR. */ 246 /* Write to the corresponding DSCR. */
260 switch (debug_arch) { 247 switch (get_debug_arch()) {
261 case ARM_DEBUG_ARCH_V6: 248 case ARM_DEBUG_ARCH_V6:
262 case ARM_DEBUG_ARCH_V6_1: 249 case ARM_DEBUG_ARCH_V6_1:
263 ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN)); 250 ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
@@ -272,15 +259,30 @@ static int enable_monitor_mode(void)
272 259
273 /* Check that the write made it through. */ 260 /* Check that the write made it through. */
274 ARM_DBG_READ(c1, 0, dscr); 261 ARM_DBG_READ(c1, 0, dscr);
275 if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN), 262 if (!(dscr & ARM_DSCR_MDBGEN))
276 "failed to enable monitor mode.")) {
277 ret = -EPERM; 263 ret = -EPERM;
278 }
279 264
280out: 265out:
281 return ret; 266 return ret;
282} 267}
283 268
269int hw_breakpoint_slots(int type)
270{
271 /*
272 * We can be called early, so don't rely on
273 * our static variables being initialised.
274 */
275 switch (type) {
276 case TYPE_INST:
277 return get_num_brps();
278 case TYPE_DATA:
279 return get_num_wrps();
280 default:
281 pr_warning("unknown slot type: %d\n", type);
282 return 0;
283 }
284}
285
284/* 286/*
285 * Check if 8-bit byte-address select is available. 287 * Check if 8-bit byte-address select is available.
286 * This clobbers WRP 0. 288 * This clobbers WRP 0.
@@ -294,9 +296,6 @@ static u8 get_max_wp_len(void)
294 if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14) 296 if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
295 goto out; 297 goto out;
296 298
297 if (enable_monitor_mode())
298 goto out;
299
300 memset(&ctrl, 0, sizeof(ctrl)); 299 memset(&ctrl, 0, sizeof(ctrl));
301 ctrl.len = ARM_BREAKPOINT_LEN_8; 300 ctrl.len = ARM_BREAKPOINT_LEN_8;
302 ctrl_reg = encode_ctrl_reg(ctrl); 301 ctrl_reg = encode_ctrl_reg(ctrl);
@@ -879,15 +878,13 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
879 878
880static int __init arch_hw_breakpoint_init(void) 879static int __init arch_hw_breakpoint_init(void)
881{ 880{
882 int ret = 0;
883 u32 dscr; 881 u32 dscr;
884 882
885 debug_arch = get_debug_arch(); 883 debug_arch = get_debug_arch();
886 884
887 if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) { 885 if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
888 pr_info("debug architecture 0x%x unsupported.\n", debug_arch); 886 pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
889 ret = -ENODEV; 887 return 0;
890 goto out;
891 } 888 }
892 889
893 /* Determine how many BRPs/WRPs are available. */ 890 /* Determine how many BRPs/WRPs are available. */
@@ -928,8 +925,7 @@ static int __init arch_hw_breakpoint_init(void)
928 925
929 /* Register hotplug notifier. */ 926 /* Register hotplug notifier. */
930 register_cpu_notifier(&dbg_reset_nb); 927 register_cpu_notifier(&dbg_reset_nb);
931out: 928 return 0;
932 return ret;
933} 929}
934arch_initcall(arch_hw_breakpoint_init); 930arch_initcall(arch_hw_breakpoint_init);
935 931