From 31175e572745e5d3864f5b4e9524bbd55424fd96 Mon Sep 17 00:00:00 2001 From: Farid Khaydari Date: Tue, 6 May 2025 17:01:42 +0300 Subject: [PATCH 1/2] target/riscv: fix riscv_mmu behaviour Fixed riscv_mmu behaviour: buggy check was removed. As a result virt2phys command behaviour was fixed: now it returns translated address even while virt2phys_mode is off. Change-Id: Ie2e6d1057024ab794038d5ed3662ef49a4d71e70 Signed-off-by: Farid Khaydari --- src/target/riscv/riscv.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index aae5eb35a9..de51cfd64c 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -3017,9 +3017,6 @@ static int riscv_mmu(struct target *target, int *enabled) { *enabled = 0; - if (!riscv_virt2phys_mode_is_sw(target)) - return ERROR_OK; - /* Don't use MMU in explicit or effective M (machine) mode */ riscv_reg_t priv; if (riscv_reg_get(target, &priv, GDB_REGNO_PRIV) != ERROR_OK) { @@ -3425,16 +3422,11 @@ static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t return ERROR_OK; } - int mmu_enabled; - int result = riscv_mmu(target, &mmu_enabled); - if (result != ERROR_OK) - return result; - RISCV_INFO(r); - if (!mmu_enabled) + if (riscv_virt2phys_mode_is_hw(target)) return r->access_memory(target, args); - result = check_virt_memory_access(target, args.address, + int result = check_virt_memory_access(target, args.address, args.size, args.count, is_write); if (result != ERROR_OK) return result; From b078514cad540255a0c5631f23b56c76fd7e8bb9 Mon Sep 17 00:00:00 2001 From: Farid Khaydari Date: Thu, 13 Mar 2025 22:57:08 +0300 Subject: [PATCH 2/2] target/riscv: add is_virtual parameter to memory access method Added is_virtual parameter to memory access method. This change is required to support hw translation appropriately. Updated repeat_read documentation according to new behaviour Change-Id: I6970b4dd9d57ff5c032a6c435358003e9a66d21c Signed-off-by: Farid Khaydari --- doc/openocd.texi | 6 ++--- src/target/riscv/riscv-011.c | 3 ++- src/target/riscv/riscv-013.c | 16 +++++++++---- src/target/riscv/riscv.c | 45 +++++++++++++++++++++++++----------- src/target/riscv/riscv.h | 4 +++- 5 files changed, 51 insertions(+), 23 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 1dcb7f3f5a..11a9c8fc22 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11522,9 +11522,9 @@ dump_sample_buf}. @end deffn @deffn {Command} {riscv repeat_read} count address [size=4] -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. +Quickly read count words of the given size from physical 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. @end deffn @deffn {Command} {riscv info} diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 54de6a10db..d1fbf1eb87 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -2339,7 +2339,8 @@ static int write_memory(struct target *target, const riscv_mem_access_args_t arg return ERROR_FAIL; } -static int access_memory(struct target *target, const riscv_mem_access_args_t args) +static int access_memory(struct target *target, + const riscv_mem_access_args_t args, const bool is_virtual) { assert(riscv_mem_access_is_valid(args)); const bool is_write = riscv_mem_access_is_write(args); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 46c61cab8d..b5e660931b 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -64,7 +64,8 @@ static int register_read_direct(struct target *target, riscv_reg_t *value, enum gdb_regno number); static int register_write_direct(struct target *target, enum gdb_regno number, riscv_reg_t value); -static int riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args); +static int riscv013_access_memory(struct target *target, + const riscv_mem_access_args_t args, const bool is_virtual); static bool riscv013_get_impebreak(const struct target *target); static unsigned int riscv013_get_progbufsize(const struct target *target); @@ -1277,7 +1278,8 @@ static int scratch_read64(struct target *target, scratch_mem_t *scratch, .count = 2, .increment = 4, }; - if (riscv013_access_memory(target, args) != ERROR_OK) + if (riscv013_access_memory(target, args, + /* is_virtual */ false) != ERROR_OK) return ERROR_FAIL; *value = buf_get_u64(buffer, /* first = */ 0, /* bit_num = */ 64); @@ -1319,7 +1321,8 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch, .count = 2, .increment = 4, }; - if (riscv013_access_memory(target, args) != ERROR_OK) + if (riscv013_access_memory(target, args, + /* is_virtual */ false) != ERROR_OK) return ERROR_FAIL; } break; @@ -4551,8 +4554,8 @@ access_memory_abstract(struct target *target, const riscv_mem_access_args_t args write_memory_abstract(target, args); } -static int -riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args) +static int riscv013_access_memory(struct target *target, + const riscv_mem_access_args_t args, const bool is_virtual) { assert(riscv_mem_access_is_valid(args)); @@ -4580,12 +4583,15 @@ riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args riscv_mem_access_method_t method = r->mem_access_methods[i]; switch (method) { case RISCV_MEM_ACCESS_PROGBUF: + // TODO: pass is_virtual here in future commits skip_reason[method] = access_memory_progbuf(target, args); break; case RISCV_MEM_ACCESS_SYSBUS: + // TODO: pass is_virtual here in future commits skip_reason[method] = access_memory_sysbus(target, args); break; case RISCV_MEM_ACCESS_ABSTRACT: + // TODO: pass is_virtual here in future commits skip_reason[method] = access_memory_abstract(target, args); break; default: diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index de51cfd64c..905fa8daf2 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -155,6 +155,13 @@ bool riscv_virt2phys_mode_is_sw(const struct target *target) return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_SW; } +bool riscv_virt2phys_mode_is_off(const struct target *target) +{ + assert(target); + RISCV_INFO(r); + return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_OFF; +} + const char *riscv_virt2phys_mode_to_str(riscv_virt2phys_mode_t mode) { assert(mode == RISCV_VIRT2PHYS_MODE_OFF @@ -3149,7 +3156,7 @@ static int riscv_address_translate(struct target *target, .increment = 4, .count = (1 << info->pte_shift) / 4, }; - int retval = r->access_memory(target, args); + int retval = r->access_memory(target, args, /* is_virtual */ false); if (retval != ERROR_OK) return ERROR_FAIL; @@ -3382,6 +3389,14 @@ static int check_virt_memory_access(struct target *target, target_addr_t address return ERROR_OK; } +static int riscv_access_phys_memory(struct target *target, + const riscv_mem_access_args_t args) +{ + RISCV_INFO(r); + return r->access_memory(target, args, /* is_virtual */ false); +} + + static int riscv_read_phys_memory(struct target *target, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer) { @@ -3392,8 +3407,7 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr .count = count, .increment = size, }; - RISCV_INFO(r); - return r->access_memory(target, args); + return riscv_access_phys_memory(target, args); } static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address, @@ -3406,12 +3420,11 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add .count = count, .increment = size, }; - - RISCV_INFO(r); - return r->access_memory(target, args); + return riscv_access_phys_memory(target, args); } -static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t args) +static int riscv_access_virt_memory(struct target *target, + const riscv_mem_access_args_t args) { assert(riscv_mem_access_is_valid(args)); @@ -3423,8 +3436,11 @@ static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t } RISCV_INFO(r); + if (riscv_virt2phys_mode_is_off(target)) + return r->access_memory(target, args, /* is_virtual */ false); + if (riscv_virt2phys_mode_is_hw(target)) - return r->access_memory(target, args); + return r->access_memory(target, args, /* is_virtual */ true); int result = check_virt_memory_access(target, args.address, args.size, args.count, is_write); @@ -3456,7 +3472,8 @@ static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t else current_access.read_buffer += current_count * args.size; - result = r->access_memory(target, current_access); + result = r->access_memory(target, + current_access, /* is_virtual */ false); if (result != ERROR_OK) return result; @@ -3477,7 +3494,7 @@ static int riscv_read_memory(struct target *target, target_addr_t address, .increment = size, }; - return riscv_rw_memory(target, args); + return riscv_access_virt_memory(target, args); } static int riscv_write_memory(struct target *target, target_addr_t address, @@ -3491,7 +3508,7 @@ static int riscv_write_memory(struct target *target, target_addr_t address, .increment = size, }; - return riscv_rw_memory(target, args); + return riscv_access_virt_memory(target, args); } static const char *riscv_get_gdb_arch(const struct target *target) @@ -5224,7 +5241,9 @@ COMMAND_HANDLER(handle_repeat_read) .count = count, .increment = 0, }; - int result = r->access_memory(target, args); + /* TODO: Add a command parameter that enables + * choosing between virtual and physical access */ + int result = r->access_memory(target, args, /* is_virtual */ false); if (result == ERROR_OK) { target_handle_md_output(cmd, target, address, size, count, buffer, false); @@ -5607,7 +5626,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 physical address." }, { .name = "set_command_timeout_sec", diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 082445e40a..adf8dc12c0 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -303,7 +303,8 @@ struct riscv_info { riscv_sample_config_t *config, int64_t until_ms); - int (*access_memory)(struct target *target, const riscv_mem_access_args_t args); + int (*access_memory)(struct target *target, + const riscv_mem_access_args_t args, const bool is_virtual); unsigned int (*data_bits)(struct target *target); @@ -411,6 +412,7 @@ typedef struct { bool riscv_virt2phys_mode_is_hw(const struct target *target); bool riscv_virt2phys_mode_is_sw(const struct target *target); +bool riscv_virt2phys_mode_is_off(const struct target *target); /* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/ int riscv_get_command_timeout_sec(void);