Skip to content

Commit

Permalink
target/riscv: reg cache entry is initialized before access
Browse files Browse the repository at this point in the history
* Register file examination is separated.
* Allow to access registers through cache as early as possible to re-use
  general register access interface and propely track state of the
  register.
* Reduces the number of operations: S0 and S1 are saved/restored only
  when needed (targets without abstract CSR access).

Change-Id: I2e205ae4e88733a5c792f8a35cf30325c68d96b2
Signed-off-by: Evgeniy Naydanov <[email protected]>
  • Loading branch information
en-sc committed Aug 12, 2024
1 parent 9a23c9e commit 6d357f4
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 122 deletions.
4 changes: 3 additions & 1 deletion src/target/riscv/riscv-011_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ static const struct reg_arch_type *riscv011_gdb_regno_reg_type(uint32_t regno)

static int riscv011_init_reg(struct target *target, uint32_t regno)
{
return riscv_reg_impl_init_one(target, regno, riscv011_gdb_regno_reg_type(regno));
return riscv_reg_impl_init_cache_entry(target, regno,
riscv_reg_impl_gdb_regno_exist(target, regno),
riscv011_gdb_regno_reg_type(regno));
}

int riscv011_reg_init_all(struct target *target)
Expand Down
99 changes: 19 additions & 80 deletions src/target/riscv/riscv-013.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ static int abstract_cmd_batch_check_and_clear_cmderr(struct target *target,
return res;
}

static int execute_abstract_command(struct target *target, uint32_t command,
int riscv013_execute_abstract_command(struct target *target, uint32_t command,
uint32_t *cmderr)
{
assert(cmderr);
Expand Down Expand Up @@ -863,7 +863,7 @@ static int write_abstract_arg(struct target *target, unsigned index,
/**
* @par size in bits
*/
static uint32_t access_register_command(struct target *target, uint32_t number,
uint32_t riscv013_access_register_command(struct target *target, uint32_t number,
unsigned size, uint32_t flags)
{
uint32_t command = set_field(0, DM_COMMAND_CMDTYPE, 0);
Expand Down Expand Up @@ -920,11 +920,11 @@ static int register_read_abstract_with_size(struct target *target,
if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31)
return ERROR_FAIL;

uint32_t command = access_register_command(target, number, size,
uint32_t command = riscv013_access_register_command(target, number, size,
AC_ACCESS_REGISTER_TRANSFER);

uint32_t cmderr;
int result = execute_abstract_command(target, command, &cmderr);
int result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result != ERROR_OK) {
if (cmderr == CMDERR_NOT_SUPPORTED) {
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
Expand Down Expand Up @@ -969,7 +969,7 @@ static int register_write_abstract(struct target *target, enum gdb_regno number,
return ERROR_FAIL;

const unsigned int size_bits = register_size(target, number);
const uint32_t command = access_register_command(target, number, size_bits,
const uint32_t command = riscv013_access_register_command(target, number, size_bits,
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE);
LOG_DEBUG_REG(target, AC_ACCESS_REGISTER, command);
Expand Down Expand Up @@ -2112,70 +2112,9 @@ static int examine(struct target *target)
* program buffer. */
r->progbuf_size = info->progbufsize;

result = register_read_abstract_with_size(target, NULL, GDB_REGNO_S0, 64);
if (result == ERROR_OK)
r->xlen = 64;
else
r->xlen = 32;

/* Save s0 and s1. The register cache hasn't be initialized yet so we
* need to take care of this manually. */
uint64_t s0, s1;
if (register_read_abstract(target, &s0, GDB_REGNO_S0) != ERROR_OK) {
LOG_TARGET_ERROR(target, "Fatal: Failed to read s0.");
return ERROR_FAIL;
}
if (register_read_abstract(target, &s1, GDB_REGNO_S1) != ERROR_OK) {
LOG_TARGET_ERROR(target, "Fatal: Failed to read s1.");
return ERROR_FAIL;
}

if (register_read_direct(target, &r->misa, GDB_REGNO_MISA)) {
LOG_TARGET_ERROR(target, "Fatal: Failed to read MISA.");
return ERROR_FAIL;
}

uint64_t value;
if (register_read_direct(target, &value, GDB_REGNO_VLENB) != ERROR_OK) {
if (riscv_supports_extension(target, 'V'))
LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work.");
r->vlenb = 0;
} else {
r->vlenb = value;
LOG_TARGET_INFO(target, "Vector support with vlenb=%d", r->vlenb);
}

if (register_read_direct(target, &value, GDB_REGNO_MTOPI) == ERROR_OK) {
r->mtopi_readable = true;

if (register_read_direct(target, &value, GDB_REGNO_MTOPEI) == ERROR_OK) {
LOG_TARGET_INFO(target, "S?aia detected with IMSIC");
r->mtopei_readable = true;
} else {
r->mtopei_readable = false;
LOG_TARGET_INFO(target, "S?aia detected without IMSIC");
}
} else {
r->mtopi_readable = false;
}

/* Display this as early as possible to help people who are using
* really slow simulators. */
LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, r->xlen, r->misa);

/* Restore s0 and s1. */
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) {
LOG_TARGET_ERROR(target, "Fatal: Failed to write back s0.");
return ERROR_FAIL;
}
if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) {
LOG_TARGET_ERROR(target, "Fatal: Failed to write back s1.");
return ERROR_FAIL;
}

/* Now init registers based on what we discovered. */
if (riscv013_reg_init_all(target) != ERROR_OK)
return ERROR_FAIL;
result = riscv013_reg_examine_all(target);
if (result != ERROR_OK)
return result;

if (set_dcsr_ebreak(target, false) != ERROR_OK)
return ERROR_FAIL;
Expand Down Expand Up @@ -3651,7 +3590,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address,

/* Execute the command */
uint32_t cmderr;
result = execute_abstract_command(target, command, &cmderr);
result = riscv013_execute_abstract_command(target, command, &cmderr);

/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
Expand All @@ -3673,7 +3612,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
} else {
/* Try the same access but with postincrement disabled. */
command = access_memory_command(target, false, width, false, false);
result = execute_abstract_command(target, command, &cmderr);
result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result == ERROR_OK) {
LOG_TARGET_DEBUG(target, "aampostincrement is not supported on this target.");
info->has_aampostincrement = YNM_NO;
Expand Down Expand Up @@ -3744,7 +3683,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,

/* Execute the command */
uint32_t cmderr;
result = execute_abstract_command(target, command, &cmderr);
result = riscv013_execute_abstract_command(target, command, &cmderr);

/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
Expand All @@ -3766,7 +3705,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
} else {
/* Try the same access but with postincrement disabled. */
command = access_memory_command(target, false, width, false, true);
result = execute_abstract_command(target, command, &cmderr);
result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result == ERROR_OK) {
LOG_TARGET_DEBUG(target, "aampostincrement is not supported on this target.");
info->has_aampostincrement = YNM_NO;
Expand Down Expand Up @@ -3812,11 +3751,11 @@ static int read_memory_progbuf_inner_startup(struct target *target,
/* AC_ACCESS_REGISTER_POSTEXEC is used to trigger first stage of the
* pipeline (memory -> s1) whenever this command is executed.
*/
const uint32_t startup_command = access_register_command(target,
const uint32_t startup_command = riscv013_access_register_command(target,
GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC);
uint32_t cmderr;
if (execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK)
if (riscv013_execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK)
return ERROR_FAIL;
/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
Expand Down Expand Up @@ -4299,11 +4238,11 @@ static int read_memory_progbuf_inner_one(struct target *target,
if (write_abstract_arg(target, 0, access.target_address, riscv_xlen(target))
!= ERROR_OK)
return ERROR_FAIL;
uint32_t command = access_register_command(target, GDB_REGNO_S1,
uint32_t command = riscv013_access_register_command(target, GDB_REGNO_S1,
riscv_xlen(target), AC_ACCESS_REGISTER_WRITE |
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC);
uint32_t cmderr;
if (execute_abstract_command(target, command, &cmderr) != ERROR_OK)
if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK)
return ERROR_FAIL;

return read_word_from_s1(target, access, 0);
Expand Down Expand Up @@ -4642,14 +4581,14 @@ static int write_memory_progbuf_startup(struct target *target, target_addr_t *ad

/* Write and execute command that moves the value from data0 [, data1]
* into S1 and executes program buffer. */
uint32_t command = access_register_command(target,
uint32_t command = riscv013_access_register_command(target,
GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_POSTEXEC |
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE);

uint32_t cmderr;
if (execute_abstract_command(target, command, &cmderr) != ERROR_OK)
if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK)
return ERROR_FAIL;

log_memory_access64(*address_p, value, size, /*is_read*/ false);
Expand Down Expand Up @@ -5320,7 +5259,7 @@ static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr)
run_program = set_field(run_program, AC_ACCESS_REGISTER_TRANSFER, 0);
run_program = set_field(run_program, AC_ACCESS_REGISTER_REGNO, 0x1000);

return execute_abstract_command(target, run_program, cmderr);
return riscv013_execute_abstract_command(target, run_program, cmderr);
}

static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d)
Expand Down
4 changes: 4 additions & 0 deletions src/target/riscv/riscv-013.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@ int riscv013_set_register(struct target *target, enum gdb_regno rid,
riscv_reg_t value);
int riscv013_set_register_buf(struct target *target, enum gdb_regno regno,
const uint8_t *value);
uint32_t riscv013_access_register_command(struct target *target, uint32_t number,
unsigned int size, uint32_t flags);
int riscv013_execute_abstract_command(struct target *target, uint32_t command,
uint32_t *cmderr);

#endif /* OPENOCD_TARGET_RISCV_RISCV_013_H */
Loading

0 comments on commit 6d357f4

Please sign in to comment.