From de00906ebd6edc74c0cf5fff0d3d7beb82c39b7b Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 22 Nov 2019 11:37:46 -0800 Subject: [PATCH] Fix memory access on some targets. (#428) Fix memory access on 64-bit targets with no progbuf and sba that supports 32-bit accesses but not 64-bit accesses. Bug was introduced in #419. This fixes https://github.com/riscv/riscv-tests/issues/217. Change-Id: Ib5ddf9886b77e3d58fe1d891b560ad03d5a46da1 --- src/target/riscv/riscv-013.c | 24 ++++++++++++++++++++++++ src/target/riscv/riscv.c | 10 +++++++++- src/target/riscv/riscv.h | 1 + src/target/target_type.h | 6 +++--- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index a673265e7..417cb9f13 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1727,6 +1727,29 @@ static int riscv013_hart_count(struct target *target) return dm->hart_count; } +static unsigned riscv013_data_bits(struct target *target) +{ + RISCV013_INFO(info); + /* TODO: Once there is a spec for discovering abstract commands, we can + * take those into account as well. For now we assume abstract commands + * support XLEN-wide accesses. */ + if (info->progbufsize >= 2 && !riscv_prefer_sba) + return riscv_xlen(target); + + if (get_field(info->sbcs, DMI_SBCS_SBACCESS128)) + return 128; + if (get_field(info->sbcs, DMI_SBCS_SBACCESS64)) + return 64; + if (get_field(info->sbcs, DMI_SBCS_SBACCESS32)) + return 32; + if (get_field(info->sbcs, DMI_SBCS_SBACCESS16)) + return 16; + if (get_field(info->sbcs, DMI_SBCS_SBACCESS8)) + return 8; + + return riscv_xlen(target); +} + static int init_target(struct command_context *cmd_ctx, struct target *target) { @@ -1759,6 +1782,7 @@ static int init_target(struct command_context *cmd_ctx, generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg; generic_info->test_compliance = &riscv013_test_compliance; generic_info->hart_count = &riscv013_hart_count; + generic_info->data_bits = &riscv013_data_bits; generic_info->version_specific = calloc(1, sizeof(riscv013_info_t)); if (!generic_info->version_specific) return ERROR_FAIL; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 41ac87c3a..ec00d9f7e 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -2462,6 +2462,14 @@ static unsigned riscv_xlen_nonconst(struct target *target) return riscv_xlen(target); } +static unsigned riscv_data_bits(struct target *target) +{ + RISCV_INFO(r); + if (r->data_bits) + return r->data_bits(target); + return riscv_xlen(target); +} + struct target_type riscv_target = { .name = "riscv", @@ -2501,7 +2509,7 @@ struct target_type riscv_target = { .commands = riscv_command_handlers, .address_bits = riscv_xlen_nonconst, - .data_bits = riscv_xlen_nonconst + .data_bits = riscv_data_bits }; /*** RISC-V Interface ***/ diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 3dfb4e58d..855116ae1 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -146,6 +146,7 @@ typedef struct { /* How many harts are attached to the DM that this target is attached to? */ int (*hart_count)(struct target *target); + unsigned (*data_bits)(struct target *target); } riscv_info_t; typedef struct { diff --git a/src/target/target_type.h b/src/target/target_type.h index b94be12ba..87ef829ae 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -297,9 +297,9 @@ struct target_type { * implemented, it's assumed to be 32. */ unsigned (*address_bits)(struct target *target); - /* Return the number of data bits this target supports. This will - * typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not - * implemented, it's assumed to be 32. */ + /* Return the number of system bus data bits this target supports. This + * will typically be 32 for 32-bit targets, and 64 for 64-bit targets. If + * not implemented, it's assumed to be 32. */ unsigned (*data_bits)(struct target *target); };