Skip to content

Commit

Permalink
target/arc: skip over breakpoints in arc_resume()
Browse files Browse the repository at this point in the history
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 zephyrproject-rtos/openocd#31).

Change-Id: I17dba0dcea311d394b303c587bc2dfaa99d67859
Signed-off-by: Evgeniy Didin <[email protected]>
Signed-off-by: Stephanos Ioannidis <[email protected]>
Signed-off-by: Artemiy Volkov <[email protected]>
Reviewed-on: https://review.openocd.org/c/openocd/+/7817
Reviewed-by: Antonio Borneo <[email protected]>
Tested-by: jenkins
  • Loading branch information
EvgeniiDidin authored and borneoa committed Jan 13, 2024
1 parent 2c10e3e commit 0de852f
Showing 1 changed file with 58 additions and 1 deletion.
59 changes: 58 additions & 1 deletion src/target/arc.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ static int arc_remove_watchpoint(struct target *target,
struct watchpoint *watchpoint);
static int arc_enable_watchpoints(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,
struct arc_reg_data_type *data_type)
Expand Down Expand Up @@ -750,6 +755,29 @@ static int arc_examine(struct target *target)
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)
{
uint32_t value, irq_state;
Expand Down Expand Up @@ -1251,7 +1279,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
uint32_t value;
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);

/* We need to reset ARC cache variables so caches
Expand Down Expand Up @@ -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));
}

/* 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*/
if (!debug_execution)
CHECK_RETVAL(arc_enable_interrupts(target, arc->irq_state));
Expand Down Expand Up @@ -2027,6 +2068,22 @@ static int arc_config_step(struct target *target, int enable_step)
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,
int handle_breakpoints)
{
Expand Down

0 comments on commit 0de852f

Please sign in to comment.