diff options
Diffstat (limited to 'src/target/riscv/riscv.c')
-rw-r--r-- | src/target/riscv/riscv.c | 119 |
1 files changed, 53 insertions, 66 deletions
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index cd31881..aae5eb3 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -294,6 +294,10 @@ static enum riscv_halt_reason riscv_halt_reason(struct target *target); static void riscv_info_init(struct target *target, struct riscv_info *r); static int riscv_step_rtos_hart(struct target *target); +static const riscv_reg_t mstatus_ie_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; +static int riscv_interrupts_disable(struct target *target, riscv_reg_t *old_mstatus); +static int riscv_interrupts_restore(struct target *target, riscv_reg_t old_mstatus); + static void riscv_sample_buf_maybe_add_timestamp(struct target *target, bool before) { RISCV_INFO(r); @@ -2433,8 +2437,8 @@ static int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_w return ERROR_FAIL; } -static int oldriscv_step(struct target *target, int current, uint32_t address, - int handle_breakpoints) +static int oldriscv_step(struct target *target, bool current, uint32_t address, + bool handle_breakpoints) { struct target_type *tt = get_target_type(target); if (!tt) @@ -2442,14 +2446,15 @@ static int oldriscv_step(struct target *target, int current, uint32_t address, return tt->step(target, current, address, handle_breakpoints); } -static int riscv_openocd_step_impl(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int handle_callbacks); +static int riscv_openocd_step_impl(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, int handle_callbacks); -static int old_or_new_riscv_step_impl(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int handle_callbacks) +static int old_or_new_riscv_step_impl(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, int handle_callbacks) { RISCV_INFO(r); - LOG_TARGET_DEBUG(target, "handle_breakpoints=%d", handle_breakpoints); + LOG_TARGET_DEBUG(target, "handle_breakpoints=%s", + handle_breakpoints ? "true" : "false"); if (!r->get_hart_state) return oldriscv_step(target, current, address, handle_breakpoints); else @@ -2457,8 +2462,8 @@ static int old_or_new_riscv_step_impl(struct target *target, int current, handle_callbacks); } -static int old_or_new_riscv_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int old_or_new_riscv_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { return old_or_new_riscv_step_impl(target, current, address, handle_breakpoints, true /* handle callbacks*/); @@ -2822,8 +2827,8 @@ static int enable_watchpoints(struct target *target, bool *wp_is_set) /** * Get everything ready to resume. */ -static int resume_prep(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int resume_prep(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { assert(target->state == TARGET_HALTED); RISCV_INFO(r); @@ -2864,8 +2869,8 @@ static int resume_prep(struct target *target, int current, * Resume all the harts that have been prepped, as close to instantaneous as * possible. */ -static int resume_go(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int resume_go(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { assert(target->state == TARGET_HALTED); RISCV_INFO(r); @@ -2883,7 +2888,7 @@ static int resume_go(struct target *target, int current, return result; } -static int resume_finish(struct target *target, int debug_execution) +static int resume_finish(struct target *target, bool debug_execution) { assert(target->state == TARGET_HALTED); if (riscv_reg_cache_any_dirty(target, LOG_LVL_ERROR)) { @@ -2908,10 +2913,10 @@ static int resume_finish(struct target *target, int debug_execution) */ static int riscv_resume( struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution, + bool handle_breakpoints, + bool debug_execution, bool single_hart) { int result = ERROR_OK; @@ -2972,8 +2977,8 @@ static int riscv_resume( return result; } -static int riscv_target_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int riscv_target_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { if (target->state != TARGET_HALTED) { LOG_TARGET_ERROR(target, "Not halted."); @@ -3648,14 +3653,13 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, } /* Disable Interrupts before attempting to run the algorithm. */ - uint64_t current_mstatus; - uint64_t irq_disabled_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; - if (riscv_interrupts_disable(target, irq_disabled_mask, ¤t_mstatus) != ERROR_OK) + riscv_reg_t current_mstatus; + if (riscv_interrupts_disable(target, ¤t_mstatus) != ERROR_OK) return ERROR_FAIL; /* Run algorithm */ - LOG_TARGET_DEBUG(target, "Resume at 0x%" TARGET_PRIxADDR, entry_point); - if (riscv_resume(target, 0, entry_point, 0, 1, true) != ERROR_OK) + LOG_TARGET_DEBUG(target, "resume at 0x%" TARGET_PRIxADDR, entry_point); + if (riscv_resume(target, false, entry_point, false, true, true) != ERROR_OK) return ERROR_FAIL; int64_t start = timeval_ms(); @@ -4196,8 +4200,8 @@ int riscv_openocd_poll(struct target *target) return ERROR_OK; } -static int riscv_openocd_step_impl(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int handle_callbacks) +static int riscv_openocd_step_impl(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, int handle_callbacks) { LOG_TARGET_DEBUG(target, "stepping hart"); @@ -4230,14 +4234,12 @@ static int riscv_openocd_step_impl(struct target *target, int current, } bool success = true; - uint64_t current_mstatus; + riscv_reg_t current_mstatus; RISCV_INFO(info); if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) { /* Disable Interrupts before stepping. */ - uint64_t irq_disabled_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; - if (riscv_interrupts_disable(target, irq_disabled_mask, - ¤t_mstatus) != ERROR_OK) { + if (riscv_interrupts_disable(target, ¤t_mstatus) != ERROR_OK) { success = false; LOG_TARGET_ERROR(target, "Unable to disable interrupts."); goto _exit; @@ -4291,8 +4293,8 @@ _exit: return success ? ERROR_OK : ERROR_FAIL; } -int riscv_openocd_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +int riscv_openocd_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { return riscv_openocd_step_impl(target, current, address, handle_breakpoints, true /* handle_callbacks */); @@ -6004,50 +6006,35 @@ static int riscv_resume_go_all_harts(struct target *target) return ERROR_OK; } -int riscv_interrupts_disable(struct target *target, uint64_t irq_mask, uint64_t *old_mstatus) +static int riscv_interrupts_disable(struct target *target, riscv_reg_t *old_mstatus) { LOG_TARGET_DEBUG(target, "Disabling interrupts."); - struct reg *reg_mstatus = register_get_by_name(target->reg_cache, - "mstatus", true); - if (!reg_mstatus) { - LOG_TARGET_ERROR(target, "Couldn't find mstatus!"); - return ERROR_FAIL; + riscv_reg_t current_mstatus; + int ret = riscv_reg_get(target, ¤t_mstatus, GDB_REGNO_MSTATUS); + if (ret != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to read mstatus!"); + return ret; } - - int retval = reg_mstatus->type->get(reg_mstatus); - if (retval != ERROR_OK) - return retval; - - RISCV_INFO(info); - uint8_t mstatus_bytes[8] = { 0 }; - uint64_t current_mstatus = buf_get_u64(reg_mstatus->value, 0, reg_mstatus->size); - buf_set_u64(mstatus_bytes, 0, info->xlen, set_field(current_mstatus, - irq_mask, 0)); - - retval = reg_mstatus->type->set(reg_mstatus, mstatus_bytes); - if (retval != ERROR_OK) - return retval; - if (old_mstatus) *old_mstatus = current_mstatus; - - return ERROR_OK; + return riscv_reg_set(target, GDB_REGNO_MSTATUS, current_mstatus & ~mstatus_ie_mask); } -int riscv_interrupts_restore(struct target *target, uint64_t old_mstatus) +static int riscv_interrupts_restore(struct target *target, riscv_reg_t old_mstatus) { LOG_TARGET_DEBUG(target, "Restoring interrupts."); - struct reg *reg_mstatus = register_get_by_name(target->reg_cache, - "mstatus", true); - if (!reg_mstatus) { - LOG_TARGET_ERROR(target, "Couldn't find mstatus!"); - return ERROR_FAIL; + riscv_reg_t current_mstatus; + int ret = riscv_reg_get(target, ¤t_mstatus, GDB_REGNO_MSTATUS); + if (ret != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to read mstatus!"); + return ret; } - - RISCV_INFO(info); - uint8_t mstatus_bytes[8]; - buf_set_u64(mstatus_bytes, 0, info->xlen, old_mstatus); - return reg_mstatus->type->set(reg_mstatus, mstatus_bytes); + if ((current_mstatus & mstatus_ie_mask) != 0) { + LOG_TARGET_WARNING(target, "Interrupt enable bits in mstatus changed during single-step."); + LOG_TARGET_WARNING(target, "OpenOCD might have affected the program when it restored the interrupt bits after single-step."); + LOG_TARGET_WARNING(target, "Hint: Use 'riscv set_maskisr off' to prevent OpenOCD from touching mstatus during single-step."); + } + return riscv_reg_set(target, GDB_REGNO_MSTATUS, current_mstatus | (old_mstatus & mstatus_ie_mask)); } static int riscv_step_rtos_hart(struct target *target) |