diff options
author | Tim Newsome <tim@sifive.com> | 2017-12-29 14:35:49 -0800 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2018-01-08 11:53:02 -0800 |
commit | fd506fa839892cddf8aab06192f4259fba81037c (patch) | |
tree | 932ef064497895daf4a475afb0fef828eb6a3eea /src | |
parent | 0e3869cbf6c5b0ff517f5ce13b69681fc34c32b5 (diff) | |
download | riscv-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.c | 7 | ||||
-rw-r--r-- | src/target/riscv/program.c | 4 | ||||
-rw-r--r-- | src/target/riscv/riscv-011.c | 29 | ||||
-rw-r--r-- | src/target/riscv/riscv-013.c | 56 | ||||
-rw-r--r-- | src/target/riscv/riscv.c | 66 | ||||
-rw-r--r-- | src/target/riscv/riscv.h | 15 |
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, ®_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. */ |