Track misa per-hart even in -rtos mode

This works around some side effects of the -rtos hack, namely that we
were unable to set hardware breakpoints on harts whose misa differed
from the first one. There may be other bugs like this one lurking
elsewhere. The only proper solution is for gdb to have a better user
interface when talking to a server that exposes multiple targets, but
that's a very big project.

This fixes #194.

Change-Id: I81aedddeaa922d220e936730e9c731545953ae21
riscv-compliance-dev
Tim Newsome 2018-01-26 15:10:54 -08:00 committed by Wesley W. Terpstra
parent ae571d78e9
commit 6030644a9d
4 changed files with 36 additions and 28 deletions

View File

@ -1572,11 +1572,11 @@ static int examine(struct target *target)
}
LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target));
if (read_csr(target, &r->misa, CSR_MISA) != ERROR_OK) {
if (read_csr(target, &r->misa[0], CSR_MISA) != ERROR_OK) {
const unsigned old_csr_misa = 0xf10;
LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA,
old_csr_misa);
if (read_csr(target, &r->misa, old_csr_misa) != ERROR_OK) {
if (read_csr(target, &r->misa[0], old_csr_misa) != ERROR_OK) {
/* Maybe this is an old core that still has $misa at the old
* address. */
LOG_ERROR("Failed to read misa at 0x%x.", old_csr_misa);
@ -1598,7 +1598,7 @@ static int examine(struct target *target)
for (size_t i = 0; i < 32; ++i)
reg_cache_set(target, i, -1);
LOG_INFO("Examined RISCV core; XLEN=%d, misa=0x%" PRIx64,
riscv_xlen(target), r->misa);
riscv_xlen(target), r->misa[0]);
return ERROR_OK;
}

View File

@ -1072,7 +1072,7 @@ static int register_write_direct(struct target *target, unsigned number,
return ERROR_FAIL;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
riscv_supports_extension(target, 'D') &&
riscv_supports_extension(target, riscv_current_hartid(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. */
@ -1094,7 +1094,7 @@ static int register_write_direct(struct target *target, unsigned number,
return ERROR_FAIL;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
if (riscv_supports_extension(target, 'D'))
if (riscv_supports_extension(target, riscv_current_hartid(target), 'D'))
riscv_program_insert(&program, fmv_d_x(number - GDB_REGNO_FPR0, S0));
else
riscv_program_insert(&program, fmv_w_x(number - GDB_REGNO_FPR0, S0));
@ -1150,7 +1150,8 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
set_field(mstatus, MSTATUS_FS, 1)) != ERROR_OK)
return ERROR_FAIL;
if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) {
if (riscv_supports_extension(target, riscv_current_hartid(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. */
riscv_program_insert(&program, fsd(number - GDB_REGNO_FPR0, S0,
@ -1163,7 +1164,8 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
if (register_write_direct(target, GDB_REGNO_S0,
scratch.hart_address) != ERROR_OK)
return ERROR_FAIL;
} else if (riscv_supports_extension(target, 'D')) {
} else if (riscv_supports_extension(target,
riscv_current_hartid(target), 'D')) {
riscv_program_insert(&program, fmv_x_d(S0, number - GDB_REGNO_FPR0));
} else {
riscv_program_insert(&program, fmv_x_w(S0, number - GDB_REGNO_FPR0));
@ -1378,7 +1380,7 @@ static int examine(struct target *target)
else
r->xlen[i] = 32;
if (register_read_direct(target, &r->misa, GDB_REGNO_MISA)) {
if (register_read_direct(target, &r->misa[i], GDB_REGNO_MISA)) {
LOG_ERROR("Fatal: Failed to read MISA from hart %d.", i);
return ERROR_FAIL;
}
@ -1390,7 +1392,7 @@ static int examine(struct target *target)
/* Display this as early as possible to help people who are using
* really slow simulators. */
LOG_DEBUG(" hart %d: XLEN=%d, misa=0x%" PRIx64, i, r->xlen[i],
r->misa);
r->misa[i]);
}
LOG_DEBUG("Enumerated %d harts", r->hart_count);
@ -1420,8 +1422,8 @@ static int examine(struct target *target)
riscv_count_harts(target));
for (int i = 0; i < riscv_count_harts(target); ++i) {
if (riscv_hart_enabled(target, i)) {
LOG_INFO(" hart %d: XLEN=%d, %d triggers", i, r->xlen[i],
r->trigger_count[i]);
LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64 ", %d triggers", i,
r->xlen[i], r->misa[i], r->trigger_count[i]);
} else {
LOG_INFO(" hart %d: currently disabled", i);
}

View File

@ -313,9 +313,12 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid,
tdata1 = set_field(tdata1, bpcontrol_r, trigger->read);
tdata1 = set_field(tdata1, bpcontrol_w, trigger->write);
tdata1 = set_field(tdata1, bpcontrol_x, trigger->execute);
tdata1 = set_field(tdata1, bpcontrol_u, !!(r->misa & (1 << ('U' - 'A'))));
tdata1 = set_field(tdata1, bpcontrol_s, !!(r->misa & (1 << ('S' - 'A'))));
tdata1 = set_field(tdata1, bpcontrol_h, !!(r->misa & (1 << ('H' - 'A'))));
tdata1 = set_field(tdata1, bpcontrol_u,
!!(r->misa[hartid] & (1 << ('U' - 'A'))));
tdata1 = set_field(tdata1, bpcontrol_s,
!!(r->misa[hartid] & (1 << ('S' - 'A'))));
tdata1 = set_field(tdata1, bpcontrol_h,
!!(r->misa[hartid] & (1 << ('H' - 'A'))));
tdata1 |= bpcontrol_m;
tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */
tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */
@ -358,11 +361,11 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid,
MCONTROL_ACTION_DEBUG_MODE);
tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL);
tdata1 |= MCONTROL_M;
if (r->misa & (1 << ('H' - 'A')))
if (r->misa[hartid] & (1 << ('H' - 'A')))
tdata1 |= MCONTROL_H;
if (r->misa & (1 << ('S' - 'A')))
if (r->misa[hartid] & (1 << ('S' - 'A')))
tdata1 |= MCONTROL_S;
if (r->misa & (1 << ('U' - 'A')))
if (r->misa[hartid] & (1 << ('U' - 'A')))
tdata1 |= MCONTROL_U;
if (trigger->execute)
@ -1648,7 +1651,7 @@ int riscv_step_rtos_hart(struct target *target)
return ERROR_OK;
}
bool riscv_supports_extension(struct target *target, char letter)
bool riscv_supports_extension(struct target *target, int hartid, char letter)
{
RISCV_INFO(r);
unsigned num;
@ -1658,7 +1661,7 @@ bool riscv_supports_extension(struct target *target, char letter)
num = letter - 'A';
else
return false;
return r->misa & (1 << num);
return r->misa[hartid] & (1 << num);
}
int riscv_xlen(const struct target *target)
@ -2192,10 +2195,12 @@ int riscv_init_registers(struct target *target)
r->feature = &feature_cpu;
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
r->caller_save = true;
if (riscv_supports_extension(target, 'D')) {
if (riscv_supports_extension(target, riscv_current_hartid(target),
'D')) {
r->reg_data_type = &type_ieee_double;
r->size = 64;
} else if (riscv_supports_extension(target, 'F')) {
} else if (riscv_supports_extension(target,
riscv_current_hartid(target), 'F')) {
r->reg_data_type = &type_ieee_single;
r->size = 32;
} else {
@ -2326,7 +2331,8 @@ int riscv_init_registers(struct target *target)
case CSR_FFLAGS:
case CSR_FRM:
case CSR_FCSR:
r->exist = riscv_supports_extension(target, 'F');
r->exist = riscv_supports_extension(target,
riscv_current_hartid(target), 'F');
r->group = "float";
r->feature = &feature_fpu;
break;
@ -2340,15 +2346,16 @@ int riscv_init_registers(struct target *target)
case CSR_SCAUSE:
case CSR_STVAL:
case CSR_SATP:
r->exist = riscv_supports_extension(target, 'S');
r->exist = riscv_supports_extension(target,
riscv_current_hartid(target), 'S');
break;
case CSR_MEDELEG:
case CSR_MIDELEG:
/* "In systems with only M-mode, or with both M-mode and
* U-mode but without U-mode trap support, the medeleg and
* mideleg registers should not exist." */
r->exist = riscv_supports_extension(target, 'S') ||
riscv_supports_extension(target, 'N');
r->exist = riscv_supports_extension(target, riscv_current_hartid(target), 'S') ||
riscv_supports_extension(target, riscv_current_hartid(target), 'N');
break;
}

View File

@ -37,8 +37,6 @@ enum riscv_halt_reason {
typedef struct {
unsigned dtm_version;
riscv_reg_t misa;
struct command_context *cmd_ctx;
void *version_specific;
@ -68,6 +66,7 @@ typedef struct {
/* It's possible that each core has a different supported ISA set. */
int xlen[RISCV_MAX_HARTS];
riscv_reg_t misa[RISCV_MAX_HARTS];
/* The number of triggers per hart. */
unsigned trigger_count[RISCV_MAX_HARTS];
@ -183,7 +182,7 @@ int riscv_resume_one_hart(struct target *target, int hartid);
* then the only hart. */
int riscv_step_rtos_hart(struct target *target);
bool riscv_supports_extension(struct target *target, char letter);
bool riscv_supports_extension(struct target *target, int hartid, char letter);
/* Returns XLEN for the given (or current) hart. */
int riscv_xlen(const struct target *target);