ARM11: basic watchpoint support
Use the DPM watchpoint support; remove old incomplete stubs. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>__archive__
parent
f4651c869f
commit
a0edb8a328
2
NEWS
2
NEWS
|
@ -24,10 +24,12 @@ Target Layer:
|
||||||
- accelerated GDB memory checksum
|
- accelerated GDB memory checksum
|
||||||
- support "arm regs" command
|
- support "arm regs" command
|
||||||
- can access all core modes and registers
|
- can access all core modes and registers
|
||||||
|
- watchpoint support
|
||||||
Cortex-A8
|
Cortex-A8
|
||||||
- support "arm regs" command
|
- support "arm regs" command
|
||||||
- can access all core modes and registers
|
- can access all core modes and registers
|
||||||
- supports "reset-assert" event (used on OMAP3530)
|
- supports "reset-assert" event (used on OMAP3530)
|
||||||
|
- watchpoint support
|
||||||
Cortex-M3
|
Cortex-M3
|
||||||
- Exposed DWT registers like cycle counter
|
- Exposed DWT registers like cycle counter
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,8 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
|
||||||
*/
|
*/
|
||||||
retval = arm_dpm_write_dirty_registers(&arm11->dpm, bpwp);
|
retval = arm_dpm_write_dirty_registers(&arm11->dpm, bpwp);
|
||||||
|
|
||||||
|
retval = arm11_bpwp_flush(arm11);
|
||||||
|
|
||||||
register_cache_invalidate(arm11->arm.core_cache);
|
register_cache_invalidate(arm11->arm.core_cache);
|
||||||
|
|
||||||
/* restore DSCR */
|
/* restore DSCR */
|
||||||
|
@ -1212,7 +1214,6 @@ static int arm11_examine(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
arm11->brp = ((didr >> 24) & 0x0F) + 1;
|
arm11->brp = ((didr >> 24) & 0x0F) + 1;
|
||||||
arm11->wrp = ((didr >> 28) & 0x0F) + 1;
|
|
||||||
|
|
||||||
/** \todo TODO: reserve one brp slot if we allow breakpoints during step */
|
/** \todo TODO: reserve one brp slot if we allow breakpoints during step */
|
||||||
arm11->free_brps = arm11->brp;
|
arm11->free_brps = arm11->brp;
|
||||||
|
|
|
@ -53,9 +53,10 @@ struct arm11_common
|
||||||
|
|
||||||
/** Debug module state. */
|
/** Debug module state. */
|
||||||
struct arm_dpm dpm;
|
struct arm_dpm dpm;
|
||||||
|
struct arm11_sc7_action *bpwp_actions;
|
||||||
|
unsigned bpwp_n;
|
||||||
|
|
||||||
size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */
|
size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */
|
||||||
size_t wrp; /**< Number of Watchpoint Register Pairs from DIDR */
|
|
||||||
size_t free_brps; /**< Number of breakpoints allocated */
|
size_t free_brps; /**< Number of breakpoints allocated */
|
||||||
|
|
||||||
uint32_t dscr; /**< Last retrieved DSCR value. */
|
uint32_t dscr; /**< Last retrieved DSCR value. */
|
||||||
|
|
|
@ -892,7 +892,7 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||||
*/
|
*/
|
||||||
void arm11_sc7_clear_vbw(struct arm11_common * arm11)
|
void arm11_sc7_clear_vbw(struct arm11_common * arm11)
|
||||||
{
|
{
|
||||||
size_t clear_bw_size = arm11->brp + arm11->wrp + 1;
|
size_t clear_bw_size = arm11->brp + 1;
|
||||||
struct arm11_sc7_action *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size);
|
struct arm11_sc7_action *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size);
|
||||||
struct arm11_sc7_action * pos = clear_bw;
|
struct arm11_sc7_action * pos = clear_bw;
|
||||||
|
|
||||||
|
@ -905,11 +905,6 @@ void arm11_sc7_clear_vbw(struct arm11_common * arm11)
|
||||||
for (size_t i = 0; i < arm11->brp; i++)
|
for (size_t i = 0; i < arm11->brp; i++)
|
||||||
(pos++)->address = ARM11_SC7_BCR0 + i;
|
(pos++)->address = ARM11_SC7_BCR0 + i;
|
||||||
|
|
||||||
|
|
||||||
for (size_t i = 0; i < arm11->wrp; i++)
|
|
||||||
(pos++)->address = ARM11_SC7_WCR0 + i;
|
|
||||||
|
|
||||||
|
|
||||||
(pos++)->address = ARM11_SC7_VCR;
|
(pos++)->address = ARM11_SC7_VCR;
|
||||||
|
|
||||||
arm11_sc7_run(arm11, clear_bw, clear_bw_size);
|
arm11_sc7_run(arm11, clear_bw, clear_bw_size);
|
||||||
|
@ -1013,6 +1008,88 @@ static int arm11_dpm_instr_read_data_r0(struct arm_dpm *dpm,
|
||||||
opcode, data);
|
opcode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Because arm11_sc7_run() takes a vector of actions, we batch breakpoint
|
||||||
|
* and watchpoint operations instead of running them right away. Since we
|
||||||
|
* pre-allocated our vector, we don't need to worry about space.
|
||||||
|
*/
|
||||||
|
static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index,
|
||||||
|
uint32_t addr, uint32_t control)
|
||||||
|
{
|
||||||
|
struct arm11_common *arm11 = dpm_to_arm11(dpm);
|
||||||
|
struct arm11_sc7_action *action;
|
||||||
|
|
||||||
|
action = arm11->bpwp_actions + arm11->bpwp_n;
|
||||||
|
|
||||||
|
/* Invariant: this bp/wp is disabled.
|
||||||
|
* It also happens that the core is halted here, but for
|
||||||
|
* DPM-based cores we don't actually care about that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
action[0].write = action[1].write = true;
|
||||||
|
|
||||||
|
action[0].value = addr;
|
||||||
|
action[1].value = control;
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case 0 ... 15:
|
||||||
|
action[0].address = ARM11_SC7_BVR0 + index;
|
||||||
|
action[1].address = ARM11_SC7_BCR0 + index;
|
||||||
|
break;
|
||||||
|
case 16 ... 32:
|
||||||
|
index -= 16;
|
||||||
|
action[0].address = ARM11_SC7_WVR0 + index;
|
||||||
|
action[1].address = ARM11_SC7_WCR0 + index;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
arm11->bpwp_n += 2;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned index)
|
||||||
|
{
|
||||||
|
struct arm11_common *arm11 = dpm_to_arm11(dpm);
|
||||||
|
struct arm11_sc7_action *action;
|
||||||
|
|
||||||
|
action = arm11->bpwp_actions + arm11->bpwp_n;
|
||||||
|
|
||||||
|
action[0].write = true;
|
||||||
|
action[0].value = 0;
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case 0 ... 15:
|
||||||
|
action[0].address = ARM11_SC7_BCR0 + index;
|
||||||
|
break;
|
||||||
|
case 16 ... 32:
|
||||||
|
index -= 16;
|
||||||
|
action[0].address = ARM11_SC7_WCR0 + index;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
arm11->bpwp_n += 1;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Flush any pending breakpoint and watchpoint updates. */
|
||||||
|
int arm11_bpwp_flush(struct arm11_common *arm11)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (!arm11->bpwp_n)
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
retval = arm11_sc7_run(arm11, arm11->bpwp_actions, arm11->bpwp_n);
|
||||||
|
arm11->bpwp_n = 0;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/** Set up high-level debug module utilities */
|
/** Set up high-level debug module utilities */
|
||||||
int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr)
|
int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr)
|
||||||
{
|
{
|
||||||
|
@ -1032,11 +1109,22 @@ int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr)
|
||||||
dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc;
|
dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc;
|
||||||
dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0;
|
dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0;
|
||||||
|
|
||||||
|
dpm->bpwp_enable = arm11_bpwp_enable;
|
||||||
|
dpm->bpwp_disable = arm11_bpwp_disable;
|
||||||
|
|
||||||
retval = arm_dpm_setup(dpm);
|
retval = arm_dpm_setup(dpm);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = arm_dpm_initialize(dpm);
|
/* alloc enough to enable all breakpoints and watchpoints at once */
|
||||||
|
arm11->bpwp_actions = calloc(2 * (dpm->nbp + dpm->nwp),
|
||||||
|
sizeof *arm11->bpwp_actions);
|
||||||
|
if (!arm11->bpwp_actions)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
return retval;
|
retval = arm_dpm_initialize(dpm);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
return arm11_bpwp_flush(arm11);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,5 +59,6 @@ int arm11_read_memory_word(struct arm11_common *arm11,
|
||||||
uint32_t address, uint32_t *result);
|
uint32_t address, uint32_t *result);
|
||||||
|
|
||||||
int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr);
|
int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr);
|
||||||
|
int arm11_bpwp_flush(struct arm11_common *arm11);
|
||||||
|
|
||||||
#endif // ARM11_DBGTAP_H
|
#endif // ARM11_DBGTAP_H
|
||||||
|
|
Loading…
Reference in New Issue