Skip to content

Commit

Permalink
target/riscv: access registers via reg->type
Browse files Browse the repository at this point in the history
* `int riscv_reg_get()` and `int riscv_reg_set()` are implemented in
  terms of `reg->type->get/set` instead of the other way around. This
  makes it easier to support custom behavior for some registers.
* Cacheability is determined by `reg->type` instead of
  `riscv_reg_impl_gdb_regno_cacheable()`.
* Issues with redirection of `priv` -> `dcsr` and `pc` -> `dpc` are
  addressed at the "topmost" level.
    - `priv` and `pc` are always invalid.
    - Fixed some issues, e.g. the first `pc` write printed-out an
      uninitialized value:
```
> reg pc 0
pc (/64): 0x000075da6b33db20
```

Change-Id: I514547f455d62b289fb5dee62753bf5d9aa3b8ae
Signed-off-by: Evgeniy Naydanov <[email protected]>
  • Loading branch information
en-sc committed Feb 27, 2025
1 parent 2c4dfd9 commit 85654c1
Show file tree
Hide file tree
Showing 6 changed files with 509 additions and 314 deletions.
9 changes: 4 additions & 5 deletions src/target/riscv/program.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ int riscv_program_init(struct riscv_program *p, struct target *t);
/* Write the program to the program buffer. */
int riscv_program_write(struct riscv_program *program);

/* Executes a program, returning 0 if the program successfully executed. Note
* that this may cause registers to be saved or restored, which could result to
* calls to things like riscv013_reg_save which itself could require a
* program to execute. That's OK, just make sure this eventually terminates.
* */
/* Executes the RISC-V Program Buffer and returns ERROR_OK if the program
* buffer got successfully executed. In case of failure, more detailed error reason
* can be found in p->execution_result.
*/
int riscv_program_exec(struct riscv_program *p, struct target *t);

/* A lower level interface, you shouldn't use this unless you have a reason. */
Expand Down
51 changes: 21 additions & 30 deletions src/target/riscv/riscv-013.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ static int examine_progbuf(struct target *target)
return ERROR_OK;
}

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand Down Expand Up @@ -1318,7 +1318,7 @@ static int fpr_read_progbuf(struct target *target, uint64_t *value,

const unsigned int freg = number - GDB_REGNO_FPR0;

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand Down Expand Up @@ -1348,7 +1348,7 @@ static int csr_read_progbuf(struct target *target, uint64_t *value,
assert(target->state == TARGET_HALTED);
assert(number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095);

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand Down Expand Up @@ -1416,7 +1416,7 @@ static int fpr_write_progbuf(struct target *target, enum gdb_regno number,
assert(number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31);
const unsigned int freg = number - GDB_REGNO_FPR0;

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand Down Expand Up @@ -1446,11 +1446,11 @@ static int vtype_write_progbuf(struct target *target, riscv_reg_t value)
{
assert(target->state == TARGET_HALTED);

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (register_write_abstract(target, GDB_REGNO_S0, value) != ERROR_OK)
return ERROR_FAIL;
if (riscv013_reg_save(target, GDB_REGNO_S1) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand All @@ -1467,11 +1467,11 @@ static int vl_write_progbuf(struct target *target, riscv_reg_t value)
{
assert(target->state == TARGET_HALTED);

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (register_write_abstract(target, GDB_REGNO_S0, value) != ERROR_OK)
return ERROR_FAIL;
if (riscv013_reg_save(target, GDB_REGNO_S1) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand All @@ -1490,7 +1490,7 @@ static int csr_write_progbuf(struct target *target, enum gdb_regno number,
assert(target->state == TARGET_HALTED);
assert(number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095);

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (register_write_abstract(target, GDB_REGNO_S0, value) != ERROR_OK)
return ERROR_FAIL;
Expand Down Expand Up @@ -2296,7 +2296,7 @@ int riscv013_get_register_buf(struct target *target, uint8_t *value,
&debug_vl, &debug_vsew) != ERROR_OK)
return ERROR_FAIL;

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;

unsigned int vnum = regno - GDB_REGNO_V0;
Expand Down Expand Up @@ -2351,7 +2351,7 @@ int riscv013_set_register_buf(struct target *target, enum gdb_regno regno,
&debug_vl, &debug_vsew) != ERROR_OK)
return ERROR_FAIL;

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;

unsigned int vnum = regno - GDB_REGNO_V0;
Expand Down Expand Up @@ -4278,11 +4278,11 @@ static int read_memory_progbuf_inner_fill_progbuf(struct target *target,
{
const bool is_repeated_read = increment == 0;

if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (riscv013_reg_save(target, GDB_REGNO_S1) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
if (is_repeated_read && riscv013_reg_save(target, GDB_REGNO_A0) != ERROR_OK)
if (is_repeated_read && riscv013_reg_save_gpr(target, GDB_REGNO_A0) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand Down Expand Up @@ -4376,7 +4376,7 @@ read_memory_progbuf_inner_one(struct target *target, const riscv_mem_access_args
{
assert(riscv_mem_access_is_read(args));

if (riscv013_reg_save(target, GDB_REGNO_S1) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S1) != ERROR_OK)
return mem_access_result(MEM_ACCESS_SKIPPED_REG_SAVE_FAILED);

struct riscv_program program;
Expand Down Expand Up @@ -4951,9 +4951,9 @@ static int write_memory_progbuf_try_to_write(struct target *target,

static int write_memory_progbuf_fill_progbuf(struct target *target, uint32_t size)
{
if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (riscv013_reg_save(target, GDB_REGNO_S1) != ERROR_OK)
if (riscv013_reg_save_gpr(target, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;

struct riscv_program program;
Expand Down Expand Up @@ -5058,19 +5058,8 @@ struct target_type riscv013_target = {
int riscv013_get_register(struct target *target,
riscv_reg_t *value, enum gdb_regno rid)
{
/* It would be beneficial to move this redirection to the
* version-independent section, but there is a conflict:
* `dcsr[5]` is `dcsr.v` in current spec, but it is `dcsr.debugint` in 0.11.
*/
if (rid == GDB_REGNO_PRIV) {
uint64_t dcsr;
if (riscv_reg_get(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK)
return ERROR_FAIL;
*value = set_field(0, VIRT_PRIV_V, get_field(dcsr, CSR_DCSR_V));
*value = set_field(*value, VIRT_PRIV_PRV, get_field(dcsr, CSR_DCSR_PRV));
return ERROR_OK;
}

assert(rid != GDB_REGNO_PC && "'pc' should be read through 'dpc'");
assert(rid != GDB_REGNO_PRIV && "'priv' should be read through 'dcsr'");
LOG_TARGET_DEBUG(target, "reading register %s", riscv_reg_gdb_regno_name(target, rid));

if (dm013_select_target(target) != ERROR_OK)
Expand All @@ -5087,6 +5076,8 @@ int riscv013_get_register(struct target *target,
int riscv013_set_register(struct target *target, enum gdb_regno rid,
riscv_reg_t value)
{
assert(rid != GDB_REGNO_PC && "'pc' should be written through 'dpc'");
assert(rid != GDB_REGNO_PRIV && "'priv' should be written through 'dcsr'");
LOG_TARGET_DEBUG(target, "writing 0x%" PRIx64 " to register %s",
value, riscv_reg_gdb_regno_name(target, rid));

Expand Down
Loading

0 comments on commit 85654c1

Please sign in to comment.