aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-12-29 14:35:49 -0800
committerTim Newsome <tim@sifive.com>2018-01-08 11:53:02 -0800
commitfd506fa839892cddf8aab06192f4259fba81037c (patch)
tree932ef064497895daf4a475afb0fef828eb6a3eea /src
parent0e3869cbf6c5b0ff517f5ce13b69681fc34c32b5 (diff)
downloadriscv-openocd-fd506fa839892cddf8aab06192f4259fba81037c.zip
riscv-openocd-fd506fa839892cddf8aab06192f4259fba81037c.tar.gz
riscv-openocd-fd506fa839892cddf8aab06192f4259fba81037c.tar.bz2
Propagate register read errors.
Change-Id: Idda111377873a2236b5b91e4ffdabd2be384b47a
Diffstat (limited to 'src')
-rw-r--r--src/rtos/riscv_debug.c7
-rw-r--r--src/target/riscv/program.c4
-rw-r--r--src/target/riscv/riscv-011.c29
-rw-r--r--src/target/riscv/riscv-013.c56
-rw-r--r--src/target/riscv/riscv.c66
-rw-r--r--src/target/riscv/riscv.h15
6 files changed, 115 insertions, 62 deletions
diff --git a/src/rtos/riscv_debug.c b/src/rtos/riscv_debug.c
index bc46754..158160e 100644
--- a/src/rtos/riscv_debug.c
+++ b/src/rtos/riscv_debug.c
@@ -281,7 +281,12 @@ static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char
*hex_reg_list[0] = '\0';
for (size_t i = 0; i < n_regs; ++i) {
if (riscv_has_register(rtos->target, thread_id, i)) {
- uint64_t reg_value = riscv_get_register_on_hart(rtos->target, thread_id - 1, i);
+ uint64_t reg_value;
+ int result = riscv_get_register_on_hart(rtos->target, &reg_value,
+ thread_id - 1, i);
+ if (result != ERROR_OK)
+ return JIM_ERR;
+
for (size_t byte = 0; byte < xlen / 8; ++byte) {
uint8_t reg_byte = reg_value >> (byte * 8);
char hex[3] = {'x', 'x', 'x'};
diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c
index a7a2e85..25a0676 100644
--- a/src/target/riscv/program.c
+++ b/src/target/riscv/program.c
@@ -47,7 +47,9 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
for (size_t i = GDB_REGNO_ZERO + 1; i <= GDB_REGNO_XPR31; ++i) {
if (p->writes_xreg[i]) {
LOG_DEBUG("Saving register %d as used by program", (int)i);
- saved_registers[i] = riscv_get_register(t, i);
+ int result = riscv_get_register(t, &saved_registers[i], i);
+ if (result != ERROR_OK)
+ return result;
}
}
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index fb459fd..f455921 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -217,7 +217,8 @@ typedef struct {
static int poll_target(struct target *target, bool announce);
static int riscv011_poll(struct target *target);
-static riscv_reg_t get_register(struct target *target, int hartid, int regid);
+static int get_register(struct target *target, riscv_reg_t *value, int hartid,
+ int regid);
/*** Utility functions. ***/
@@ -1180,8 +1181,8 @@ static int update_mstatus_actual(struct target *target)
/* Force reading the register. In that process mstatus_actual will be
* updated. */
- get_register(target, 0, GDB_REGNO_MSTATUS);
- return ERROR_OK;
+ riscv_reg_t mstatus;
+ return get_register(target, &mstatus, 0, GDB_REGNO_MSTATUS);
}
/*** OpenOCD target functions. ***/
@@ -1285,22 +1286,22 @@ static int register_write(struct target *target, unsigned int number,
return ERROR_OK;
}
-static riscv_reg_t get_register(struct target *target, int hartid, int regid)
+static int get_register(struct target *target, riscv_reg_t *value, int hartid,
+ int regid)
{
assert(hartid == 0);
riscv011_info_t *info = get_info(target);
maybe_write_tselect(target);
- riscv_reg_t value = ~0;
if (regid <= GDB_REGNO_XPR31) {
- value = reg_cache_get(target, regid);
+ *value = reg_cache_get(target, regid);
} else if (regid == GDB_REGNO_PC) {
- value = info->dpc;
+ *value = info->dpc;
} else if (regid >= GDB_REGNO_FPR0 && regid <= GDB_REGNO_FPR31) {
int result = update_mstatus_actual(target);
if (result != ERROR_OK)
- return ~0;
+ return result;
unsigned i = 0;
if ((info->mstatus_actual & MSTATUS_FS) == 0) {
info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1);
@@ -1316,17 +1317,19 @@ static riscv_reg_t get_register(struct target *target, int hartid, int regid)
cache_set_jump(target, i++);
if (cache_write(target, 4, true) != ERROR_OK)
- return ~0;
+ return ERROR_FAIL;
} else if (regid == GDB_REGNO_PRIV) {
- value = get_field(info->dcsr, DCSR_PRV);
- } else if (register_read(target, &value, regid) != ERROR_OK) {
- value = ~0;
+ *value = get_field(info->dcsr, DCSR_PRV);
+ } else {
+ int result = register_read(target, value, regid);
+ if (result != ERROR_OK)
+ return result;
}
if (regid == GDB_REGNO_MSTATUS)
target->reg_cache->reg_list[regid].valid = true;
- return value;
+ return ERROR_OK;
}
static int set_register(struct target *target, int hartid, int regid,
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 3d82680..a5b1ee2 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -30,20 +30,21 @@
#define DMI_DATA1 (DMI_DATA0 + 1)
#define DMI_PROGBUF1 (DMI_PROGBUF0 + 1)
-static void riscv013_on_step_or_resume(struct target *target, bool step);
+static int riscv013_on_step_or_resume(struct target *target, bool step);
static int riscv013_step_or_resume_current_hart(struct target *target, bool step);
static void riscv013_clear_abstract_error(struct target *target);
/* Implementations of the functions in riscv_info_t. */
-static riscv_reg_t riscv013_get_register(struct target *target, int hartid, int regid);
+static int riscv013_get_register(struct target *target,
+ riscv_reg_t *value, int hid, int rid);
static int riscv013_set_register(struct target *target, int hartid, int regid, uint64_t value);
static void riscv013_select_current_hart(struct target *target);
static int riscv013_halt_current_hart(struct target *target);
static int riscv013_resume_current_hart(struct target *target);
static int riscv013_step_current_hart(struct target *target);
-static void riscv013_on_halt(struct target *target);
-static void riscv013_on_step(struct target *target);
-static void riscv013_on_resume(struct target *target);
+static int riscv013_on_halt(struct target *target);
+static int riscv013_on_step(struct target *target);
+static int riscv013_on_resume(struct target *target);
static bool riscv013_is_halted(struct target *target);
static enum riscv_halt_reason riscv013_halt_reason(struct target *target);
static int riscv013_write_debug_buffer(struct target *target, unsigned index,
@@ -1855,36 +1856,37 @@ struct target_type riscv013_target = {
};
/*** 0.13-specific implementations of various RISC-V helper functions. ***/
-static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid)
+static int riscv013_get_register(struct target *target,
+ riscv_reg_t *value, int hid, int rid)
{
LOG_DEBUG("reading register %s on hart %d", gdb_regno_name(rid), hid);
riscv_set_current_hartid(target, hid);
- uint64_t out;
riscv013_info_t *info = get_info(target);
+ int result = ERROR_OK;
if (rid <= GDB_REGNO_XPR31) {
- register_read_direct(target, &out, rid);
+ result = register_read_direct(target, value, rid);
} else if (rid == GDB_REGNO_PC) {
- register_read_direct(target, &out, GDB_REGNO_DPC);
- LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, out);
+ result = register_read_direct(target, value, GDB_REGNO_DPC);
+ LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, *value);
} else if (rid == GDB_REGNO_PRIV) {
uint64_t dcsr;
- register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
- buf_set_u64((unsigned char *)&out, 0, 8, get_field(dcsr, CSR_DCSR_PRV));
+ result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
+ buf_set_u64((unsigned char *)value, 0, 8, get_field(dcsr, CSR_DCSR_PRV));
} else {
- int result = register_read_direct(target, &out, rid);
+ result = register_read_direct(target, value, rid);
if (result != ERROR_OK) {
LOG_ERROR("Unable to read register %d", rid);
- out = -1;
+ *value = -1;
}
if (rid == GDB_REGNO_MSTATUS)
- info->mstatus_actual = out;
+ info->mstatus_actual = *value;
}
- return out;
+ return result;
}
static int riscv013_set_register(struct target *target, int hid, int rid, uint64_t value)
@@ -1969,18 +1971,19 @@ static int riscv013_step_current_hart(struct target *target)
return riscv013_step_or_resume_current_hart(target, true);
}
-static void riscv013_on_resume(struct target *target)
+static int riscv013_on_resume(struct target *target)
{
return riscv013_on_step_or_resume(target, false);
}
-static void riscv013_on_step(struct target *target)
+static int riscv013_on_step(struct target *target)
{
return riscv013_on_step_or_resume(target, true);
}
-static void riscv013_on_halt(struct target *target)
+static int riscv013_on_halt(struct target *target)
{
+ return ERROR_OK;
}
static bool riscv013_is_halted(struct target *target)
@@ -1995,7 +1998,11 @@ static bool riscv013_is_halted(struct target *target)
static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
{
- uint64_t dcsr = riscv_get_register(target, GDB_REGNO_DCSR);
+ riscv_reg_t dcsr;
+ int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
+ if (result != ERROR_OK)
+ return RISCV_HALT_UNKNOWN;
+
switch (get_field(dcsr, CSR_DCSR_CAUSE)) {
case CSR_DCSR_CAUSE_SWBP:
case CSR_DCSR_CAUSE_TRIGGER:
@@ -2064,7 +2071,7 @@ int riscv013_dmi_write_u64_bits(struct target *target)
}
/* Helper Functions. */
-static void riscv013_on_step_or_resume(struct target *target, bool step)
+static int riscv013_on_step_or_resume(struct target *target, bool step)
{
struct riscv_program program;
riscv_program_init(&program, target);
@@ -2073,12 +2080,15 @@ static void riscv013_on_step_or_resume(struct target *target, bool step)
LOG_ERROR("Unable to execute fence.i");
/* We want to twiddle some bits in the debug CSR so debugging works. */
- uint64_t dcsr = riscv_get_register(target, GDB_REGNO_DCSR);
+ riscv_reg_t dcsr;
+ int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
+ if (result != ERROR_OK)
+ return result;
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, 1);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, 1);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, 1);
- riscv_set_register(target, GDB_REGNO_DCSR, dcsr);
+ return riscv_set_register(target, GDB_REGNO_DCSR, dcsr);
}
static int riscv013_step_or_resume_current_hart(struct target *target, bool step)
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 10baac5..f8a2739 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -320,8 +320,10 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid,
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1);
- riscv_reg_t tdata1_rb = riscv_get_register_on_hart(target, hartid,
- GDB_REGNO_TDATA1);
+ riscv_reg_t tdata1_rb;
+ if (riscv_get_register_on_hart(target, &tdata1_rb, hartid,
+ GDB_REGNO_TDATA1) != ERROR_OK)
+ return ERROR_FAIL;
LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
if (tdata1 != tdata1_rb) {
@@ -370,7 +372,10 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid,
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1);
- uint64_t tdata1_rb = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TDATA1);
+ uint64_t tdata1_rb;
+ int result = riscv_get_register_on_hart(target, &tdata1_rb, hartid, GDB_REGNO_TDATA1);
+ if (result != ERROR_OK)
+ return result;
LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
if (tdata1 != tdata1_rb) {
@@ -405,8 +410,10 @@ static int add_trigger(struct target *target, struct trigger *trigger)
continue;
if (first_hart < 0)
first_hart = hartid;
- tselect[hartid] = riscv_get_register_on_hart(target, hartid,
- GDB_REGNO_TSELECT);
+ int result = riscv_get_register_on_hart(target, &tselect[hartid],
+ hartid, GDB_REGNO_TSELECT);
+ if (result != ERROR_OK)
+ return result;
}
assert(first_hart >= 0);
@@ -417,10 +424,14 @@ static int add_trigger(struct target *target, struct trigger *trigger)
riscv_set_register_on_hart(target, first_hart, GDB_REGNO_TSELECT, i);
- uint64_t tdata1 = riscv_get_register_on_hart(target, first_hart, GDB_REGNO_TDATA1);
+ uint64_t tdata1;
+ int result = riscv_get_register_on_hart(target, &tdata1, first_hart,
+ GDB_REGNO_TDATA1);
+ if (result != ERROR_OK)
+ return result;
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
- int result = ERROR_OK;
+ result = ERROR_OK;
for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) {
if (!riscv_hart_enabled(target, hartid))
continue;
@@ -533,7 +544,10 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) {
if (!riscv_hart_enabled(target, hartid))
continue;
- riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT);
+ riscv_reg_t tselect;
+ int result = riscv_get_register_on_hart(target, &tselect, hartid, GDB_REGNO_TSELECT);
+ if (result != ERROR_OK)
+ return result;
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i);
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0);
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, tselect);
@@ -1553,17 +1567,20 @@ int riscv_set_register_on_hart(struct target *target, int hartid,
return r->set_register(target, hartid, regid, value);
}
-riscv_reg_t riscv_get_register(struct target *target, enum gdb_regno r)
+int riscv_get_register(struct target *target, riscv_reg_t *value,
+ enum gdb_regno r)
{
- return riscv_get_register_on_hart(target, riscv_current_hartid(target), r);
+ return riscv_get_register_on_hart(target, value,
+ riscv_current_hartid(target), r);
}
-uint64_t riscv_get_register_on_hart(struct target *target, int hartid, enum gdb_regno regid)
+int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
+ int hartid, enum gdb_regno regid)
{
RISCV_INFO(r);
- uint64_t value = r->get_register(target, hartid, regid);
- LOG_DEBUG("[%d] %s: %" PRIx64, hartid, gdb_regno_name(regid), value);
- return value;
+ int result = r->get_register(target, value, hartid, regid);
+ LOG_DEBUG("[%d] %s: %" PRIx64, hartid, gdb_regno_name(regid), *value);
+ return result;
}
bool riscv_is_halted(struct target *target)
@@ -1669,22 +1686,32 @@ int riscv_enumerate_triggers(struct target *target)
if (!riscv_hart_enabled(target, hartid))
continue;
- riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid,
+ riscv_reg_t tselect;
+ int result = riscv_get_register_on_hart(target, &tselect, hartid,
GDB_REGNO_TSELECT);
+ if (result != ERROR_OK)
+ return result;
for (unsigned t = 0; t < RISCV_MAX_TRIGGERS; ++t) {
r->trigger_count[hartid] = t;
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, t);
- uint64_t tselect_rb = riscv_get_register_on_hart(target, hartid,
+ uint64_t tselect_rb;
+ result = riscv_get_register_on_hart(target, &tselect_rb, hartid,
GDB_REGNO_TSELECT);
+ if (result != ERROR_OK)
+ return result;
/* Mask off the top bit, which is used as tdrmode in old
* implementations. */
tselect_rb &= ~(1ULL << (riscv_xlen(target)-1));
if (tselect_rb != t)
break;
- uint64_t tdata1 = riscv_get_register_on_hart(target, hartid,
+ uint64_t tdata1;
+ result = riscv_get_register_on_hart(target, &tdata1, hartid,
GDB_REGNO_TDATA1);
+ if (result != ERROR_OK)
+ return result;
+
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
switch (type) {
case 1:
@@ -1760,7 +1787,10 @@ const char *gdb_regno_name(enum gdb_regno regno)
static int register_get(struct reg *reg)
{
struct target *target = (struct target *) reg->arch_info;
- uint64_t value = riscv_get_register(target, reg->number);
+ uint64_t value;
+ int result = riscv_get_register(target, &value, reg->number);
+ if (result != ERROR_OK)
+ return result;
buf_set_u64(reg->value, 0, reg->size, value);
return ERROR_OK;
}
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index dc3c6f5..5d3a212 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -88,7 +88,8 @@ typedef struct {
/* Helper functions that target the various RISC-V debug spec
* implementations. */
- riscv_reg_t (*get_register)(struct target *, int hartid, int regid);
+ int (*get_register)(struct target *target,
+ riscv_reg_t *value, int hid, int rid);
int (*set_register)(struct target *, int hartid, int regid,
uint64_t value);
void (*select_current_hart)(struct target *);
@@ -96,9 +97,9 @@ typedef struct {
int (*halt_current_hart)(struct target *);
int (*resume_current_hart)(struct target *target);
int (*step_current_hart)(struct target *target);
- void (*on_halt)(struct target *target);
- void (*on_resume)(struct target *target);
- void (*on_step)(struct target *target);
+ int (*on_halt)(struct target *target);
+ int (*on_resume)(struct target *target);
+ int (*on_step)(struct target *target);
enum riscv_halt_reason (*halt_reason)(struct target *target);
int (*write_debug_buffer)(struct target *target, unsigned index,
riscv_insn_t d);
@@ -205,8 +206,10 @@ bool riscv_has_register(struct target *target, int hartid, int regid);
* are zero extended to 64 bits. */
int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v);
int riscv_set_register_on_hart(struct target *target, int hid, enum gdb_regno rid, uint64_t v);
-riscv_reg_t riscv_get_register(struct target *target, enum gdb_regno i);
-riscv_reg_t riscv_get_register_on_hart(struct target *target, int hid, enum gdb_regno rid);
+int riscv_get_register(struct target *target, riscv_reg_t *value,
+ enum gdb_regno r);
+int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
+ int hartid, enum gdb_regno regid);
/* Checks the state of the current hart -- "is_halted" checks the actual
* on-device register. */