svn commit: r300968 - head/sys/arm/arm
Zbigniew Bodek
zbb at FreeBSD.org
Sun May 29 17:33:50 UTC 2016
Author: zbb
Date: Sun May 29 17:33:49 2016
New Revision: 300968
URL: https://svnweb.freebsd.org/changeset/base/300968
Log:
Fix debug_monitor code for older ARMs (ARM11)
- Enable monitor mode prior to accessing watchpoint
registers for v6, v6.1 architectures.
- Fix configuration scheme for v6, v6.1 and v7 Debug Archs
- Enable monitor unconditionally and for good instead
of enabling and disabling it (needed for single stepping
on on v6/v6.1)
Tested on RPI-B and Arndale
Differential Revision: https://reviews.freebsd.org/D6008
Modified:
head/sys/arm/arm/debug_monitor.c
Modified: head/sys/arm/arm/debug_monitor.c
==============================================================================
--- head/sys/arm/arm/debug_monitor.c Sun May 29 17:32:19 2016 (r300967)
+++ head/sys/arm/arm/debug_monitor.c Sun May 29 17:33:49 2016 (r300968)
@@ -82,8 +82,6 @@ static boolean_t dbg_ossr; /* OS Save an
static uint32_t dbg_watchpoint_num;
static uint32_t dbg_breakpoint_num;
-static int dbg_ref_count_mme; /* Times monitor mode was enabled */
-
/* ID_DFR0 - Debug Feature Register 0 */
#define ID_DFR0_CP_DEBUG_M_SHIFT 0
#define ID_DFR0_CP_DEBUG_M_MASK (0xF << ID_DFR0_CP_DEBUG_M_SHIFT)
@@ -250,6 +248,13 @@ dbg_wb_write_reg(int reg, int n, uint32_
boolean_t
kdb_cpu_pc_is_singlestep(db_addr_t pc)
{
+ /*
+ * XXX: If the platform fails to enable its debug arch.
+ * there will be no stepping capabilities
+ * (SOFTWARE_SSTEP is not defined for __ARM_ARCH >= 6).
+ */
+ if (!dbg_capable)
+ return (FALSE);
if (dbg_find_slot(DBG_TYPE_BREAKPOINT, pc) != ~0U)
return (TRUE);
@@ -265,6 +270,9 @@ kdb_cpu_set_singlestep(void)
uint32_t wcr;
u_int i;
+ if (!dbg_capable)
+ return;
+
/*
* Disable watchpoints, e.g. stepping over watched instruction will
* trigger break exception instead of single-step exception and locks
@@ -295,6 +303,9 @@ kdb_cpu_clear_singlestep(void)
uint32_t wvr, wcr;
u_int i;
+ if (!dbg_capable)
+ return;
+
dbg_remove_breakpoint(DBG_BKPT_BT_SLOT);
dbg_remove_breakpoint(DBG_BKPT_BNT_SLOT);
@@ -572,34 +583,6 @@ dbg_enable_monitor(void)
}
static int
-dbg_disable_monitor(void)
-{
- uint32_t dbg_dscr;
-
- if (!dbg_monitor_is_enabled())
- return (0);
-
- dbg_dscr = cp14_dbgdscrint_get();
- switch (dbg_model) {
- case ID_DFR0_CP_DEBUG_M_V6:
- case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
- dbg_dscr &= ~DBGSCR_MDBG_EN;
- cp14_dbgdscr_v6_set(dbg_dscr);
- break;
- case ID_DFR0_CP_DEBUG_M_V7: /* fall through */
- case ID_DFR0_CP_DEBUG_M_V7_1:
- dbg_dscr &= ~DBGSCR_MDBG_EN;
- cp14_dbgdscr_v7_set(dbg_dscr);
- break;
- default:
- return (ENXIO);
- }
- isb();
-
- return (0);
-}
-
-static int
dbg_setup_xpoint(struct dbg_wb_conf *conf)
{
struct pcpu *pcpu;
@@ -702,13 +685,6 @@ dbg_setup_xpoint(struct dbg_wb_conf *con
dbg_wb_write_reg(reg_addr, i, addr);
dbg_wb_write_reg(reg_ctrl, i, ctrl);
- err = dbg_enable_monitor();
- if (err != 0)
- return (err);
-
- /* Increment monitor enable counter */
- dbg_ref_count_mme++;
-
/*
* Save watchpoint settings for all CPUs.
* We don't need to do the same with breakpoints since HW breakpoints
@@ -775,19 +751,6 @@ dbg_remove_xpoint(struct dbg_wb_conf *co
dbg_wb_write_reg(reg_ctrl, i, 0);
dbg_wb_write_reg(reg_addr, i, 0);
- /* Decrement monitor enable counter */
- dbg_ref_count_mme--;
- if (dbg_ref_count_mme < 0)
- dbg_ref_count_mme = 0;
-
- atomic_thread_fence_rel();
-
- if (dbg_ref_count_mme == 0) {
- err = dbg_disable_monitor();
- if (err != 0)
- return (err);
- }
-
/*
* Save watchpoint settings for all CPUs.
* We don't need to do the same with breakpoints since HW breakpoints
@@ -827,7 +790,7 @@ dbg_get_ossr(void)
{
switch (dbg_model) {
- case ID_DFR0_CP_DEBUG_M_V6_1:
+ case ID_DFR0_CP_DEBUG_M_V7:
if ((cp14_dbgoslsr_get() & DBGOSLSR_OSLM0) != 0)
return (TRUE);
@@ -844,10 +807,8 @@ dbg_arch_supported(void)
{
switch (dbg_model) {
-#ifdef not_yet
case ID_DFR0_CP_DEBUG_M_V6:
case ID_DFR0_CP_DEBUG_M_V6_1:
-#endif
case ID_DFR0_CP_DEBUG_M_V7:
case ID_DFR0_CP_DEBUG_M_V7_1: /* fall through */
return (TRUE);
@@ -889,9 +850,16 @@ dbg_reset_state(void)
switch (dbg_model) {
case ID_DFR0_CP_DEBUG_M_V6:
- /* v6 Debug logic reset upon power-up */
- return (0);
- case ID_DFR0_CP_DEBUG_M_V6_1:
+ case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
+ /*
+ * Arch needs monitor mode selected and enabled
+ * to be able to access breakpoint/watchpoint registers.
+ */
+ err = dbg_enable_monitor();
+ if (err != 0)
+ return (err);
+ goto vectr_clr;
+ case ID_DFR0_CP_DEBUG_M_V7:
/* Is core power domain powered up? */
if ((cp14_dbgprsr_get() & DBGPRSR_PU) == 0)
err = ENXIO;
@@ -902,8 +870,6 @@ dbg_reset_state(void)
if (dbg_ossr)
goto vectr_clr;
break;
- case ID_DFR0_CP_DEBUG_M_V7:
- break;
case ID_DFR0_CP_DEBUG_M_V7_1:
/* Is double lock set? */
if ((cp14_dbgosdlr_get() & DBGPRSR_DLK) != 0)
@@ -998,8 +964,11 @@ dbg_monitor_init(void)
err = dbg_reset_state();
if (err == 0) {
- dbg_capable = TRUE;
- return;
+ err = dbg_enable_monitor();
+ if (err == 0) {
+ dbg_capable = TRUE;
+ return;
+ }
}
db_printf("HW Breakpoints/Watchpoints not enabled on CPU%d\n",
@@ -1050,21 +1019,6 @@ dbg_resume_dbreg(void)
dbg_wb_write_reg(DBG_REG_BASE_WCR, i, d->dbg_wcr[i]);
}
- if ((dbg_ref_count_mme > 0) && !dbg_monitor_is_enabled()) {
- err = dbg_enable_monitor();
- if (err != 0) {
- panic("%s: Failed to enable Debug Monitor "
- "on CPU%d", __func__, cpuid);
- }
- }
- if ((dbg_ref_count_mme == 0) && dbg_monitor_is_enabled()) {
- err = dbg_disable_monitor();
- if (err != 0) {
- panic("%s: Failed to disable Debug Monitor "
- "on CPU%d", __func__, cpuid);
- }
- }
-
PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
break;
}
More information about the svn-src-all
mailing list