|
From: openocd-gerrit <ope...@us...> - 2026-10-23 04:24:56
|
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 d74275c08fbc87b13c85d0e2a9ad92784cdacb92 (commit)
from 54129082562d3d31568df8ba89bfc179add13f7f (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 d74275c08fbc87b13c85d0e2a9ad92784cdacb92
Author: Farid Khaydari <kha...@gm...>
Date: Thu Aug 13 14:34:57 2026 +0300
target/riscv: carry the privilege mode in memory access args
The address space used to be implied by the virt2phys mode, so a
physical request in riscv virt2phys_mode hw was translated and the
system bus served a virtual one untranslated.
Change-Id: I689588ddc79b3427c054a26ac3e4db8ceea3f7df
Signed-off-by: Farid Khaydari <kha...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9933
Reviewed-by: Evgeniy Naydanov <eu...@gm...>
Tested-by: jenkins
diff --git a/doc/openocd.texi b/doc/openocd.texi
index b89bea0d8..7c8d36f06 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -12069,6 +12069,8 @@ dump_sample_buf}.
Quickly read count words of the given size from address. This can be useful
to read out a buffer that's memory-mapped to be accessed through a single
address, or to sample a changing value in a memory-mapped device.
+
+The address is physical.
@end deffn
@deffn {Command} {riscv info}
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index 8294b82d8..d4aa87947 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -2341,6 +2341,13 @@ static int access_memory(struct target *target, const struct riscv_mem_access_ar
{
assert(riscv_mem_access_is_valid(args));
const bool is_write = riscv_mem_access_is_write(args);
+
+ if (args.mode != RISCV_MODE_M) {
+ LOG_TARGET_ERROR(target, "Memory %s: hardware address translation is not "
+ "supported for RISC-V Debug Spec v0.11 targets", is_write ? "write" : "read");
+ return ERROR_FAIL;
+ }
+
if (is_write)
return write_memory(target, args);
return read_memory(target, args);
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 96033af6f..d1885786f 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1304,6 +1304,7 @@ static int scratch_read64(struct target *target, scratch_mem_t *scratch,
uint8_t buffer[8] = {0};
const struct riscv_mem_access_args args = {
.address = scratch->debug_address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = 4,
.count = 2,
@@ -1346,6 +1347,7 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch,
};
const struct riscv_mem_access_args args = {
.address = scratch->debug_address,
+ .mode = RISCV_MODE_M,
.write_buffer = buffer,
.size = 4,
.count = 2,
@@ -3255,13 +3257,13 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
/* 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,
- riscv_reg_t *dcsr, riscv_reg_t *dcsr_old)
+ riscv_reg_t *dcsr, riscv_reg_t *dcsr_old, enum riscv_priv_mode mode)
{
assert(mstatus);
assert(mstatus_old);
assert(dcsr);
assert(dcsr_old);
- if (!riscv_virt2phys_mode_is_hw(target))
+ if (mode == RISCV_MODE_M)
return ERROR_OK;
/* Read and save DCSR */
@@ -3303,9 +3305,6 @@ static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_
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)
{
- if (!riscv_virt2phys_mode_is_hw(target))
- return ERROR_OK;
-
/* Restore MSTATUS */
if (mstatus != mstatus_old &&
riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
@@ -3627,6 +3626,8 @@ enum mem_access_result_type {
SKIPPED, "skipped (abstract command argument write failed)") \
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PRIV_MOD_FAILED, \
SKIPPED, "skipped (privilege modification failed)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_NO_HW_TRANSLATION, \
+ SKIPPED, "skipped (backend cannot translate a virtual address)") \
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED, FAILED, "failed") \
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_DM_ACCESS_FAILED, \
FAILED, "failed (DM register access failed)") \
@@ -3778,6 +3779,12 @@ mem_should_skip_sysbus(struct target *target, const struct riscv_mem_access_args
const bool is_read = riscv_mem_access_is_read(args);
const char *const access_type = is_read ? "read" : "write";
+ if (args.mode != RISCV_MODE_M) {
+ LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - "
+ "no hardware address translation for a virtual address", access_type);
+ return mem_access_result(MEM_ACCESS_SKIPPED_NO_HW_TRANSLATION);
+ }
+
if (!sba_supports_access(target, args.size)) {
LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - "
"unsupported size.", access_type);
@@ -3809,6 +3816,12 @@ mem_should_skip_abstract(struct target *target, const struct riscv_mem_access_ar
const bool is_read = riscv_mem_access_is_read(args);
const char *const access_type = is_read ? "read" : "write";
+ if (args.mode != RISCV_MODE_M) {
+ /* Temporary, until aamvirtual support lands. */
+ LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - "
+ "virtual access (aamvirtual) not implemented yet", access_type);
+ return mem_access_result(MEM_ACCESS_SKIPPED_NO_HW_TRANSLATION);
+ }
if (args.size > 8) {
/* TODO: Add 128b support if it's ever used. Involves modifying
read/write_abstract_arg() to work on two 64b values. */
@@ -4545,7 +4558,7 @@ access_memory_progbuf(struct target *target, const struct riscv_mem_access_args
riscv_reg_t dcsr = 0;
riscv_reg_t dcsr_old = 0;
if (modify_privilege_for_virt2phys_mode(target,
- &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
+ &mstatus, &mstatus_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 ?
@@ -4618,6 +4631,10 @@ riscv013_access_memory(struct target *target, const struct riscv_mem_access_args
const bool is_read = riscv_mem_access_is_read(args);
const char *const access_type = is_read ? "read" : "write";
+ LOG_TARGET_DEBUG(target, "Memory %s: addr=0x%" TARGET_PRIxADDR
+ " (%s), size=%" PRIu32 ", count=%" PRIu32 ", increment=%" PRIu32,
+ access_type, args.address, args.mode == RISCV_MODE_M ? "physical" : "virtual",
+ args.size, args.count, args.increment);
if (!is_read && args.increment != args.size) {
LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size");
return ERROR_NOT_IMPLEMENTED;
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index f527f9549..3ddd75275 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -142,20 +142,26 @@ struct tdata1_cache {
struct list_head elem_tdata1;
};
-bool riscv_virt2phys_mode_is_hw(const struct target *target)
+static bool riscv_virt2phys_mode_is_hw(const struct target *target)
{
assert(target);
RISCV_INFO(r);
return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_HW;
}
-bool riscv_virt2phys_mode_is_sw(const struct target *target)
+static bool riscv_virt2phys_mode_is_sw(const struct target *target)
{
assert(target);
RISCV_INFO(r);
return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_SW;
}
+static bool riscv_virt2phys_mode_is_off(const struct target *target)
+{
+ assert(target);
+ return riscv_info(target)->virt2phys_mode == RISCV_VIRT2PHYS_MODE_OFF;
+}
+
const char *riscv_virt2phys_mode_to_str(enum riscv_virt2phys_mode mode)
{
assert(mode == RISCV_VIRT2PHYS_MODE_OFF
@@ -3109,20 +3115,14 @@ static int riscv_effective_privilege_mode(struct target *target, enum riscv_priv
return ERROR_OK;
}
-static int riscv_mmu(struct target *target, bool *enabled)
+static int riscv_mmu_impl(struct target *target,
+ enum riscv_priv_mode mode, bool *enabled)
{
assert(target);
assert(enabled);
*enabled = false;
- if (!riscv_virt2phys_mode_is_sw(target))
- return ERROR_OK;
-
- enum riscv_priv_mode mode = RISCV_MODE_M;
- if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
- return ERROR_FAIL;
-
if (mode == RISCV_MODE_M) {
LOG_TARGET_DEBUG(target, "SATP/MMU ignored in Machine mode");
return ERROR_OK;
@@ -3177,6 +3177,23 @@ static int riscv_mmu(struct target *target, bool *enabled)
return ERROR_OK;
}
+static int riscv_mmu(struct target *target, bool *enabled)
+{
+ assert(target);
+ assert(enabled);
+
+ *enabled = false;
+
+ if (!riscv_virt2phys_mode_is_sw(target))
+ return ERROR_OK;
+
+ enum riscv_priv_mode mode = RISCV_MODE_M;
+ if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return riscv_mmu_impl(target, mode, enabled);
+}
+
/* Translate address from virtual to physical, using info and ppn.
* If extra_info is non-NULL, then translate page table accesses for the primary
* translation using extra_info and extra_ppn. */
@@ -3220,6 +3237,7 @@ static int riscv_address_translate(struct target *target,
assert(info->pte_shift <= 3);
const struct riscv_mem_access_args args = {
.address = pte_address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = 4,
.increment = 4,
@@ -3387,12 +3405,11 @@ static int riscv_virt2phys_v(struct target *target, target_addr_t virtual, targe
static int riscv_virt2phys(struct target *target, target_addr_t virtual, target_addr_t *physical)
{
- bool enabled;
- if (riscv_mmu(target, &enabled) != ERROR_OK)
- return ERROR_FAIL;
- if (!enabled) {
+ /* TODO: translate the address in the other modes as well. */
+ if (!riscv_virt2phys_mode_is_sw(target)) {
*physical = virtual;
- LOG_TARGET_DEBUG(target, "MMU is disabled. 0x%" TARGET_PRIxADDR " -> 0x%" TARGET_PRIxADDR, virtual, *physical);
+ LOG_TARGET_DEBUG(target, "Address translation is off. 0x%" TARGET_PRIxADDR
+ " -> 0x%" TARGET_PRIxADDR, virtual, *physical);
return ERROR_OK;
}
@@ -3400,6 +3417,15 @@ static int riscv_virt2phys(struct target *target, target_addr_t virtual, target_
if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
return ERROR_FAIL;
+ bool enabled = false;
+ if (riscv_mmu_impl(target, mode, &enabled) != ERROR_OK)
+ return ERROR_FAIL;
+ if (!enabled) {
+ *physical = virtual;
+ LOG_TARGET_DEBUG(target, "MMU is disabled. 0x%" TARGET_PRIxADDR " -> 0x%" TARGET_PRIxADDR, virtual, *physical);
+ return ERROR_OK;
+ }
+
if (riscv_priv_mode_is_guest(mode))
return riscv_virt2phys_v(target, virtual, physical);
@@ -3461,6 +3487,7 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr
{
const struct riscv_mem_access_args args = {
.address = phys_address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = size,
.count = count,
@@ -3475,6 +3502,7 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
{
const struct riscv_mem_access_args args = {
.address = phys_address,
+ .mode = RISCV_MODE_M,
.write_buffer = buffer,
.size = size,
.count = count,
@@ -3485,7 +3513,7 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
return r->access_memory(target, args);
}
-static int riscv_rw_memory(struct target *target, const struct riscv_mem_access_args args)
+static int riscv_rw_memory(struct target *target, struct riscv_mem_access_args args)
{
assert(riscv_mem_access_is_valid(args));
@@ -3496,12 +3524,34 @@ static int riscv_rw_memory(struct target *target, const struct riscv_mem_access_
return ERROR_OK;
}
- bool mmu_enabled;
- int result = riscv_mmu(target, &mmu_enabled);
+ struct riscv_info *r = riscv_info(target);
+
+ args.mode = RISCV_MODE_M;
+
+ if (riscv_virt2phys_mode_is_off(target))
+ return r->access_memory(target, args);
+
+ enum riscv_priv_mode mode = RISCV_MODE_M;
+ if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (riscv_virt2phys_mode_is_hw(target)) {
+ if (riscv_priv_mode_is_guest(mode)) {
+ LOG_TARGET_ERROR(target, "Cannot translate a guest access in "
+ "hardware: OpenOCD does not set mstatus.MPV yet. "
+ "Use 'riscv virt2phys_mode sw'.");
+ return ERROR_FAIL;
+ }
+
+ args.mode = mode;
+ return r->access_memory(target, args);
+ }
+
+ bool mmu_enabled = false;
+ int result = riscv_mmu_impl(target, mode, &mmu_enabled);
if (result != ERROR_OK)
return result;
- RISCV_INFO(r);
if (!mmu_enabled)
return r->access_memory(target, args);
@@ -5350,6 +5400,7 @@ COMMAND_HANDLER(handle_repeat_read)
}
const struct riscv_mem_access_args args = {
.address = address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = size,
.count = count,
@@ -5746,7 +5797,7 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.handler = handle_repeat_read,
.mode = COMMAND_ANY,
.usage = "count address [size=4]",
- .help = "Repeatedly read the value at address."
+ .help = "Repeatedly read the value at the given physical address."
},
{
.name = "set_command_timeout_sec",
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index c2e727fc9..c2e34a548 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -132,8 +132,18 @@ struct reg_name_table {
char **reg_names;
};
+enum riscv_priv_mode {
+ RISCV_MODE_M,
+ RISCV_MODE_S,
+ RISCV_MODE_U,
+ RISCV_MODE_VS,
+ RISCV_MODE_VU,
+ N_RISCV_MODE
+};
+
struct riscv_mem_access_args {
target_addr_t address;
+ enum riscv_priv_mode mode;
const uint8_t *write_buffer;
uint8_t *read_buffer;
@@ -366,15 +376,6 @@ struct riscv_info {
bool autofence;
};
-enum riscv_priv_mode {
- RISCV_MODE_M,
- RISCV_MODE_S,
- RISCV_MODE_U,
- RISCV_MODE_VS,
- RISCV_MODE_VU,
- N_RISCV_MODE
-};
-
struct riscv_private_config {
bool dcsr_ebreak_fields[N_RISCV_MODE];
bool dcsr_cetrig;
@@ -409,9 +410,6 @@ typedef struct {
unsigned int pa_ppn_mask[PG_MAX_LEVEL];
} virt2phys_info_t;
-bool riscv_virt2phys_mode_is_hw(const struct target *target);
-bool riscv_virt2phys_mode_is_sw(const struct target *target);
-
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
int riscv_get_command_timeout_sec(void);
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 2 +
src/target/riscv/riscv-011.c | 7 ++++
src/target/riscv/riscv-013.c | 29 +++++++++++---
src/target/riscv/riscv.c | 91 ++++++++++++++++++++++++++++++++++----------
src/target/riscv/riscv.h | 22 +++++------
5 files changed, 113 insertions(+), 38 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|