Skip to content

Commit

Permalink
ARM: hw_breakpoint: do not fail initcall if monitor mode is disabled
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Will Deacon committed Dec 15, 2010
1 parent 4a55c18 commit 8fbf397
Showing 1 changed file with 25 additions and 29 deletions.
54 changes: 25 additions & 29 deletions arch/arm/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,23 +219,6 @@ static int get_num_brps(void)
return brps;
}

int hw_breakpoint_slots(int type)
{
/*
* We can be called early, so don't rely on
* our static variables being initialised.
*/
switch (type) {
case TYPE_INST:
return get_num_brps();
case TYPE_DATA:
return get_num_wrps();
default:
pr_warning("unknown slot type: %d\n", type);
return 0;
}
}

/*
* In order to access the breakpoint/watchpoint control registers,
* we must be running in debug monitor mode. Unfortunately, we can
Expand All @@ -256,8 +239,12 @@ static int enable_monitor_mode(void)
goto out;
}

/* If monitor mode is already enabled, just return. */
if (dscr & ARM_DSCR_MDBGEN)
goto out;

/* Write to the corresponding DSCR. */
switch (debug_arch) {
switch (get_debug_arch()) {
case ARM_DEBUG_ARCH_V6:
case ARM_DEBUG_ARCH_V6_1:
ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
Expand All @@ -272,15 +259,30 @@ static int enable_monitor_mode(void)

/* Check that the write made it through. */
ARM_DBG_READ(c1, 0, dscr);
if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
"failed to enable monitor mode.")) {
if (!(dscr & ARM_DSCR_MDBGEN))
ret = -EPERM;
}

out:
return ret;
}

int hw_breakpoint_slots(int type)
{
/*
* We can be called early, so don't rely on
* our static variables being initialised.
*/
switch (type) {
case TYPE_INST:
return get_num_brps();
case TYPE_DATA:
return get_num_wrps();
default:
pr_warning("unknown slot type: %d\n", type);
return 0;
}
}

/*
* Check if 8-bit byte-address select is available.
* This clobbers WRP 0.
Expand All @@ -294,9 +296,6 @@ static u8 get_max_wp_len(void)
if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
goto out;

if (enable_monitor_mode())
goto out;

memset(&ctrl, 0, sizeof(ctrl));
ctrl.len = ARM_BREAKPOINT_LEN_8;
ctrl_reg = encode_ctrl_reg(ctrl);
Expand Down Expand Up @@ -879,15 +878,13 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {

static int __init arch_hw_breakpoint_init(void)
{
int ret = 0;
u32 dscr;

debug_arch = get_debug_arch();

if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
ret = -ENODEV;
goto out;
return 0;
}

/* Determine how many BRPs/WRPs are available. */
Expand Down Expand Up @@ -928,8 +925,7 @@ static int __init arch_hw_breakpoint_init(void)

/* Register hotplug notifier. */
register_cpu_notifier(&dbg_reset_nb);
out:
return ret;
return 0;
}
arch_initcall(arch_hw_breakpoint_init);

Expand Down

0 comments on commit 8fbf397

Please sign in to comment.