ARM DPM: share debug reason logic
No point in both ARM11 and Cortex-A8 having private copies of the logic sorting out e.g. DBG_REASON_WATCHPOINT. Add and use a shared routine for this ... there's actually a bunch more debug entry logic that could be shared, this is just a start on that. Note that this routine fixes a bug observed in the ARM11 code, where some abort mode quirks were displayed as being an unknown debug reason; and also silences needless ARM11 chatter. Likewise with private copies of DSCR ... add one to the DPM struct. Save it as part of setting DBG_REASON_* so later patches can switch over to using that copy. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>__archive__
parent
6eee0729d7
commit
ea7a49cb9b
|
@ -83,8 +83,7 @@ static int arm11_check_init(struct arm11_common *arm11)
|
|||
*/
|
||||
|
||||
arm11->arm.target->state = TARGET_HALTED;
|
||||
arm11->arm.target->debug_reason =
|
||||
arm11_get_DSCR_debug_reason(arm11->dscr);
|
||||
arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -108,8 +107,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
|
|||
int retval;
|
||||
|
||||
arm11->arm.target->state = TARGET_HALTED;
|
||||
arm11->arm.target->debug_reason =
|
||||
arm11_get_DSCR_debug_reason(arm11->dscr);
|
||||
arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
|
||||
|
||||
/* REVISIT entire cache should already be invalid !!! */
|
||||
register_cache_invalidate(arm11->arm.core_cache);
|
||||
|
@ -551,20 +549,12 @@ static int arm11_resume(struct target *target, int current,
|
|||
i++;
|
||||
}
|
||||
|
||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||
if (!debug_execution)
|
||||
{
|
||||
target->state = TARGET_RUNNING;
|
||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||
|
||||
CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
|
||||
}
|
||||
target->state = TARGET_RUNNING;
|
||||
else
|
||||
{
|
||||
target->state = TARGET_DEBUG_RUNNING;
|
||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||
|
||||
CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
|
||||
}
|
||||
target->state = TARGET_DEBUG_RUNNING;
|
||||
CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -728,7 +718,7 @@ static int arm11_step(struct target *target, int current,
|
|||
|
||||
}
|
||||
|
||||
target->debug_reason = DBG_REASON_SINGLESTEP;
|
||||
target->debug_reason = DBG_REASON_SINGLESTEP;
|
||||
|
||||
CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
|
||||
|
||||
|
|
|
@ -94,18 +94,6 @@ enum arm11_instructions
|
|||
ARM11_BYPASS = 0x1F,
|
||||
};
|
||||
|
||||
enum arm11_dscr
|
||||
{
|
||||
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK = 0x0F << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT = 0x00 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT = 0x01 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT = 0x02 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION = 0x03 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ = 0x04 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH = 0x05 << 2,
|
||||
};
|
||||
|
||||
enum arm11_sc7
|
||||
{
|
||||
ARM11_SC7_NULL = 0,
|
||||
|
|
|
@ -288,50 +288,6 @@ int arm11_write_DSCR(struct arm11_common * arm11, uint32_t dscr)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Get the debug reason from Debug Status and Control Register (DSCR)
|
||||
*
|
||||
* \param dscr DSCR value to analyze
|
||||
* \return Debug reason
|
||||
*
|
||||
*/
|
||||
enum target_debug_reason arm11_get_DSCR_debug_reason(uint32_t dscr)
|
||||
{
|
||||
switch (dscr & ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK)
|
||||
{
|
||||
case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT:
|
||||
LOG_INFO("Debug entry: JTAG HALT");
|
||||
return DBG_REASON_DBGRQ;
|
||||
|
||||
case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT:
|
||||
LOG_INFO("Debug entry: breakpoint");
|
||||
return DBG_REASON_BREAKPOINT;
|
||||
|
||||
case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT:
|
||||
LOG_INFO("Debug entry: watchpoint");
|
||||
return DBG_REASON_WATCHPOINT;
|
||||
|
||||
case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION:
|
||||
LOG_INFO("Debug entry: BKPT instruction");
|
||||
return DBG_REASON_BREAKPOINT;
|
||||
|
||||
case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ:
|
||||
LOG_INFO("Debug entry: EDBGRQ signal");
|
||||
return DBG_REASON_DBGRQ;
|
||||
|
||||
case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH:
|
||||
LOG_INFO("Debug entry: VCR vector catch");
|
||||
return DBG_REASON_BREAKPOINT;
|
||||
|
||||
default:
|
||||
LOG_INFO("Debug entry: unknown");
|
||||
return DBG_REASON_DBGRQ;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Prepare the stage for ITR/DTR operations
|
||||
* from the arm11_run_instr... group of functions.
|
||||
*
|
||||
|
|
|
@ -14,8 +14,6 @@ int arm11_add_debug_SCAN_N(struct arm11_common *arm11,
|
|||
int arm11_read_DSCR(struct arm11_common *arm11);
|
||||
int arm11_write_DSCR(struct arm11_common *arm11, uint32_t dscr);
|
||||
|
||||
enum target_debug_reason arm11_get_DSCR_debug_reason(uint32_t dscr);
|
||||
|
||||
int arm11_run_instr_data_prepare(struct arm11_common *arm11);
|
||||
int arm11_run_instr_data_finish(struct arm11_common *arm11);
|
||||
int arm11_run_instr_no_data1(struct arm11_common *arm11, uint32_t opcode);
|
||||
|
|
|
@ -755,6 +755,42 @@ void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr)
|
|||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Other debug and support utilities
|
||||
*/
|
||||
|
||||
void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
|
||||
{
|
||||
struct target *target = dpm->arm->target;
|
||||
|
||||
dpm->dscr = dscr;
|
||||
|
||||
/* Examine debug reason */
|
||||
switch (DSCR_ENTRY(dscr)) {
|
||||
case 6: /* Data abort (v6 only) */
|
||||
case 7: /* Prefetch abort (v6 only) */
|
||||
/* FALL THROUGH -- assume a v6 core in abort mode */
|
||||
case 0: /* HALT request from debugger */
|
||||
case 4: /* EDBGRQ */
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
break;
|
||||
case 1: /* HW breakpoint */
|
||||
case 3: /* SW BKPT */
|
||||
case 5: /* vector catch */
|
||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||
break;
|
||||
case 2: /* asynch watchpoint */
|
||||
case 10: /* precise watchpoint */
|
||||
target->debug_reason = DBG_REASON_WATCHPOINT;
|
||||
break;
|
||||
default:
|
||||
target->debug_reason = DBG_REASON_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup and management support.
|
||||
*/
|
||||
|
|
|
@ -125,6 +125,9 @@ struct arm_dpm {
|
|||
/** Address of the instruction which triggered a watchpoint. */
|
||||
uint32_t wp_pc;
|
||||
|
||||
/** Recent value of DSCR. */
|
||||
uint32_t dscr;
|
||||
|
||||
// FIXME -- read/write DCSR methods and symbols
|
||||
};
|
||||
|
||||
|
@ -151,4 +154,6 @@ void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar);
|
|||
|
||||
#define DSCR_ENTRY(dscr) (((dscr) >> 2) & 0xf)
|
||||
|
||||
void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr);
|
||||
|
||||
#endif /* __ARM_DPM_H */
|
||||
|
|
|
@ -782,7 +782,7 @@ static int cortex_a8_resume(struct target *target, int current,
|
|||
static int cortex_a8_debug_entry(struct target *target)
|
||||
{
|
||||
int i;
|
||||
uint32_t regfile[16], wfar, cpsr, dscr;
|
||||
uint32_t regfile[16], cpsr, dscr;
|
||||
int retval = ERROR_OK;
|
||||
struct working_area *regfile_working_area = NULL;
|
||||
struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
|
||||
|
@ -793,6 +793,7 @@ static int cortex_a8_debug_entry(struct target *target)
|
|||
|
||||
LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a8->cpudbg_dscr);
|
||||
|
||||
/* REVISIT surely we should not re-read DSCR !! */
|
||||
mem_ap_read_atomic_u32(swjdp,
|
||||
armv7a->debug_base + CPUDBG_DSCR, &dscr);
|
||||
|
||||
|
@ -807,30 +808,16 @@ static int cortex_a8_debug_entry(struct target *target)
|
|||
armv7a->debug_base + CPUDBG_DSCR, dscr);
|
||||
|
||||
/* Examine debug reason */
|
||||
switch (DSCR_ENTRY(cortex_a8->cpudbg_dscr))
|
||||
{
|
||||
case 0: /* DRCR[0] write */
|
||||
case 4: /* EDBGRQ */
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
break;
|
||||
case 1: /* HW breakpoint */
|
||||
case 3: /* SW BKPT */
|
||||
case 5: /* vector catch */
|
||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||
break;
|
||||
case 2: /* asynch watchpoint */
|
||||
case 10: /* precise watchpoint */
|
||||
target->debug_reason = DBG_REASON_WATCHPOINT;
|
||||
arm_dpm_report_dscr(&armv7a->dpm, cortex_a8->cpudbg_dscr);
|
||||
|
||||
/* save address of faulting instruction */
|
||||
retval = mem_ap_read_atomic_u32(swjdp,
|
||||
armv7a->debug_base + CPUDBG_WFAR,
|
||||
&wfar);
|
||||
arm_dpm_report_wfar(&armv7a->dpm, wfar);
|
||||
break;
|
||||
default:
|
||||
target->debug_reason = DBG_REASON_UNDEFINED;
|
||||
break;
|
||||
/* save address of instruction that triggered the watchpoint? */
|
||||
if (target->debug_reason == DBG_REASON_WATCHPOINT) {
|
||||
uint32_t wfar;
|
||||
|
||||
retval = mem_ap_read_atomic_u32(swjdp,
|
||||
armv7a->debug_base + CPUDBG_WFAR,
|
||||
&wfar);
|
||||
arm_dpm_report_wfar(&armv7a->dpm, wfar);
|
||||
}
|
||||
|
||||
/* REVISIT fast_reg_read is never set ... */
|
||||
|
|
Loading…
Reference in New Issue