Keep around cmderr for callers to inspect.
Use this to only change abstract register access behavior when cmderr explicitly says the requested operation is unsupported.print_port
parent
856f70fe44
commit
09bf86e31a
|
@ -192,6 +192,11 @@ typedef struct {
|
||||||
bool abstract_write_csr_supported;
|
bool abstract_write_csr_supported;
|
||||||
bool abstract_read_fpr_supported;
|
bool abstract_read_fpr_supported;
|
||||||
bool abstract_write_fpr_supported;
|
bool abstract_write_fpr_supported;
|
||||||
|
|
||||||
|
// When a function returns some error due to a failure indicated by the
|
||||||
|
// target in cmderr, the caller can look here to see what that error was.
|
||||||
|
// (Compare with errno.)
|
||||||
|
unsigned cmderr;
|
||||||
} riscv013_info_t;
|
} riscv013_info_t;
|
||||||
|
|
||||||
static void decode_dmi(char *text, unsigned address, unsigned data)
|
static void decode_dmi(char *text, unsigned address, unsigned data)
|
||||||
|
@ -546,6 +551,7 @@ uint32_t abstract_register_size(unsigned width)
|
||||||
|
|
||||||
static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
||||||
{
|
{
|
||||||
|
RISCV013_INFO(info);
|
||||||
time_t start = time(NULL);
|
time_t start = time(NULL);
|
||||||
while (1) {
|
while (1) {
|
||||||
*abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
*abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
|
@ -555,7 +561,8 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
|
if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
|
||||||
if (get_field(*abstractcs, DMI_ABSTRACTCS_CMDERR) != CMDERR_NONE) {
|
info->cmderr = get_field(*abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||||
|
if (info->cmderr != CMDERR_NONE) {
|
||||||
const char *errors[8] = {
|
const char *errors[8] = {
|
||||||
"none",
|
"none",
|
||||||
"busy",
|
"busy",
|
||||||
|
@ -567,8 +574,7 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
||||||
"other" };
|
"other" };
|
||||||
|
|
||||||
LOG_ERROR("Abstract command ended in error '%s' (abstractcs=0x%x)",
|
LOG_ERROR("Abstract command ended in error '%s' (abstractcs=0x%x)",
|
||||||
errors[get_field(*abstractcs, DMI_ABSTRACTCS_CMDERR)],
|
errors[info->cmderr], *abstractcs);
|
||||||
*abstractcs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR("Timed out waiting for busy to go low. (abstractcs=0x%x)",
|
LOG_ERROR("Timed out waiting for busy to go low. (abstractcs=0x%x)",
|
||||||
|
@ -580,6 +586,7 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
||||||
|
|
||||||
static int execute_abstract_command(struct target *target, uint32_t command)
|
static int execute_abstract_command(struct target *target, uint32_t command)
|
||||||
{
|
{
|
||||||
|
RISCV013_INFO(info);
|
||||||
LOG_DEBUG("command=0x%x", command);
|
LOG_DEBUG("command=0x%x", command);
|
||||||
dmi_write(target, DMI_COMMAND, command);
|
dmi_write(target, DMI_COMMAND, command);
|
||||||
|
|
||||||
|
@ -589,12 +596,12 @@ static int execute_abstract_command(struct target *target, uint32_t command)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t cs = dmi_read(target, DMI_ABSTRACTCS);
|
uint32_t cs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
unsigned cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR);
|
info->cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR);
|
||||||
if (cmderr != 0) {
|
if (info->cmderr != 0) {
|
||||||
LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs);
|
LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs);
|
||||||
// Clear the error.
|
// Clear the error.
|
||||||
dmi_write(target, DMI_ABSTRACTCS, set_field(0, DMI_ABSTRACTCS_CMDERR,
|
dmi_write(target, DMI_ABSTRACTCS, set_field(0, DMI_ABSTRACTCS_CMDERR,
|
||||||
cmderr));
|
info->cmderr));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,6 +682,7 @@ static int register_read_abstract(struct target *target, uint64_t *value,
|
||||||
|
|
||||||
int result = execute_abstract_command(target, command);
|
int result = execute_abstract_command(target, command);
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK) {
|
||||||
|
if (r->cmderr == CMDERR_NOT_SUPPORTED) {
|
||||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||||
r->abstract_read_fpr_supported = false;
|
r->abstract_read_fpr_supported = false;
|
||||||
LOG_INFO("Disabling abstract command reads from FPRs.");
|
LOG_INFO("Disabling abstract command reads from FPRs.");
|
||||||
|
@ -682,6 +690,7 @@ static int register_read_abstract(struct target *target, uint64_t *value,
|
||||||
r->abstract_read_csr_supported = false;
|
r->abstract_read_csr_supported = false;
|
||||||
LOG_INFO("Disabling abstract command reads from CSRs.");
|
LOG_INFO("Disabling abstract command reads from CSRs.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +702,7 @@ static int register_read_abstract(struct target *target, uint64_t *value,
|
||||||
static int register_write_abstract(struct target *target, uint32_t number,
|
static int register_write_abstract(struct target *target, uint32_t number,
|
||||||
uint64_t value, unsigned size)
|
uint64_t value, unsigned size)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(r);
|
RISCV013_INFO(info);
|
||||||
|
|
||||||
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0);
|
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0);
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
@ -715,12 +724,12 @@ static int register_write_abstract(struct target *target, uint32_t number,
|
||||||
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
||||||
0x1000 + number - GDB_REGNO_XPR0);
|
0x1000 + number - GDB_REGNO_XPR0);
|
||||||
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||||
if (!r->abstract_read_fpr_supported)
|
if (!info->abstract_read_fpr_supported)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
||||||
0x1020 + number - GDB_REGNO_FPR0);
|
0x1020 + number - GDB_REGNO_FPR0);
|
||||||
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||||
if (!r->abstract_read_csr_supported)
|
if (!info->abstract_read_csr_supported)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
||||||
number - GDB_REGNO_CSR0);
|
number - GDB_REGNO_CSR0);
|
||||||
|
@ -734,13 +743,15 @@ static int register_write_abstract(struct target *target, uint32_t number,
|
||||||
|
|
||||||
int result = execute_abstract_command(target, command);
|
int result = execute_abstract_command(target, command);
|
||||||
if (result != ERROR_OK) {
|
if (result != ERROR_OK) {
|
||||||
|
if (info->cmderr == CMDERR_NOT_SUPPORTED) {
|
||||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||||
r->abstract_write_fpr_supported = false;
|
info->abstract_write_fpr_supported = false;
|
||||||
LOG_INFO("Disabling abstract command writes to FPRs.");
|
LOG_INFO("Disabling abstract command writes to FPRs.");
|
||||||
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||||
r->abstract_write_csr_supported = false;
|
info->abstract_write_csr_supported = false;
|
||||||
LOG_INFO("Disabling abstract command writes to CSRs.");
|
LOG_INFO("Disabling abstract command writes to CSRs.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1690,7 +1701,8 @@ static int read_memory(struct target *target, target_addr_t address,
|
||||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||||
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
switch (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)) {
|
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||||
|
switch (info->cmderr) {
|
||||||
case CMDERR_NONE:
|
case CMDERR_NONE:
|
||||||
LOG_DEBUG("successful (partial?) memory write");
|
LOG_DEBUG("successful (partial?) memory write");
|
||||||
break;
|
break;
|
||||||
|
@ -1874,7 +1886,8 @@ static int write_memory(struct target *target, target_addr_t address,
|
||||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||||
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
switch (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)) {
|
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||||
|
switch (info->cmderr) {
|
||||||
case CMDERR_NONE:
|
case CMDERR_NONE:
|
||||||
LOG_DEBUG("successful (partial?) memory write");
|
LOG_DEBUG("successful (partial?) memory write");
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue