This is an automated email from Gerrit. "Artemiy Volkov <arte...@synopsys.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7817
-- gerrit commit b7d996d116805fe8e881338b36ab80a418fb2791 Author: Evgeniy Didin <di...@synopsys.com> Date: Fri Jul 31 00:13:12 2020 +0300 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 <di...@synopsys.com> Signed-off-by: Stephanos Ioannidis <r...@stephanos.io> Signed-off-by: Artemiy Volkov <arte...@synopsys.com> diff --git a/src/target/arc.c b/src/target/arc.c index 2e2efa645b..868e1d0fca 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -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) @@ -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; @@ -1255,7 +1283,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 @@ -1301,6 +1329,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); + arc_unset_breakpoint(target, breakpoint); + arc_single_step_core(target); + 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)); @@ -2038,6 +2079,22 @@ static int arc_config_step(struct target *target, int enable_step) return ERROR_OK; } +static int arc_single_step_core(struct target *target) +{ + arc_debug_entry(target); + + /* disable interrupts while stepping */ + arc_enable_interrupts(target, 0); + + /* configure single step mode */ + arc_config_step(target, 1); + + /* exit debug mode */ + arc_exit_debug(target); + + return ERROR_OK; +} + static int arc_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { --