diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 1a3f4b12e..2c0af9b65 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -2298,6 +2298,15 @@ 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) +{ + assert(riscv_mem_access_is_valid(args)); + const bool is_write = riscv_mem_access_is_write(args); + if (is_write) + return write_memory(target, args); + return read_memory(target, args); +} + static int arch_state(struct target *target) { return ERROR_OK; @@ -2390,8 +2399,7 @@ static int init_target(struct command_context *cmd_ctx, LOG_DEBUG("init"); RISCV_INFO(generic_info); /* TODO: replace read and write with single access function*/ - generic_info->read_memory = read_memory; - generic_info->write_memory = write_memory; + generic_info->access_memory = access_memory; generic_info->authdata_read = &riscv011_authdata_read; generic_info->authdata_write = &riscv011_authdata_write; generic_info->print_info = &riscv011_print_info; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index c399de7e4..ba005d80b 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -65,8 +65,7 @@ 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 read_memory(struct target *target, const riscv_mem_access_args_t args); -static int write_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); static bool riscv013_get_impebreak(const struct target *target); static unsigned int riscv013_get_progbufsize(const struct target *target); @@ -1207,7 +1206,7 @@ static int scratch_read64(struct target *target, scratch_mem_t *scratch, .count = 2, .increment = 4, }; - if (read_memory(target, args) != ERROR_OK) + if (riscv013_access_memory(target, args) != ERROR_OK) return ERROR_FAIL; *value = buf_get_u64(buffer, /* first = */ 0, /* bit_num = */ 64); @@ -1249,7 +1248,7 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch, .count = 2, .increment = 4, }; - if (write_memory(target, args) != ERROR_OK) + if (riscv013_access_memory(target, args) != ERROR_OK) return ERROR_FAIL; } break; @@ -2778,8 +2777,7 @@ static int init_target(struct command_context *cmd_ctx, generic_info->dmi_write = &dmi_write; generic_info->get_dmi_address = &riscv013_get_dmi_address; /* TODO: replace read and write with single access function*/ - generic_info->read_memory = read_memory; - generic_info->write_memory = write_memory; + generic_info->access_memory = &riscv013_access_memory; generic_info->data_bits = &riscv013_data_bits; generic_info->print_info = &riscv013_print_info; generic_info->get_impebreak = &riscv013_get_impebreak; @@ -3451,7 +3449,8 @@ typedef enum { MEM_ACCESS_RESULT_TYPE_FAILED, "failed (DM register access failed)") \ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PRIV_MOD_FAILED, \ MEM_ACCESS_RESULT_TYPE_FAILED, "failed (privilege modification failed)") \ - + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_REG_WRITE_FAILED, \ + MEM_ACCESS_RESULT_TYPE_FAILED, "failed (register write failed)") \ #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) name, typedef enum { @@ -3620,16 +3619,9 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args) { assert(riscv_mem_access_is_read(args)); - mem_access_result_t skip_reason = mem_should_skip_abstract(target, args); - if (skip_reason != MEM_ACCESS_OK) - return skip_reason; - RISCV013_INFO(info); bool use_aampostincrement = info->has_aampostincrement != YNM_NO; - LOG_TARGET_DEBUG(target, "Reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, args.count, - args.size, args.address); - memset(args.read_buffer, 0, args.count * args.size); /* Convert the size (bytes) to width (bits) */ @@ -3717,17 +3709,10 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args) { assert(riscv_mem_access_is_write(args)); - mem_access_result_t skip_reason = mem_should_skip_abstract(target, args); - if (skip_reason != MEM_ACCESS_OK) - return skip_reason; - RISCV013_INFO(info); int result = ERROR_OK; bool use_aampostincrement = info->has_aampostincrement != YNM_NO; - LOG_TARGET_DEBUG(target, "writing %d words of %d bytes from 0x%" TARGET_PRIxADDR, args.count, - args.size, args.address); - /* Convert the size (bytes) to width (bits) */ unsigned int width = args.size << 3; @@ -4341,77 +4326,127 @@ static int read_memory_progbuf_inner_one(struct target *target, /** * Read the requested memory, silently handling memory access errors. */ -static mem_access_result_t -read_memory_progbuf(struct target *target, const riscv_mem_access_args_t args) +static mem_access_result_t read_memory_progbuf(struct target *target, + const riscv_mem_access_args_t args, bool mprven) { assert(riscv_mem_access_is_read(args)); - mem_access_result_t skip_reason = mem_should_skip_progbuf(target, args); - if (skip_reason != MEM_ACCESS_OK) - return skip_reason; - - LOG_TARGET_DEBUG(target, "reading %" PRIu32 " elements of %" PRIu32 - " bytes from 0x%" TARGET_PRIxADDR, args.count, args.size, args.address); - - if (dm013_select_target(target) != ERROR_OK) - return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED; - select_dmi(target); - memset(args.read_buffer, 0, args.count * args.size); if (execute_autofence(target) != ERROR_OK) return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED; + int res = (args.count == 1) ? + read_memory_progbuf_inner_one(target, args, mprven) : + read_memory_progbuf_inner(target, args, mprven); + + return res == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED; +} + +static mem_access_result_t write_memory_progbuf(struct target *target, + const riscv_mem_access_args_t args, bool mprven); + +static mem_access_result_t +access_memory_progbuf(struct target *target, const riscv_mem_access_args_t args) +{ + mem_access_result_t result = mem_should_skip_progbuf(target, args); + if (result != MEM_ACCESS_OK) + return result; + + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "read" : "write"; + LOG_TARGET_DEBUG(target, "%sing %" PRIu32 " words of %" PRIu32 + " bytes to 0x%" TARGET_PRIxADDR, access_type, args.count, + args.size, args.address); + + if (dm013_select_target(target) != ERROR_OK) + return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED; + uint64_t mstatus = 0; uint64_t mstatus_old = 0; if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK) return MEM_ACCESS_FAILED_PRIV_MOD_FAILED; - const bool mprven = riscv_virt2phys_mode_is_hw(target) + const bool mprven_required = riscv_virt2phys_mode_is_hw(target) && get_field(mstatus, MSTATUS_MPRV); - int result = (args.count == 1) ? - read_memory_progbuf_inner_one(target, args, mprven) : - read_memory_progbuf_inner(target, args, mprven); - if (mstatus != mstatus_old && - register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK) - return MEM_ACCESS_FAILED; + result = is_read ? read_memory_progbuf(target, args, mprven_required) : + write_memory_progbuf(target, args, mprven_required); - return (result == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED; + if (mstatus != mstatus_old && register_write_direct(target, + GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK) + return MEM_ACCESS_SKIPPED_REG_WRITE_FAILED; + + return result; } +static int +write_memory_bus_v0(struct target *target, const riscv_mem_access_args_t args); +static int +write_memory_bus_v1(struct target *target, const riscv_mem_access_args_t args); + static mem_access_result_t -read_memory_sysbus(struct target *target, const riscv_mem_access_args_t args) +access_memory_sysbus(struct target *target, const riscv_mem_access_args_t args) { - assert(riscv_mem_access_is_read(args)); + assert(riscv_mem_access_is_valid(args)); - mem_access_result_t skip_reason = mem_should_skip_sysbus(target, args); - if (skip_reason != MEM_ACCESS_OK) - return skip_reason; + mem_access_result_t result = mem_should_skip_sysbus(target, args); + if (result != MEM_ACCESS_OK) + return result; - int ret = ERROR_FAIL; - uint64_t sbver = get_field(get_info(target)->sbcs, DM_SBCS_SBVERSION); + RISCV013_INFO(info); + int res = ERROR_FAIL; + const bool is_read = riscv_mem_access_is_read(args); + const uint64_t sbver = get_field(info->sbcs, DM_SBCS_SBVERSION); if (sbver == 0) - ret = read_memory_bus_v0(target, args); + res = is_read ? read_memory_bus_v0(target, args) : + write_memory_bus_v0(target, args); else if (sbver == 1) - ret = read_memory_bus_v1(target, args); + res = is_read ? read_memory_bus_v1(target, args) : + write_memory_bus_v1(target, args); else - LOG_TARGET_ERROR(target, - "Unknown system bus version: %" PRIu64, sbver); + LOG_TARGET_ERROR(target, "Unknown system bus version: %" PRIu64, sbver); - return (ret == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED; + return res == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED; } -static int read_memory(struct target *target, const riscv_mem_access_args_t args) +static mem_access_result_t +access_memory_abstract(struct target *target, const riscv_mem_access_args_t args) { - assert(riscv_mem_access_is_read(args)); + assert(riscv_mem_access_is_valid(args)); - if (args.count == 0) - return ERROR_OK; + mem_access_result_t res = mem_should_skip_abstract(target, args); + if (res != MEM_ACCESS_OK) + return res; + + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "read" : "write"; + LOG_TARGET_DEBUG(target, "%sing %d words of %d bytes from 0x%" + TARGET_PRIxADDR, access_type, args.count, + args.size, args.address); + + int result = is_read ? read_memory_abstract(target, args) : + write_memory_abstract(target, args); + + return result == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED; +} + +static int +riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args) +{ + assert(riscv_mem_access_is_valid(args)); + + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "read" : "write"; + 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; + } if (!IS_PWR_OF_2(args.size) || args.size < 1 || args.size > 16) { - LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory read: %d", args.size); + LOG_TARGET_ERROR(target, "BUG: Unsupported size for " + "memory %s: %d", access_type, args.size); return ERROR_FAIL; } @@ -4424,34 +4459,36 @@ static int read_memory(struct target *target, const riscv_mem_access_args_t args RISCV_INFO(r); for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; ++i) { riscv_mem_access_method_t method = r->mem_access_methods[i]; + + mem_access_result_t result = MEM_ACCESS_DISABLED; switch (method) { - case RISCV_MEM_ACCESS_PROGBUF: - skip_reason[method] = read_memory_progbuf(target, args); - break; - case RISCV_MEM_ACCESS_SYSBUS: - skip_reason[method] = read_memory_sysbus(target, args); - break; - case RISCV_MEM_ACCESS_ABSTRACT: - skip_reason[method] = read_memory_abstract(target, args); - break; - default: - LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method); - assert(false); - return ERROR_FAIL; + case RISCV_MEM_ACCESS_PROGBUF: + result = access_memory_progbuf(target, args); + break; + case RISCV_MEM_ACCESS_SYSBUS: + result = access_memory_sysbus(target, args); + break; + case RISCV_MEM_ACCESS_ABSTRACT: + result = access_memory_abstract(target, args); + break; + default: + assert(false && "Unknown memory access method"); + goto failure; } - if (is_mem_access_failed(skip_reason[method])) + skip_reason[method] = result; + if (is_mem_access_failed(result)) goto failure; - const bool success = (skip_reason[method] == MEM_ACCESS_OK); - log_mem_access_result(target, success, method, /* is_read = */ true); + const bool success = (result == MEM_ACCESS_OK); + log_mem_access_result(target, success, method, is_read); if (success) return ERROR_OK; } failure: - LOG_TARGET_ERROR(target, "Failed to read memory (addr=0x%" PRIx64 ")\n" - " progbuf=%s, sysbus=%s, abstract=%s", args.address, + LOG_TARGET_ERROR(target, "Failed to %s memory (addr=0x%" PRIx64 ")\n" + " progbuf=%s, sysbus=%s, abstract=%s", access_type, args.address, mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]), mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]), mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT])); @@ -4906,126 +4943,19 @@ static int write_memory_progbuf_inner(struct target *target, const riscv_mem_acc return write_memory_progbuf_teardown(target); } -static mem_access_result_t -write_memory_progbuf(struct target *target, const riscv_mem_access_args_t args) +static mem_access_result_t write_memory_progbuf(struct target *target, + const riscv_mem_access_args_t args, bool mprven) { assert(riscv_mem_access_is_write(args)); - mem_access_result_t skip_reason = mem_should_skip_progbuf(target, args); - if (skip_reason != MEM_ACCESS_OK) - return skip_reason; - - LOG_TARGET_DEBUG(target, "writing %" PRIu32 " words of %" PRIu32 - " bytes to 0x%" TARGET_PRIxADDR, args.count, args.size, args.address); - - if (dm013_select_target(target) != ERROR_OK) - return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED; - - uint64_t mstatus = 0; - uint64_t mstatus_old = 0; - if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK) - return MEM_ACCESS_FAILED_PRIV_MOD_FAILED; - - const bool mprven = riscv_virt2phys_mode_is_hw(target) - && get_field(mstatus, MSTATUS_MPRV); - int result = write_memory_progbuf_inner(target, args, mprven); - /* Restore MSTATUS */ - if (mstatus != mstatus_old) - if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old)) - return MEM_ACCESS_FAILED; - if (execute_autofence(target) != ERROR_OK) return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED; return result == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED; } -static mem_access_result_t -write_memory_sysbus(struct target *target, const riscv_mem_access_args_t args) -{ - assert(riscv_mem_access_is_write(args)); - - riscv013_info_t *info = get_info(target); - mem_access_result_t skip_reason = mem_should_skip_sysbus(target, args); - if (skip_reason != MEM_ACCESS_OK) - return skip_reason; - - /* TODO: write_memory_bus_* should return mem_access_result_t too*/ - int ret = ERROR_FAIL; - uint64_t sbver = get_field(info->sbcs, DM_SBCS_SBVERSION); - if (sbver == 0) - ret = write_memory_bus_v0(target, args); - else if (sbver == 1) - ret = write_memory_bus_v1(target, args); - else - LOG_TARGET_ERROR(target, - "Unknown system bus version: %" PRIu64, sbver); - - if (ret != ERROR_OK) - skip_reason = MEM_ACCESS_FAILED; - - return skip_reason; -} - -static int write_memory(struct target *target, const riscv_mem_access_args_t args) -{ - assert(riscv_mem_access_is_write(args)); - - if (args.increment != args.size) { - LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size"); - return ERROR_NOT_IMPLEMENTED; - } - - if (!IS_PWR_OF_2(args.size) || args.size < 1 || args.size > 16) { - LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory write: %d", args.size); - return ERROR_FAIL; - } - - mem_access_result_t skip_reason[] = { - [RISCV_MEM_ACCESS_PROGBUF] = MEM_ACCESS_DISABLED, - [RISCV_MEM_ACCESS_SYSBUS] = MEM_ACCESS_DISABLED, - [RISCV_MEM_ACCESS_ABSTRACT] = MEM_ACCESS_DISABLED - }; - - RISCV_INFO(r); - for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; ++i) { - riscv_mem_access_method_t method = r->mem_access_methods[i]; - switch (method) { - case RISCV_MEM_ACCESS_PROGBUF: - skip_reason[method] = write_memory_progbuf(target, args); - break; - case RISCV_MEM_ACCESS_SYSBUS: - skip_reason[method] = write_memory_sysbus(target, args); - break; - case RISCV_MEM_ACCESS_ABSTRACT: - skip_reason[method] = write_memory_abstract(target, args); - break; - default: - LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method); - assert(false); - return ERROR_FAIL; - } - - if (is_mem_access_failed(skip_reason[method])) - goto failure; - - const bool success = (skip_reason[method] == MEM_ACCESS_OK); - log_mem_access_result(target, success, method, /* is_read = */ false); - if (success) - return ERROR_OK; - } - -failure: - LOG_TARGET_ERROR(target, "Failed to write memory (addr=0x%" PRIx64 ")\n" - "progbuf=%s, sysbus=%s, abstract=%s", args.address, - mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]), - mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]), - mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT])); - return ERROR_FAIL; -} - static bool riscv013_get_impebreak(const struct target *target) { RISCV013_INFO(r); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 0ca921657..27d5719c2 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -2968,7 +2968,7 @@ static int riscv_address_translate(struct target *target, .increment = 4, .count = (1 << info->pte_shift) / 4, }; - int retval = r->read_memory(target, args); + int retval = r->access_memory(target, args); if (retval != ERROR_OK) return ERROR_FAIL; @@ -3212,7 +3212,7 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr .increment = size, }; RISCV_INFO(r); - return r->read_memory(target, args); + return r->access_memory(target, args); } static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address, @@ -3227,7 +3227,7 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add }; RISCV_INFO(r); - return r->write_memory(target, args); + return r->access_memory(target, args); } static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t args) @@ -3247,12 +3247,8 @@ static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t return result; RISCV_INFO(r); - if (!mmu_enabled) { - if (is_write) - return r->write_memory(target, args); - else - return r->read_memory(target, args); - } + if (!mmu_enabled) + return r->access_memory(target, args); result = check_virt_memory_access(target, args.address, args.size, args.count, is_write); @@ -3279,13 +3275,12 @@ static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t riscv_mem_access_args_t current_access = args; current_access.address = physical_addr; current_access.count = chunk_count; - if (is_write) { + if (is_write) current_access.write_buffer += current_count * args.size; - result = r->write_memory(target, current_access); - } else { + else current_access.read_buffer += current_count * args.size; - result = r->read_memory(target, current_access); - } + + result = r->access_memory(target, current_access); if (result != ERROR_OK) return result; @@ -4981,7 +4976,7 @@ COMMAND_HANDLER(handle_repeat_read) .count = count, .increment = 0, }; - int result = r->read_memory(target, args); + int result = r->access_memory(target, args); if (result == ERROR_OK) { target_handle_md_output(cmd, target, address, size, count, buffer, false); diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 482d0fd71..f3c4cf79d 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -300,8 +300,7 @@ struct riscv_info { riscv_sample_config_t *config, int64_t until_ms); - int (*read_memory)(struct target *target, const riscv_mem_access_args_t args); - int (*write_memory)(struct target *target, const riscv_mem_access_args_t args); + int (*access_memory)(struct target *target, const riscv_mem_access_args_t args); unsigned int (*data_bits)(struct target *target);