From 2b6827cd53ab751888d31f8d6984f09ed3d634c3 Mon Sep 17 00:00:00 2001 From: Samuel Obuch Date: Tue, 4 Feb 2025 16:27:23 +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 | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index e920c9f8a..8f9ef9c7d 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -4170,12 +4170,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_reg_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; @@ -4199,11 +4199,24 @@ static int riscv_openocd_step_impl(struct target *target, int current, riscv_reg_cache_invalidate_all(target); - if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) + if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) { + riscv_reg_t new_mstatus; + if (riscv_reg_get(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_watchpoints(target, wps_to_enable) != ERROR_OK) {