aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2019-07-26 11:08:35 -0700
committerGitHub <noreply@github.com>2019-07-26 11:08:35 -0700
commit7eaf60f1b58da45087fb8e5c5808b84b3451c990 (patch)
tree25fa9b206e0834242464afd378d49dc38bb261bf
parent239a515a9cc0cf7d7ebcc7c1a710ff40de721ca8 (diff)
downloadriscv-openocd-7eaf60f1b58da45087fb8e5c5808b84b3451c990.zip
riscv-openocd-7eaf60f1b58da45087fb8e5c5808b84b3451c990.tar.gz
riscv-openocd-7eaf60f1b58da45087fb8e5c5808b84b3451c990.tar.bz2
Properly detect errors in SBA reads. (#392)
Also don't set/clear sbreadondata when only reading one word. Change-Id: Ia81834014895f1f4b552312ad0b60b3d3967a2c7
-rw-r--r--src/target/riscv/riscv-013.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 6b7da47..cb4f9fe 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -2211,11 +2211,12 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
target_addr_t end_address = address + count * size;
while (next_address < end_address) {
- uint32_t sbcs = set_field(0, DMI_SBCS_SBREADONADDR, 1);
- sbcs |= sb_sbaccess(size);
- sbcs = set_field(sbcs, DMI_SBCS_SBAUTOINCREMENT, 1);
- sbcs = set_field(sbcs, DMI_SBCS_SBREADONDATA, count > 1);
- if (dmi_write(target, DMI_SBCS, sbcs) != ERROR_OK)
+ uint32_t sbcs_write = set_field(0, DMI_SBCS_SBREADONADDR, 1);
+ sbcs_write |= sb_sbaccess(size);
+ sbcs_write = set_field(sbcs_write, DMI_SBCS_SBAUTOINCREMENT, 1);
+ if (count > 1)
+ sbcs_write = set_field(sbcs_write, DMI_SBCS_SBREADONDATA, count > 1);
+ if (dmi_write(target, DMI_SBCS, sbcs_write) != ERROR_OK)
return ERROR_FAIL;
/* This address write will trigger the first read. */
@@ -2236,23 +2237,29 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_FAIL;
}
- /* "Writes to sbcs while sbbusy is high result in undefined behavior.
- * A debugger must not write to sbcs until it reads sbbusy as 0." */
- if (read_sbcs_nonbusy(target, &sbcs) != ERROR_OK)
- return ERROR_FAIL;
+ uint32_t sbcs_read = 0;
+ if (count > 1) {
+ /* "Writes to sbcs while sbbusy is high result in undefined behavior.
+ * A debugger must not write to sbcs until it reads sbbusy as 0." */
+ if (read_sbcs_nonbusy(target, &sbcs_read) != ERROR_OK)
+ return ERROR_FAIL;
- sbcs = set_field(sbcs, DMI_SBCS_SBREADONDATA, 0);
- if (dmi_write(target, DMI_SBCS, sbcs) != ERROR_OK)
- return ERROR_FAIL;
+ sbcs_write = set_field(sbcs_write, DMI_SBCS_SBREADONDATA, 0);
+ if (dmi_write(target, DMI_SBCS, sbcs_write) != ERROR_OK)
+ return ERROR_FAIL;
+ }
- if (read_memory_bus_word(target, address + (count - 1) * size, size,
- buffer + (count - 1) * size) != ERROR_OK)
- return ERROR_FAIL;
+ if (!get_field(sbcs_read, DMI_SBCS_SBERROR) &&
+ !get_field(sbcs_read, DMI_SBCS_SBBUSYERROR)) {
+ if (read_memory_bus_word(target, address + (count - 1) * size, size,
+ buffer + (count - 1) * size) != ERROR_OK)
+ return ERROR_FAIL;
- if (read_sbcs_nonbusy(target, &sbcs) != ERROR_OK)
- return ERROR_FAIL;
+ if (read_sbcs_nonbusy(target, &sbcs_read) != ERROR_OK)
+ return ERROR_FAIL;
+ }
- if (get_field(sbcs, DMI_SBCS_SBBUSYERROR)) {
+ if (get_field(sbcs_read, DMI_SBCS_SBBUSYERROR)) {
/* We read while the target was busy. Slow down and try again. */
if (dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR) != ERROR_OK)
return ERROR_FAIL;
@@ -2261,7 +2268,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
continue;
}
- unsigned error = get_field(sbcs, DMI_SBCS_SBERROR);
+ unsigned error = get_field(sbcs_read, DMI_SBCS_SBERROR);
if (error == 0) {
next_address = end_address;
} else {