|
From: openocd-gerrit <ope...@us...> - 2026-10-23 04:25:53
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 87075a144bad4404a9d70884ce0b469575b9f0ae (commit)
from d74275c08fbc87b13c85d0e2a9ad92784cdacb92 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 87075a144bad4404a9d70884ce0b469575b9f0ae
Author: Farid Khaydari <kha...@gm...>
Date: Tue Aug 18 16:51:08 2026 +0300
target/riscv: fix progbuf privilege context setup
mstatus.MPV belongs to that context too. If not reset, can result in
host address being interpreted as the guest one.
mstatus update/restore separated into a helper for future reuse by
abstract command memory access.
Change-Id: I440b5ab6979afd6bba3931a9e01a091cb3571c26
Signed-off-by: Farid Khaydari <kha...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9934
Reviewed-by: Evgeniy Naydanov <eu...@gm...>
Tested-by: jenkins
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index d1885786f..9205d6ae3 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -3255,46 +3255,82 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
}
}
+static int set_mpp_mpv(struct target *target, riscv_reg_t *mstatus,
+ riscv_reg_t *mstatus_old, riscv_reg_t *mstatush,
+ riscv_reg_t *mstatush_old, enum riscv_priv_mode mode)
+{
+ assert(mstatus);
+ assert(mstatus_old);
+ assert(mstatush);
+ assert(mstatush_old);
+
+ if (riscv_reg_get(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
+ return ERROR_FAIL;
+ *mstatus_old = *mstatus;
+
+ *mstatus = set_field(*mstatus, MSTATUS_MPRV, 1);
+ *mstatus = set_field(*mstatus, MSTATUS_MPP, riscv_priv_mode_to_prv(mode));
+
+ /* The caller refuses a guest access, so MPV is cleared. */
+ if (riscv_supports_extension(target, 'H')) {
+ if (riscv_xlen(target) == 32) {
+ if (riscv_reg_get(target, mstatush, GDB_REGNO_MSTATUSH) != ERROR_OK)
+ return ERROR_FAIL;
+ *mstatush_old = *mstatush;
+ *mstatush = set_field(*mstatush, MSTATUSH_MPV, 0);
+ } else {
+ *mstatus = set_field(*mstatus, MSTATUS_MPV, 0);
+ }
+ }
+
+ if (*mstatus != *mstatus_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (*mstatush != *mstatush_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUSH, *mstatush) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return ERROR_OK;
+}
+
+static int restore_mpp_mpv(struct target *target, riscv_reg_t mstatus,
+ riscv_reg_t mstatus_old, riscv_reg_t mstatush, riscv_reg_t mstatush_old)
+{
+ if (mstatus != mstatus_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (mstatush != mstatush_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUSH, mstatush_old) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return ERROR_OK;
+}
+
/* TODO: return struct mem_access_result */
-static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_t *mstatus, riscv_reg_t *mstatus_old,
+static int modify_privilege_progbuf(struct target *target, riscv_reg_t *mstatus,
+ riscv_reg_t *mstatus_old, riscv_reg_t *mstatush, riscv_reg_t *mstatush_old,
riscv_reg_t *dcsr, riscv_reg_t *dcsr_old, enum riscv_priv_mode mode)
{
assert(mstatus);
assert(mstatus_old);
+ assert(mstatush);
+ assert(mstatush_old);
assert(dcsr);
assert(dcsr_old);
if (mode == RISCV_MODE_M)
return ERROR_OK;
- /* Read and save DCSR */
if (riscv_reg_get(target, dcsr, GDB_REGNO_DCSR) != ERROR_OK)
return ERROR_FAIL;
*dcsr_old = *dcsr;
- /* Read and save MSTATUS */
- if (riscv_reg_get(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
+ if (set_mpp_mpv(target, mstatus, mstatus_old, mstatush, mstatush_old, mode) != ERROR_OK)
return ERROR_FAIL;
- *mstatus_old = *mstatus;
- /* If we come from m-mode with mprv set, we want to keep mpp */
- if (get_field(*dcsr, CSR_DCSR_PRV) == PRV_M)
- return ERROR_OK;
-
- /* mstatus.mpp <- dcsr.prv */
- *mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(*dcsr, CSR_DCSR_PRV));
-
- /* mstatus.mprv <- 1 */
- *mstatus = set_field(*mstatus, MSTATUS_MPRV, 1);
-
- /* Write MSTATUS */
- if (*mstatus != *mstatus_old &&
- riscv_reg_set(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK)
- return ERROR_FAIL;
-
- /* dcsr.mprven <- 1 */
*dcsr = set_field(*dcsr, CSR_DCSR_MPRVEN, CSR_DCSR_MPRVEN_ENABLED);
- /* Write DCSR */
if (*dcsr != *dcsr_old &&
riscv_reg_set(target, GDB_REGNO_DCSR, *dcsr) != ERROR_OK)
return ERROR_FAIL;
@@ -3302,15 +3338,12 @@ static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_
return ERROR_OK;
}
-static int restore_privilege_from_virt2phys_mode(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
- riscv_reg_t dcsr, riscv_reg_t dcsr_old)
+static int restore_privilege_progbuf(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
+ riscv_reg_t mstatush, riscv_reg_t mstatush_old, riscv_reg_t dcsr, riscv_reg_t dcsr_old)
{
- /* Restore MSTATUS */
- if (mstatus != mstatus_old &&
- riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
+ if (restore_mpp_mpv(target, mstatus, mstatus_old, mstatush, mstatush_old) != ERROR_OK)
return ERROR_FAIL;
- /* Restore DCSR */
if (dcsr != dcsr_old &&
riscv_reg_set(target, GDB_REGNO_DCSR, dcsr_old) != ERROR_OK)
return ERROR_FAIL;
@@ -4555,18 +4588,20 @@ access_memory_progbuf(struct target *target, const struct riscv_mem_access_args
riscv_reg_t mstatus = 0;
riscv_reg_t mstatus_old = 0;
+ riscv_reg_t mstatush = 0;
+ riscv_reg_t mstatush_old = 0;
riscv_reg_t dcsr = 0;
riscv_reg_t dcsr_old = 0;
- if (modify_privilege_for_virt2phys_mode(target,
- &mstatus, &mstatus_old, &dcsr, &dcsr_old, args.mode) != ERROR_OK)
+ if (modify_privilege_progbuf(target, &mstatus, &mstatus_old, &mstatush,
+ &mstatush_old, &dcsr, &dcsr_old, args.mode) != ERROR_OK)
return mem_access_result(MEM_ACCESS_SKIPPED_PRIV_MOD_FAILED);
struct mem_access_result result = is_read ?
read_memory_progbuf(target, args) :
write_memory_progbuf(target, args);
- if (restore_privilege_from_virt2phys_mode(target,
- mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
+ if (restore_privilege_progbuf(target, mstatus, mstatus_old,
+ mstatush, mstatush_old, dcsr, dcsr_old) != ERROR_OK)
return mem_access_result(MEM_ACCESS_FAILED_PRIV_MOD_FAILED);
return result;
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index c2e34a548..508d212db 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -376,6 +376,23 @@ struct riscv_info {
bool autofence;
};
+static inline riscv_reg_t riscv_priv_mode_to_prv(enum riscv_priv_mode mode)
+{
+ switch (mode) {
+ case RISCV_MODE_M:
+ return PRV_M;
+ case RISCV_MODE_S:
+ case RISCV_MODE_VS:
+ return PRV_S;
+ case RISCV_MODE_U:
+ case RISCV_MODE_VU:
+ return PRV_U;
+ default:
+ assert(false);
+ return PRV_M;
+ }
+}
+
struct riscv_private_config {
bool dcsr_ebreak_fields[N_RISCV_MODE];
bool dcsr_cetrig;
-----------------------------------------------------------------------
Summary of changes:
src/target/riscv/riscv-013.c | 99 ++++++++++++++++++++++++++++++--------------
src/target/riscv/riscv.h | 17 ++++++++
2 files changed, 84 insertions(+), 32 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|