Merge branch 'riscv_timeout_commands' into riscv-compliance
This commit is contained in:
commit
6200d9a180
|
@ -910,7 +910,6 @@ static int init_target(struct command_context *cmd_ctx,
|
|||
generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits;
|
||||
generic_info->reset_current_hart = &riscv013_reset_current_hart;
|
||||
generic_info->test_compliance = &riscv013_test_compliance;
|
||||
|
||||
generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
|
||||
if (!generic_info->version_specific)
|
||||
return ERROR_FAIL;
|
||||
|
@ -1355,8 +1354,10 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
riscv_addr_t fin_addr = address + (count * size);
|
||||
riscv_addr_t prev_addr = ((riscv_addr_t) address) - size;
|
||||
bool first = true;
|
||||
LOG_DEBUG("writing until final address 0x%" PRIx64, fin_addr);
|
||||
while (count > 1 && (cur_addr = riscv_read_debug_buffer_x(target, d_addr)) < fin_addr) {
|
||||
bool this_is_last_read = false;
|
||||
LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr);
|
||||
while (count > 1 && !this_is_last_read) {
|
||||
cur_addr = riscv_read_debug_buffer_x(target, d_addr);
|
||||
LOG_DEBUG("transferring burst starting at address 0x%" TARGET_PRIxADDR
|
||||
" (previous burst was 0x%" TARGET_PRIxADDR ")", cur_addr,
|
||||
prev_addr);
|
||||
|
@ -1373,11 +1374,22 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
size_t reads = 0;
|
||||
size_t rereads = reads;
|
||||
for (riscv_addr_t i = start; i < count; ++i) {
|
||||
size_t index =
|
||||
riscv_batch_add_dmi_read(
|
||||
batch,
|
||||
riscv013_debug_buffer_register(target, r_data));
|
||||
assert(index == reads);
|
||||
if (i == count - 1) {
|
||||
// don't do actual read in this batch,
|
||||
// we will do it later after we disable autoexec
|
||||
//
|
||||
// this is done to avoid reading more memory than requested
|
||||
// which in some special cases(like reading stack located
|
||||
// at the very top of RAM) may cause an exception
|
||||
this_is_last_read = true;
|
||||
} else {
|
||||
size_t const index =
|
||||
riscv_batch_add_dmi_read(
|
||||
batch,
|
||||
riscv013_debug_buffer_register(target, r_data));
|
||||
assert(index == reads);
|
||||
}
|
||||
|
||||
reads++;
|
||||
if (riscv_batch_full(batch))
|
||||
break;
|
||||
|
@ -1385,13 +1397,54 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
|
||||
riscv_batch_run(batch);
|
||||
|
||||
// Note that if the scan resulted in a Busy DMI response, it
|
||||
// is this read to abstractcs that will cause the dmi_busy_delay
|
||||
// to be incremented if necessary. The loop condition above
|
||||
// catches the case where no writes went through at all.
|
||||
|
||||
bool retry_batch_transaction = false;
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||
switch (info->cmderr) {
|
||||
case CMDERR_NONE:
|
||||
LOG_DEBUG("successful (partial?) memory write");
|
||||
break;
|
||||
case CMDERR_BUSY:
|
||||
LOG_DEBUG("memory write resulted in busy response");
|
||||
riscv013_clear_abstract_error(target);
|
||||
increase_ac_busy_delay(target);
|
||||
retry_batch_transaction = true;
|
||||
riscv_batch_free(batch);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
|
||||
riscv013_set_autoexec(target, d_data, 0);
|
||||
riscv_set_register(target, GDB_REGNO_S0, s0);
|
||||
riscv_set_register(target, GDB_REGNO_S1, s1);
|
||||
riscv013_clear_abstract_error(target);
|
||||
riscv_batch_free(batch);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (retry_batch_transaction) continue;
|
||||
|
||||
for (size_t i = start; i < start + reads; ++i) {
|
||||
riscv_addr_t offset = size*i;
|
||||
riscv_addr_t t_addr = address + offset;
|
||||
uint8_t *t_buffer = buffer + offset;
|
||||
|
||||
uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads);
|
||||
value = get_field(dmi_out, DTM_DMI_DATA);
|
||||
if (this_is_last_read && i == start + reads - 1) {
|
||||
riscv013_set_autoexec(target, d_data, 0);
|
||||
|
||||
// access debug buffer without executing a program - this address logic was taken from program.c
|
||||
int const off = (r_data - riscv_debug_buffer_addr(program.target)) / sizeof(program.debug_buffer[0]);
|
||||
value = riscv_read_debug_buffer(target, off);
|
||||
} else {
|
||||
uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads);
|
||||
value = get_field(dmi_out, DTM_DMI_DATA);
|
||||
}
|
||||
|
||||
rereads++;
|
||||
|
||||
switch (size) {
|
||||
|
@ -1415,35 +1468,7 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
|
||||
LOG_DEBUG("M[0x%08lx] reads 0x%08lx", (long)t_addr, (long)value);
|
||||
}
|
||||
|
||||
riscv_batch_free(batch);
|
||||
|
||||
// Note that if the scan resulted in a Busy DMI response, it
|
||||
// is this read to abstractcs that will cause the dmi_busy_delay
|
||||
// to be incremented if necessary. The loop condition above
|
||||
// catches the case where no writes went through at all.
|
||||
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||
switch (info->cmderr) {
|
||||
case CMDERR_NONE:
|
||||
LOG_DEBUG("successful (partial?) memory write");
|
||||
break;
|
||||
case CMDERR_BUSY:
|
||||
LOG_DEBUG("memory write resulted in busy response");
|
||||
riscv013_clear_abstract_error(target);
|
||||
increase_ac_busy_delay(target);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("error when writing memory, abstractcs=0x%08lx", (long)abstractcs);
|
||||
riscv013_set_autoexec(target, d_data, 0);
|
||||
riscv_set_register(target, GDB_REGNO_S0, s0);
|
||||
riscv_set_register(target, GDB_REGNO_S1, s1);
|
||||
riscv013_clear_abstract_error(target);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
riscv013_set_autoexec(target, d_data, 0);
|
||||
|
|
|
@ -1137,8 +1137,96 @@ int riscv_openocd_deassert_reset(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
// Declared below
|
||||
const struct command_registration riscv_command_handlers[];
|
||||
/* Command Handlers */
|
||||
COMMAND_HANDLER(riscv_set_command_timeout_sec) {
|
||||
|
||||
if (CMD_ARGC != 1) {
|
||||
LOG_ERROR("Command takes exactly 1 parameter");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
int timeout = atoi(CMD_ARGV[0]);
|
||||
if (timeout <= 0){
|
||||
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
riscv_command_timeout_sec = timeout;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_set_reset_timeout_sec) {
|
||||
|
||||
if (CMD_ARGC != 1) {
|
||||
LOG_ERROR("Command takes exactly 1 parameter");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
int timeout = atoi(CMD_ARGV[0]);
|
||||
if (timeout <= 0){
|
||||
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
riscv_reset_timeout_sec = timeout;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_test_compliance) {
|
||||
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
|
||||
RISCV_INFO(r);
|
||||
|
||||
if (CMD_ARGC > 0) {
|
||||
LOG_ERROR("Command does not take any parameters.");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
if (r->test_compliance) {
|
||||
return r->test_compliance(target);
|
||||
} else {
|
||||
LOG_ERROR("This target does not support this command (may implement an older version of the spec).");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static const struct command_registration riscv_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "test_compliance",
|
||||
.handler = riscv_test_compliance,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "riscv test_compliance",
|
||||
.help = "Runs a basic compliance test suite against the RISC-V Debug Spec."
|
||||
},
|
||||
{
|
||||
.name = "set_command_timeout_sec",
|
||||
.handler = riscv_set_command_timeout_sec,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "riscv set_command_timeout_sec [sec]",
|
||||
.help = "Set the wall-clock timeout (in seconds) for individual commands"
|
||||
},
|
||||
{
|
||||
.name = "set_reset_timeout_sec",
|
||||
.handler = riscv_set_reset_timeout_sec,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "riscv set_reset_timeout_sec [sec]",
|
||||
.help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
const struct command_registration riscv_command_handlers[] = {
|
||||
{
|
||||
.name = "riscv",
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "RISC-V Command Group",
|
||||
.usage = "",
|
||||
.chain = riscv_exec_command_handlers
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
struct target_type riscv_target =
|
||||
{
|
||||
|
@ -1586,7 +1674,6 @@ int riscv_enumerate_triggers(struct target *target)
|
|||
tselect_rb &= ~(1ULL << (riscv_xlen(target)-1));
|
||||
if (tselect_rb != t)
|
||||
break;
|
||||
|
||||
uint64_t tdata1 = riscv_get_register_on_hart(target, hartid,
|
||||
GDB_REGNO_TDATA1);
|
||||
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
|
||||
|
@ -1612,98 +1699,6 @@ int riscv_enumerate_triggers(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* Command Handlers */
|
||||
|
||||
COMMAND_HANDLER(riscv_test_compliance) {
|
||||
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
|
||||
RISCV_INFO(r);
|
||||
|
||||
if (CMD_ARGC > 0) {
|
||||
LOG_ERROR("Command does not take any parameters.");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
if (r->test_compliance) {
|
||||
return r->test_compliance(target);
|
||||
} else {
|
||||
LOG_ERROR("This target does not support this command (may implement an older version of the spec).");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_set_command_timeout_sec) {
|
||||
|
||||
if (CMD_ARGC != 1) {
|
||||
LOG_ERROR("Command takes exactly 1 parameter");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
int timeout = atoi(CMD_ARGV[0]);
|
||||
if (timeout <= 0){
|
||||
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
riscv_command_timeout_sec = timeout;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_set_reset_timeout_sec) {
|
||||
|
||||
if (CMD_ARGC != 1) {
|
||||
LOG_ERROR("Command takes exactly 1 parameter");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
int timeout = atoi(CMD_ARGV[0]);
|
||||
if (timeout <= 0){
|
||||
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
riscv_reset_timeout_sec = timeout;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
static const struct command_registration riscv_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "test_compliance",
|
||||
.handler = riscv_test_compliance,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "riscv test_compliance",
|
||||
.help = "Runs a basic compliance test suite against the RISC-V Debug Spec."
|
||||
},
|
||||
{
|
||||
.name = "set_command_timeout_sec",
|
||||
.handler = riscv_set_command_timeout_sec,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "riscv set_command_timeout_sec [sec]",
|
||||
.help = "Set the wall-clock timeout (in seconds) for individual commands"
|
||||
},
|
||||
{
|
||||
.name = "set_reset_timeout_sec",
|
||||
.handler = riscv_set_reset_timeout_sec,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "riscv set_reset_timeout_sec [sec]",
|
||||
.help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
const struct command_registration riscv_command_handlers[] = {
|
||||
{
|
||||
.name = "riscv",
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "RISC-V Command Group",
|
||||
.usage = "",
|
||||
.chain = riscv_exec_command_handlers
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
const char *gdb_regno_name(enum gdb_regno regno)
|
||||
{
|
||||
static char buf[32];
|
||||
|
|
Loading…
Reference in New Issue