Merge pull request #181 from riscv/propagate_errors

Propagate register read errors
This commit is contained in:
Tim Newsome 2018-01-10 15:16:19 -08:00 committed by GitHub
commit 160b794274
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 63 deletions

View File

@ -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'};

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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,
@ -1002,8 +1003,15 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
/* Write program to move data into s0. */
uint64_t mstatus;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
/* TODO: Possibly set F in mstatus. */
if (register_read_direct(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
return ERROR_FAIL;
if ((mstatus & MSTATUS_FS) == 0)
if (register_write_direct(target, GDB_REGNO_MSTATUS,
set_field(mstatus, MSTATUS_FS, 1)) != ERROR_OK)
return ERROR_FAIL;
if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) {
/* There are no instructions to move all the bits from a
* register, so we need to use some scratch RAM. */
@ -1041,6 +1049,11 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
return ERROR_FAIL;
}
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
(mstatus & MSTATUS_FS) == 0)
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus) != ERROR_OK)
return ERROR_FAIL;
/* Restore S0. */
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
return ERROR_FAIL;
@ -1855,36 +1868,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 +1983,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 +2010,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 +2083,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 +2092,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)

View File

@ -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;
}

View File

@ -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. */