target/arc: skip over breakpoints in arc_resume()
When requested by the core code (handle_breakpoints = true), arc_resume() should be able to advance over a potential breakpoint set at the resume address instead of getting stuck in one place. This is achieved by removing the breakpoint, executing one instruction, resetting the breakpoint, then proceeding forward as normal. With this patch applied, openocd is now able to resume from a breakpoint halt when debugging ARCv2 targets via telnet. This has previously been committed to the Zephyr project's openocd repo (see https://github.com/zephyrproject-rtos/openocd/pull/31). Change-Id: I17dba0dcea311d394b303c587bc2dfaa99d67859 Signed-off-by: Evgeniy Didin <didin@synopsys.com> Signed-off-by: Stephanos Ioannidis <root@stephanos.io> Signed-off-by: Artemiy Volkov <artemiy@synopsys.com> Reviewed-on: https://review.openocd.org/c/openocd/+/7817 Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com> Tested-by: jenkins
This commit is contained in:
parent
198b39ff45
commit
74c9170b67
|
@ -52,6 +52,11 @@ static int arc_remove_watchpoint(struct target *target,
|
||||||
struct watchpoint *watchpoint);
|
struct watchpoint *watchpoint);
|
||||||
static int arc_enable_watchpoints(struct target *target);
|
static int arc_enable_watchpoints(struct target *target);
|
||||||
static int arc_enable_breakpoints(struct target *target);
|
static int arc_enable_breakpoints(struct target *target);
|
||||||
|
static int arc_unset_breakpoint(struct target *target,
|
||||||
|
struct breakpoint *breakpoint);
|
||||||
|
static int arc_set_breakpoint(struct target *target,
|
||||||
|
struct breakpoint *breakpoint);
|
||||||
|
static int arc_single_step_core(struct target *target);
|
||||||
|
|
||||||
void arc_reg_data_type_add(struct target *target,
|
void arc_reg_data_type_add(struct target *target,
|
||||||
struct arc_reg_data_type *data_type)
|
struct arc_reg_data_type *data_type)
|
||||||
|
@ -750,6 +755,29 @@ static int arc_examine(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int arc_exit_debug(struct target *target)
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
struct arc_common *arc = target_to_arc(target);
|
||||||
|
|
||||||
|
/* Do read-modify-write sequence, or DEBUG.UB will be reset unintentionally. */
|
||||||
|
CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, &value));
|
||||||
|
value |= SET_CORE_FORCE_HALT; /* set the HALT bit */
|
||||||
|
CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value));
|
||||||
|
alive_sleep(1);
|
||||||
|
|
||||||
|
target->state = TARGET_HALTED;
|
||||||
|
CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
|
||||||
|
|
||||||
|
if (debug_level >= LOG_LVL_DEBUG) {
|
||||||
|
LOG_DEBUG("core stopped (halted) debug-reg: 0x%08" PRIx32, value);
|
||||||
|
CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value));
|
||||||
|
LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int arc_halt(struct target *target)
|
static int arc_halt(struct target *target)
|
||||||
{
|
{
|
||||||
uint32_t value, irq_state;
|
uint32_t value, irq_state;
|
||||||
|
@ -1251,7 +1279,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
struct reg *pc = &arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache];
|
struct reg *pc = &arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache];
|
||||||
|
|
||||||
LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints(not supported yet):%i,"
|
LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i,"
|
||||||
" debug_execution:%i", current, address, handle_breakpoints, debug_execution);
|
" debug_execution:%i", current, address, handle_breakpoints, debug_execution);
|
||||||
|
|
||||||
/* We need to reset ARC cache variables so caches
|
/* We need to reset ARC cache variables so caches
|
||||||
|
@ -1296,6 +1324,19 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
|
||||||
CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value));
|
CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the front-end may request us not to handle breakpoints here */
|
||||||
|
if (handle_breakpoints) {
|
||||||
|
/* Single step past breakpoint at current address */
|
||||||
|
struct breakpoint *breakpoint = breakpoint_find(target, resume_pc);
|
||||||
|
if (breakpoint) {
|
||||||
|
LOG_DEBUG("skipping past breakpoint at 0x%08" TARGET_PRIxADDR,
|
||||||
|
breakpoint->address);
|
||||||
|
CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint));
|
||||||
|
CHECK_RETVAL(arc_single_step_core(target));
|
||||||
|
CHECK_RETVAL(arc_set_breakpoint(target, breakpoint));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Restore IRQ state if not in debug_execution*/
|
/* Restore IRQ state if not in debug_execution*/
|
||||||
if (!debug_execution)
|
if (!debug_execution)
|
||||||
CHECK_RETVAL(arc_enable_interrupts(target, arc->irq_state));
|
CHECK_RETVAL(arc_enable_interrupts(target, arc->irq_state));
|
||||||
|
@ -2027,6 +2068,22 @@ static int arc_config_step(struct target *target, int enable_step)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int arc_single_step_core(struct target *target)
|
||||||
|
{
|
||||||
|
CHECK_RETVAL(arc_debug_entry(target));
|
||||||
|
|
||||||
|
/* disable interrupts while stepping */
|
||||||
|
CHECK_RETVAL(arc_enable_interrupts(target, 0));
|
||||||
|
|
||||||
|
/* configure single step mode */
|
||||||
|
CHECK_RETVAL(arc_config_step(target, 1));
|
||||||
|
|
||||||
|
/* exit debug mode */
|
||||||
|
CHECK_RETVAL(arc_exit_debug(target));
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int arc_step(struct target *target, int current, target_addr_t address,
|
static int arc_step(struct target *target, int current, target_addr_t address,
|
||||||
int handle_breakpoints)
|
int handle_breakpoints)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue