@@ -928,8 +928,6 @@ static inline const char *riscv_get_csr_name(int csr_no)
}
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
-target_ulong riscv_new_csr_seed(target_ulong new_value,
- target_ulong write_mask);
uint8_t satp_mode_max_from_map(uint32_t map);
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
@@ -5389,8 +5389,10 @@ static int write_mnstatus(CPURISCVState *env, int csrno, target_ulong val)
#endif
/* Crypto Extension */
-target_ulong riscv_new_csr_seed(target_ulong new_value,
- target_ulong write_mask)
+static RISCVException rmw_seed(CPURISCVState *env, int csrno,
+ target_ulong *ret_value,
+ target_ulong new_value,
+ target_ulong write_mask)
{
uint16_t random_v;
Error *random_e = NULL;
@@ -5414,18 +5416,6 @@ target_ulong riscv_new_csr_seed(target_ulong new_value,
rval = random_v | SEED_OPST_ES16;
}
- return rval;
-}
-
-static RISCVException rmw_seed(CPURISCVState *env, int csrno,
- target_ulong *ret_value,
- target_ulong new_value,
- target_ulong write_mask)
-{
- target_ulong rval;
-
- rval = riscv_new_csr_seed(new_value, write_mask);
-
if (ret_value) {
*ret_value = rval;
}
@@ -1626,26 +1626,72 @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
return ret;
}
+/* User-space CSR emulation */
+struct kvm_riscv_emu_csr_data {
+ target_ulong csr_num;
+ int (*context_load)(CPUState *cs);
+ int (*context_put)(CPUState *cs);
+};
+
+struct kvm_riscv_emu_csr_data kvm_riscv_emu_csr_data[] = {
+ { CSR_SEED, NULL, NULL },
+};
+
static int kvm_riscv_handle_csr(CPUState *cs, struct kvm_run *run)
{
+ CPURISCVState *env = cpu_env(cs);
target_ulong csr_num = run->riscv_csr.csr_num;
target_ulong new_value = run->riscv_csr.new_value;
target_ulong write_mask = run->riscv_csr.write_mask;
- int ret = 0;
+ struct kvm_riscv_emu_csr_data *emu_csr_data = NULL;
+ target_ulong ret_value;
+ RISCVException ret_excp;
+ int i, ret;
- switch (csr_num) {
- case CSR_SEED:
- run->riscv_csr.ret_value = riscv_new_csr_seed(new_value, write_mask);
- break;
- default:
+ for (i = 0; i < ARRAY_SIZE(kvm_riscv_emu_csr_data); i++) {
+ if (csr_num == kvm_riscv_emu_csr_data[i].csr_num) {
+ emu_csr_data = &kvm_riscv_emu_csr_data[i];
+
+ break;
+ }
+ }
+
+ if (!emu_csr_data) {
qemu_log_mask(LOG_UNIMP,
- "%s: un-handled CSR EXIT for CSR %lx\n",
- __func__, csr_num);
- ret = -1;
- break;
+ "%s: un-handled CSR EXIT for CSR %s\n",
+ __func__, riscv_get_csr_name(csr_num));
+
+ return -1;
}
- return ret;
+ if (emu_csr_data->context_load) {
+ ret = emu_csr_data->context_load(cs);
+ if (ret) {
+ goto handle_failed;
+ }
+ }
+
+ ret_excp = riscv_csrrw(env, csr_num, &ret_value, new_value, write_mask);
+ if (ret_excp != RISCV_EXCP_NONE) {
+ goto handle_failed;
+ }
+ run->riscv_csr.ret_value = ret_value;
+
+ if (emu_csr_data->context_put) {
+ ret = emu_csr_data->context_put(cs);
+ if (ret) {
+ goto handle_failed;
+ }
+ }
+
+ return 0;
+
+handle_failed:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: failed to handle CSR EXIT for CSR %s\n",
+ __func__, riscv_get_csr_name(csr_num));
+
+ return -1;
}
static bool kvm_riscv_handle_debug(CPUState *cs)
Rewrite the kvm_riscv_handle_csr() to support additional CSR emulation in user space with KVM acceleration. This update reuses the TCG CSR emulation function to simplify the implementation and reduce the redundant work. Also it introduces two hook functions for certain CSRs. Before emulation, the related VS mode context of the CSR can be loaded from host in context_load() hook. After the CSR handling, the modified VS context is written back in context_put() hook. Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com> --- target/riscv/cpu.h | 2 -- target/riscv/csr.c | 18 +++------- target/riscv/kvm/kvm-cpu.c | 68 ++++++++++++++++++++++++++++++++------ 3 files changed, 61 insertions(+), 27 deletions(-)