aboutsummaryrefslogtreecommitdiff
path: root/src/target/riscv/riscv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/riscv/riscv.c')
-rw-r--r--src/target/riscv/riscv.c119
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, &current_mstatus) != ERROR_OK)
+ riscv_reg_t current_mstatus;
+ if (riscv_interrupts_disable(target, &current_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,
- &current_mstatus) != ERROR_OK) {
+ if (riscv_interrupts_disable(target, &current_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, &current_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, &current_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)