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
This commit is contained in:
parent
4a8240ec66
commit
9ae1207bcf
@ -82,8 +82,6 @@ static boolean_t dbg_ossr; /* OS Save and Restore implemented */
|
||||
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_t val)
|
||||
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);
|
||||
|
||||
@ -571,34 +582,6 @@ dbg_enable_monitor(void)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -702,13 +685,6 @@ dbg_setup_xpoint(struct dbg_wb_conf *conf)
|
||||
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 *conf)
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user