@@ -27,6 +27,7 @@
#include "exec/exec-all.h"
#include "exec/tb-flush.h"
#include "system/cpu-timers.h"
+#include "system/kvm.h"
#include "qemu/guest-random.h"
#include "qapi/error.h"
#include <stdbool.h>
@@ -42,6 +43,11 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
csr_ops[csrno & (CSR_TABLE_SIZE - 1)] = *ops;
}
+static bool riscv_has_ext_s(CPURISCVState *env)
+{
+ return riscv_has_ext(env, RVS) || kvm_enabled();
+}
+
/* Predicates */
#if !defined(CONFIG_USER_ONLY)
RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit)
@@ -52,7 +58,7 @@ RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit)
return RISCV_EXCP_NONE;
}
- if (!(env->mstateen[index] & bit)) {
+ if (!kvm_enabled() && !(env->mstateen[index] & bit)) {
return RISCV_EXCP_ILLEGAL_INST;
}
@@ -66,7 +72,7 @@ RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit)
}
}
- if (env->priv == PRV_U && riscv_has_ext(env, RVS)) {
+ if (env->priv == PRV_U && riscv_has_ext_s(env)) {
if (!(env->sstateen[index] & bit)) {
return RISCV_EXCP_ILLEGAL_INST;
}
@@ -326,7 +332,7 @@ static RISCVException csrind_or_aia_any(CPURISCVState *env, int csrno)
static RISCVException smode(CPURISCVState *env, int csrno)
{
- if (riscv_has_ext(env, RVS)) {
+ if (riscv_has_ext_s(env)) {
return RISCV_EXCP_NONE;
}
@@ -1627,6 +1627,31 @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
}
/* User-space CSR emulation */
+static int kvm_riscv_emu_sireg_ctx_load(CPUState *cs)
+{
+ CPURISCVState *env = &RISCV_CPU(cs)->env;
+
+ KVM_RISCV_GET_CSR(cs, env, RISCV_AIA_CSR_REG(siselect), env->siselect);
+ KVM_RISCV_GET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio1), env->siprio[0]);
+ KVM_RISCV_GET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio1h), env->siprio[8]);
+ KVM_RISCV_GET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio2), env->siprio[16]);
+ KVM_RISCV_GET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio2h), env->siprio[24]);
+
+ return 0;
+}
+
+static int kvm_riscv_emu_sireg_ctx_put(CPUState *cs)
+{
+ CPURISCVState *env = &RISCV_CPU(cs)->env;
+
+ KVM_RISCV_SET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio1), env->siprio[0]);
+ KVM_RISCV_SET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio1h), env->siprio[8]);
+ KVM_RISCV_SET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio2), env->siprio[16]);
+ KVM_RISCV_SET_CSR(cs, env, RISCV_AIA_CSR_REG(iprio2h), env->siprio[24]);
+
+ return 0;
+}
+
struct kvm_riscv_emu_csr_data {
target_ulong csr_num;
int (*context_load)(CPUState *cs);
@@ -1635,6 +1660,8 @@ struct kvm_riscv_emu_csr_data {
struct kvm_riscv_emu_csr_data kvm_riscv_emu_csr_data[] = {
{ CSR_SEED, NULL, NULL },
+ { CSR_SIREG, kvm_riscv_emu_sireg_ctx_load, kvm_riscv_emu_sireg_ctx_put },
+ { CSR_STOPEI, NULL, NULL },
};
static int kvm_riscv_handle_csr(CPUState *cs, struct kvm_run *run)
Support user-space emulation of SIREG and STOPEI CSR with KVM acceleration. For SIREG emulation, the SISELECT CSR value and iprio array must be loaded before handling, and since the iprio array might be modified, it must be written back after the emulation. When running with KVM acceleration, the machine lacks M-mode CSRs and does not report S-mode support in its environment configuration, even though some S-mode CSRs are accessible. This patch adds kvm_enabled() checks in relevant predicates to ensure proper handling and validation. Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com> --- target/riscv/csr.c | 12 +++++++++--- target/riscv/kvm/kvm-cpu.c | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-)