From dfc008fd3d9e7ae430278b573f9a77f4c73ad89f Mon Sep 17 00:00:00 2001 From: Samuel Obuch Date: Tue, 14 Jan 2025 16:10:27 +0100 Subject: [PATCH] target/riscv: only update mstatus.*ie bits with set_maskisr steponly 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 --- src/target/riscv/riscv.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index ea3ed17856..d1d07678f3 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -3324,11 +3324,11 @@ int riscv_openocd_step(struct target *target, int current, bool success = true; uint64_t current_mstatus; + uint64_t irq_disabled_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; 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) { success = false; @@ -3344,11 +3344,24 @@ int riscv_openocd_step(struct target *target, int current, register_cache_invalidate(target->reg_cache); - if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) + if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) { + uint64_t new_mstatus; + if (riscv_get_register(target, &new_mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) { + success = false; + LOG_TARGET_ERROR(target, "Unable to read mstatus after step"); + goto _exit; + } + if (new_mstatus != (current_mstatus & ~irq_disabled_mask)) { + LOG_TARGET_DEBUG(target, "mstatus value changed while stepping, " + "only restoring interrupt enable bits."); + current_mstatus = new_mstatus | (current_mstatus & irq_disabled_mask); + } + if (riscv_interrupts_restore(target, current_mstatus) != ERROR_OK) { success = false; LOG_TARGET_ERROR(target, "Unable to restore interrupts."); } + } _exit: if (enable_triggers(target, trigger_state) != ERROR_OK) {