Make general CSR reads work.

Change-Id: Ic9b7e065b7303b3707c28c9b7c496cc1c1e91acd
__archive__
Tim Newsome 2017-02-14 12:55:03 -08:00
parent ae4fda2719
commit ceb8dc048d
1 changed files with 22 additions and 36 deletions

View File

@ -1146,6 +1146,7 @@ static int abstract_write_register(struct target *target,
return ERROR_OK; return ERROR_OK;
} }
/** csr is the CSR index between 0 and 4096. */
static int read_csr(struct target *target, uint64_t *value, uint32_t csr) static int read_csr(struct target *target, uint64_t *value, uint32_t csr)
{ {
int result = abstract_read_register(target, csr, xlen(target), value); int result = abstract_read_register(target, csr, xlen(target), value);
@ -1320,6 +1321,15 @@ static int resume(struct target *target, int debug_execution, bool step)
return execute_resume(target, step); return execute_resume(target, step);
} }
static void reg_cache_set(struct target *target, unsigned int number,
uint64_t value)
{
struct reg *r = &target->reg_cache->reg_list[number];
LOG_DEBUG("%s <= 0x%" PRIx64, r->name, value);
r->valid = true;
buf_set_u64(r->value, 0, r->size, value);
}
/** Update register sizes based on xlen. */ /** Update register sizes based on xlen. */
static void update_reg_list(struct target *target) static void update_reg_list(struct target *target)
{ {
@ -1342,6 +1352,8 @@ static void update_reg_list(struct target *target)
} }
r->valid = false; r->valid = false;
} }
reg_cache_set(target, ZERO, 0);
} }
static uint64_t reg_cache_get(struct target *target, unsigned int number) static uint64_t reg_cache_get(struct target *target, unsigned int number)
@ -1356,15 +1368,6 @@ static uint64_t reg_cache_get(struct target *target, unsigned int number)
return value; return value;
} }
static void reg_cache_set(struct target *target, unsigned int number,
uint64_t value)
{
struct reg *r = &target->reg_cache->reg_list[number];
LOG_DEBUG("%s <= 0x%" PRIx64, r->name, value);
r->valid = true;
buf_set_u64(r->value, 0, r->size, value);
}
static int update_mstatus_actual(struct target *target) static int update_mstatus_actual(struct target *target)
{ {
struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS]; struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS];
@ -1387,6 +1390,8 @@ static int register_get(struct reg *reg)
maybe_write_tselect(target); maybe_write_tselect(target);
int result = ERROR_OK;
uint64_t value;
if (reg->number <= REG_XPR31) { if (reg->number <= REG_XPR31) {
buf_set_u64(reg->value, 0, xlen(target), reg_cache_get(target, reg->number)); buf_set_u64(reg->value, 0, xlen(target), reg_cache_get(target, reg->number));
LOG_DEBUG("%s=0x%" PRIx64, reg->name, reg_cache_get(target, reg->number)); LOG_DEBUG("%s=0x%" PRIx64, reg->name, reg_cache_get(target, reg->number));
@ -1397,7 +1402,7 @@ static int register_get(struct reg *reg)
LOG_DEBUG("%s=0x%" PRIx64 " (cached)", reg->name, info->dpc); LOG_DEBUG("%s=0x%" PRIx64 " (cached)", reg->name, info->dpc);
return ERROR_OK; return ERROR_OK;
} else if (reg->number >= REG_FPR0 && reg->number <= REG_FPR31) { } else if (reg->number >= REG_FPR0 && reg->number <= REG_FPR31) {
int result = update_mstatus_actual(target); result = update_mstatus_actual(target);
if (result != ERROR_OK) { if (result != ERROR_OK) {
return result; return result;
} }
@ -1416,9 +1421,7 @@ static int register_get(struct reg *reg)
} }
cache_set_jump(target, i++); cache_set_jump(target, i++);
} else if (reg->number >= REG_CSR0 && reg->number <= REG_CSR4095) { } else if (reg->number >= REG_CSR0 && reg->number <= REG_CSR4095) {
cache_set32(target, 0, csrr(S0, reg->number - REG_CSR0)); result = read_csr(target, &value, reg->number - REG_CSR0);
cache_set_store(target, 1, S0, SLOT0);
cache_set_jump(target, 2);
} else if (reg->number == REG_PRIV) { } else if (reg->number == REG_PRIV) {
buf_set_u64(reg->value, 0, 8, get_field(info->dcsr, DCSR_PRV)); buf_set_u64(reg->value, 0, 8, get_field(info->dcsr, DCSR_PRV));
LOG_DEBUG("%s=%d (cached)", reg->name, LOG_DEBUG("%s=%d (cached)", reg->name,
@ -1429,19 +1432,9 @@ static int register_get(struct reg *reg)
return ERROR_FAIL; return ERROR_FAIL;
} }
if (cache_write(target, 4, true) != ERROR_OK) { if (result != ERROR_OK)
return ERROR_FAIL; return result;
}
uint32_t exception = cache_get32(target, info->dramsize-1);
if (exception) {
LOG_ERROR("Got exception 0x%x when reading register %d", exception,
reg->number);
buf_set_u64(reg->value, 0, xlen(target), ~0);
return ERROR_FAIL;
}
uint64_t value = cache_get(target, SLOT0);
LOG_DEBUG("%s=0x%" PRIx64, reg->name, value); LOG_DEBUG("%s=0x%" PRIx64, reg->name, value);
buf_set_u64(reg->value, 0, xlen(target), value); buf_set_u64(reg->value, 0, xlen(target), value);
@ -1548,15 +1541,7 @@ static int halt(struct target *target)
LOG_DEBUG("riscv_halt()"); LOG_DEBUG("riscv_halt()");
select_dmi(target); select_dmi(target);
cache_set32(target, 0, csrsi(CSR_DCSR, DCSR_HALT)); dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_HALTREQ | DMI_DMCONTROL_DMACTIVE);
cache_set32(target, 1, csrr(S0, CSR_MHARTID));
cache_set32(target, 2, sw(S0, ZERO, SETHALTNOT));
cache_set_jump(target, 3);
if (cache_write(target, 4, true) != ERROR_OK) {
LOG_ERROR("cache_write() failed.");
return ERROR_FAIL;
}
return ERROR_OK; return ERROR_OK;
} }
@ -1957,8 +1942,9 @@ static int examine(struct target *target)
} }
// Reset the Debug Module. // Reset the Debug Module.
dmi_write(target, DMI_DMCONTROL, 0); dmi_write(target, DMI_DMCONTROL, dmcontrol & DMI_DMCONTROL_HALTREQ);
dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE); dmi_write(target, DMI_DMCONTROL, (dmcontrol & DMI_DMCONTROL_HALTREQ) |
DMI_DMCONTROL_DMACTIVE);
dmcontrol = dmi_read(target, DMI_DMCONTROL); dmcontrol = dmi_read(target, DMI_DMCONTROL);
LOG_DEBUG("dmcontrol: 0x%08x", dmcontrol); LOG_DEBUG("dmcontrol: 0x%08x", dmcontrol);