diff options
author | Michael Clark <mjc@sifive.com> | 2019-01-04 23:23:55 +0000 |
---|---|---|
committer | Palmer Dabbelt <palmer@sifive.com> | 2019-01-08 13:59:09 -0800 |
commit | c7b951718815694284501ed01fec7acb8654db7b (patch) | |
tree | 46b4536a8192583eafe702156b0147224299c45d /target/riscv/cpu.h | |
parent | 147923b1a901a0370f83a0f4c58ec1baffef22f0 (diff) |
RISC-V: Implement modular CSR helper interface
Previous CSR code uses csr_read_helper and csr_write_helper
to update CSR registers however this interface prevents
atomic read/modify/write CSR operations; in addition
there is no trap-free method to access to CSRs due
to the monolithic CSR functions call longjmp.
The current iCSR interface is not safe to be called by
target/riscv/gdbstub.c as privilege checks or missing CSRs
may call longjmp to generate exceptions. It needs to
indicate existence so traps can be generated in the
CSR instruction helpers.
This commit moves CSR access from the monolithic switch
statements in target/riscv/op_helper.c into modular
read/write functions in target/riscv/csr.c using a new
function pointer table for dispatch (which can later
be used to allow CPUs to hook up model specific CSRs).
A read/modify/write interface is added to support atomic
CSR operations and a non-trapping interface is added
to allow exception-free access to CSRs by the debugger.
The CSR functions and CSR dispatch table are ordered
to match The RISC-V Instruction Set Manual, Volume II:
Privileged Architecture Version 1.10, 2.2 CSR Listing.
An API is added to allow derived cpu instances to modify
or implement new CSR operations.
Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Diffstat (limited to 'target/riscv/cpu.h')
-rw-r--r-- | target/riscv/cpu.h | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 4ee09b9cff..4aeaa32049 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -289,9 +289,38 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, #endif } -void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, - target_ulong csrno); -target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno); +int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, + target_ulong new_value, target_ulong write_mask); + +static inline void csr_write_helper(CPURISCVState *env, target_ulong val, + int csrno) +{ + riscv_csrrw(env, csrno, NULL, val, MAKE_64BIT_MASK(0, TARGET_LONG_BITS)); +} + +static inline target_ulong csr_read_helper(CPURISCVState *env, int csrno) +{ + target_ulong val = 0; + riscv_csrrw(env, csrno, &val, 0, 0); + return val; +} + +typedef int (*riscv_csr_predicate_fn)(CPURISCVState *env, int csrno); +typedef int (*riscv_csr_read_fn)(CPURISCVState *env, int csrno, + target_ulong *ret_value); +typedef int (*riscv_csr_write_fn)(CPURISCVState *env, int csrno, + target_ulong new_value); +typedef int (*riscv_csr_op_fn)(CPURISCVState *env, int csrno, + target_ulong *ret_value, target_ulong new_value, target_ulong write_mask); + +typedef struct { + riscv_csr_read_fn read; + riscv_csr_write_fn write; + riscv_csr_op_fn op; +} riscv_csr_operations; + +void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops); +void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops); #include "exec/cpu-all.h" |