Skip to content

Commit 716fbe3

Browse files
committed
target/riscv: only restore mstatus.*ie bits in riscv_interrupts_restore
When value of mstatus CSR changes while stepping with "set_maskisr steponly", OpenOCD should not write back the old value to mstatus when reenabling interrupts. Signed-off-by: Samuel Obuch <samuel.obuch@espressif.com>
1 parent 41a2254 commit 716fbe3

File tree

2 files changed

+27
-44
lines changed

2 files changed

+27
-44
lines changed

src/target/riscv/riscv.c

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ static enum riscv_halt_reason riscv_halt_reason(struct target *target);
294294
static void riscv_info_init(struct target *target, struct riscv_info *r);
295295
static int riscv_step_rtos_hart(struct target *target);
296296

297+
static const riscv_reg_t mstatus_ie_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE;
298+
static int riscv_interrupts_disable(struct target *target, riscv_reg_t *old_mstatus);
299+
static int riscv_interrupts_restore(struct target *target, riscv_reg_t old_mstatus);
300+
297301
static void riscv_sample_buf_maybe_add_timestamp(struct target *target, bool before)
298302
{
299303
RISCV_INFO(r);
@@ -3645,9 +3649,8 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
36453649
}
36463650

36473651
/* Disable Interrupts before attempting to run the algorithm. */
3648-
uint64_t current_mstatus;
3649-
uint64_t irq_disabled_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE;
3650-
if (riscv_interrupts_disable(target, irq_disabled_mask, &current_mstatus) != ERROR_OK)
3652+
riscv_reg_t current_mstatus;
3653+
if (riscv_interrupts_disable(target, &current_mstatus) != ERROR_OK)
36513654
return ERROR_FAIL;
36523655

36533656
/* Run algorithm */
@@ -4227,14 +4230,12 @@ static int riscv_openocd_step_impl(struct target *target, int current,
42274230
}
42284231

42294232
bool success = true;
4230-
uint64_t current_mstatus;
4233+
riscv_reg_t current_mstatus;
42314234
RISCV_INFO(info);
42324235

42334236
if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) {
42344237
/* Disable Interrupts before stepping. */
4235-
uint64_t irq_disabled_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE;
4236-
if (riscv_interrupts_disable(target, irq_disabled_mask,
4237-
&current_mstatus) != ERROR_OK) {
4238+
if (riscv_interrupts_disable(target, &current_mstatus) != ERROR_OK) {
42384239
success = false;
42394240
LOG_TARGET_ERROR(target, "Unable to disable interrupts.");
42404241
goto _exit;
@@ -6001,50 +6002,35 @@ static int riscv_resume_go_all_harts(struct target *target)
60016002
return ERROR_OK;
60026003
}
60036004

6004-
int riscv_interrupts_disable(struct target *target, uint64_t irq_mask, uint64_t *old_mstatus)
6005+
static int riscv_interrupts_disable(struct target *target, riscv_reg_t *old_mstatus)
60056006
{
60066007
LOG_TARGET_DEBUG(target, "Disabling interrupts.");
6007-
struct reg *reg_mstatus = register_get_by_name(target->reg_cache,
6008-
"mstatus", true);
6009-
if (!reg_mstatus) {
6010-
LOG_TARGET_ERROR(target, "Couldn't find mstatus!");
6011-
return ERROR_FAIL;
6008+
riscv_reg_t current_mstatus;
6009+
int ret = riscv_reg_get(target, &current_mstatus, GDB_REGNO_MSTATUS);
6010+
if (ret != ERROR_OK) {
6011+
LOG_TARGET_ERROR(target, "Failed to read mstatus!");
6012+
return ret;
60126013
}
6013-
6014-
int retval = reg_mstatus->type->get(reg_mstatus);
6015-
if (retval != ERROR_OK)
6016-
return retval;
6017-
6018-
RISCV_INFO(info);
6019-
uint8_t mstatus_bytes[8] = { 0 };
6020-
uint64_t current_mstatus = buf_get_u64(reg_mstatus->value, 0, reg_mstatus->size);
6021-
buf_set_u64(mstatus_bytes, 0, info->xlen, set_field(current_mstatus,
6022-
irq_mask, 0));
6023-
6024-
retval = reg_mstatus->type->set(reg_mstatus, mstatus_bytes);
6025-
if (retval != ERROR_OK)
6026-
return retval;
6027-
60286014
if (old_mstatus)
60296015
*old_mstatus = current_mstatus;
6030-
6031-
return ERROR_OK;
6016+
return riscv_reg_set(target, GDB_REGNO_MSTATUS, current_mstatus & ~mstatus_ie_mask);
60326017
}
60336018

6034-
int riscv_interrupts_restore(struct target *target, uint64_t old_mstatus)
6019+
static int riscv_interrupts_restore(struct target *target, riscv_reg_t old_mstatus)
60356020
{
60366021
LOG_TARGET_DEBUG(target, "Restoring interrupts.");
6037-
struct reg *reg_mstatus = register_get_by_name(target->reg_cache,
6038-
"mstatus", true);
6039-
if (!reg_mstatus) {
6040-
LOG_TARGET_ERROR(target, "Couldn't find mstatus!");
6041-
return ERROR_FAIL;
6022+
riscv_reg_t current_mstatus;
6023+
int ret = riscv_reg_get(target, &current_mstatus, GDB_REGNO_MSTATUS);
6024+
if (ret != ERROR_OK) {
6025+
LOG_TARGET_ERROR(target, "Failed to read mstatus!");
6026+
return ret;
60426027
}
6043-
6044-
RISCV_INFO(info);
6045-
uint8_t mstatus_bytes[8];
6046-
buf_set_u64(mstatus_bytes, 0, info->xlen, old_mstatus);
6047-
return reg_mstatus->type->set(reg_mstatus, mstatus_bytes);
6028+
if ((current_mstatus & mstatus_ie_mask) != 0) {
6029+
LOG_TARGET_WARNING(target, "Interrupt enable bits in mstatus changed during single-step.");
6030+
LOG_TARGET_WARNING(target, "OpenOCD might have affected the program when it restored the interrupt bits after single-step.");
6031+
LOG_TARGET_WARNING(target, "Hint: Use 'riscv set_maskisr off' to prevent OpenOCD from touching mstatus during single-step.");
6032+
}
6033+
return riscv_reg_set(target, GDB_REGNO_MSTATUS, current_mstatus | (old_mstatus & mstatus_ie_mask));
60486034
}
60496035

60506036
static int riscv_step_rtos_hart(struct target *target)

src/target/riscv/riscv.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,4 @@ void riscv_add_bscan_tunneled_scan(struct jtag_tap *tap, const struct scan_field
503503
int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);
504504
int riscv_write_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);
505505

506-
int riscv_interrupts_disable(struct target *target, uint64_t ie_mask, uint64_t *old_mstatus);
507-
int riscv_interrupts_restore(struct target *target, uint64_t old_mstatus);
508-
509506
#endif /* OPENOCD_TARGET_RISCV_RISCV_H */

0 commit comments

Comments
 (0)