Clear dmode triggers when we first halt the target
This helps repeated runs of the testsuite pass, and is probably a good idea in general. Change-Id: I89ed167968f8b8817c66f1718f374d0c502780c7
This commit is contained in:
parent
78fe0b56db
commit
4dbc9962d3
|
@ -170,6 +170,8 @@ typedef struct {
|
||||||
// unique_id of the breakpoint/watchpoint that is using it.
|
// unique_id of the breakpoint/watchpoint that is using it.
|
||||||
int trigger_unique_id[MAX_HWBPS];
|
int trigger_unique_id[MAX_HWBPS];
|
||||||
|
|
||||||
|
unsigned int trigger_count;
|
||||||
|
|
||||||
// Number of run-test/idle cycles the target requests we do after each dbus
|
// Number of run-test/idle cycles the target requests we do after each dbus
|
||||||
// access.
|
// access.
|
||||||
unsigned int dtmcontrol_idle;
|
unsigned int dtmcontrol_idle;
|
||||||
|
@ -189,6 +191,7 @@ typedef struct {
|
||||||
uint64_t gpr_cache[32];
|
uint64_t gpr_cache[32];
|
||||||
|
|
||||||
bool need_strict_step;
|
bool need_strict_step;
|
||||||
|
bool never_halted;
|
||||||
} riscv_info_t;
|
} riscv_info_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -1017,12 +1020,14 @@ static int read_csr(struct target *target, uint64_t *value, uint32_t csr)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
*value = cache_get(target, SLOT0);
|
*value = cache_get(target, SLOT0);
|
||||||
|
LOG_DEBUG("csr 0x%x = 0x%" PRIx64, csr, *value);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_csr(struct target *target, uint32_t csr, uint64_t value)
|
static int write_csr(struct target *target, uint32_t csr, uint64_t value)
|
||||||
{
|
{
|
||||||
|
LOG_DEBUG("csr 0x%x <- 0x%" PRIx64, csr, value);
|
||||||
cache_set_load(target, 0, S0, SLOT0);
|
cache_set_load(target, 0, S0, SLOT0);
|
||||||
cache_set32(target, 1, csrw(S0, csr));
|
cache_set32(target, 1, csrw(S0, csr));
|
||||||
cache_set_jump(target, 2);
|
cache_set_jump(target, 2);
|
||||||
|
@ -1404,23 +1409,13 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
||||||
|
|
||||||
maybe_read_tselect(target);
|
maybe_read_tselect(target);
|
||||||
|
|
||||||
int i;
|
unsigned int i;
|
||||||
for (i = 0; i < MAX_HWBPS; i++) {
|
for (i = 0; i < info->trigger_count; i++) {
|
||||||
if (info->trigger_unique_id[i] != -1) {
|
if (info->trigger_unique_id[i] != -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t tselect = i;
|
write_csr(target, CSR_TSELECT, i);
|
||||||
write_csr(target, CSR_TSELECT, tselect);
|
|
||||||
uint64_t tselect_rb;
|
|
||||||
read_csr(target, &tselect_rb, CSR_TSELECT);
|
|
||||||
if (tselect_rb != tselect) {
|
|
||||||
// We've run out of breakpoints.
|
|
||||||
LOG_ERROR("Couldn't find an available hardware trigger. "
|
|
||||||
"(0x%" PRIx64 " != 0x%" PRIx64 ")", tselect,
|
|
||||||
tselect_rb);
|
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t tdata1;
|
uint64_t tdata1;
|
||||||
read_csr(target, &tdata1, CSR_TDATA1);
|
read_csr(target, &tdata1, CSR_TDATA1);
|
||||||
|
@ -1476,7 +1471,7 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
||||||
info->trigger_unique_id[i] = trigger->unique_id;
|
info->trigger_unique_id[i] = trigger->unique_id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i >= MAX_HWBPS) {
|
if (i >= info->trigger_count) {
|
||||||
LOG_ERROR("Couldn't find an available hardware trigger.");
|
LOG_ERROR("Couldn't find an available hardware trigger.");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
@ -1490,13 +1485,13 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
|
||||||
|
|
||||||
maybe_read_tselect(target);
|
maybe_read_tselect(target);
|
||||||
|
|
||||||
int i;
|
unsigned int i;
|
||||||
for (i = 0; i < MAX_HWBPS; i++) {
|
for (i = 0; i < info->trigger_count; i++) {
|
||||||
if (info->trigger_unique_id[i] == trigger->unique_id) {
|
if (info->trigger_unique_id[i] == trigger->unique_id) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i >= MAX_HWBPS) {
|
if (i >= info->trigger_count) {
|
||||||
LOG_ERROR("Couldn't find the hardware resources used by hardware "
|
LOG_ERROR("Couldn't find the hardware resources used by hardware "
|
||||||
"trigger.");
|
"trigger.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -1800,13 +1795,15 @@ static int riscv_examine(struct target *target)
|
||||||
// Update register list to match discovered XLEN.
|
// Update register list to match discovered XLEN.
|
||||||
update_reg_list(target);
|
update_reg_list(target);
|
||||||
|
|
||||||
target_set_examined(target);
|
|
||||||
|
|
||||||
if (read_csr(target, &info->misa, CSR_MISA) != ERROR_OK) {
|
if (read_csr(target, &info->misa, CSR_MISA) != ERROR_OK) {
|
||||||
LOG_ERROR("Failed to read misa.");
|
LOG_ERROR("Failed to read misa.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info->never_halted = true;
|
||||||
|
|
||||||
|
target_set_examined(target);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2001,6 +1998,32 @@ static int handle_halt(struct target *target, bool announce)
|
||||||
cause, info->dcsr);
|
cause, info->dcsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->never_halted) {
|
||||||
|
info->never_halted = false;
|
||||||
|
|
||||||
|
// Disable any hardware triggers that have dmode set. We can't have set
|
||||||
|
// them ourselves. Maybe they're left over from some killed debug
|
||||||
|
// session.
|
||||||
|
// Count the number of triggers while we're at it.
|
||||||
|
|
||||||
|
int result = maybe_read_tselect(target);
|
||||||
|
if (result != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
for (info->trigger_count = 0; info->trigger_count < MAX_HWBPS; info->trigger_count++) {
|
||||||
|
write_csr(target, CSR_TSELECT, info->trigger_count);
|
||||||
|
uint64_t tselect_rb;
|
||||||
|
read_csr(target, &tselect_rb, CSR_TSELECT);
|
||||||
|
if (info->trigger_count != tselect_rb)
|
||||||
|
break;
|
||||||
|
uint64_t tdata1;
|
||||||
|
read_csr(target, &tdata1, CSR_TDATA1);
|
||||||
|
if ((tdata1 & MCONTROL_DMODE(info->xlen)) &&
|
||||||
|
(tdata1 & (MCONTROL_EXECUTE | MCONTROL_STORE | MCONTROL_LOAD))) {
|
||||||
|
write_csr(target, CSR_TDATA1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (announce) {
|
if (announce) {
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue