This patch adds Kvm put/get msgint CSRs and check msgint feature.
Signed-off-by: Song Gao <[email protected]>
---
target/loongarch/cpu.c | 5 ++-
target/loongarch/cpu.h | 1 +
target/loongarch/kvm/kvm.c | 74 ++++++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 8f277f7696..64f437fcba 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -443,9 +443,6 @@ static void loongarch_max_initfn(Object *obj)
cpu->ptw = ON_OFF_AUTO_AUTO;
if (tcg_enabled()) {
- cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT,
1);
- cpu->msgint = ON_OFF_AUTO_AUTO;
-
uint32_t data = cpu->env.cpucfg[2];
data = FIELD_DP32(data, CPUCFG2, HPTW, 1);
/* Enable LA v1.1 instructions */
@@ -460,6 +457,8 @@ static void loongarch_max_initfn(Object *obj)
data = FIELD_DP32(data, CPUCFG3, DBAR_HINTS, 1);
cpu->env.cpucfg[3] = data;
}
+ cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
+ cpu->msgint = ON_OFF_AUTO_AUTO;
}
#if defined(CONFIG_KVM)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 096d778928..e6bbcded95 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -301,6 +301,7 @@ enum loongarch_features {
LOONGARCH_FEATURE_PV_IPI,
LOONGARCH_FEATURE_STEALTIME,
LOONGARCH_FEATURE_PTW,
+ LOONGARCH_FEATURE_MSGINT,
};
typedef struct LoongArchBT {
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 4af4ab2ed0..af08f551a0 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -36,6 +36,13 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
+static bool kvm_cpu_has_msgint(CPUState *cs)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+ return FIELD_EX64(cpu->env.cpucfg[1], CPUCFG1, MSG_INT);
+}
+
static int kvm_get_stealtime(CPUState *cs)
{
CPULoongArchState *env = cpu_env(cs);
@@ -359,6 +366,25 @@ static int kvm_loongarch_get_csr(CPUState *cs)
ret |= kvm_loongarch_get_pmu(cs);
+ /*
+ * CSR register MSGIS getting must be put after CSR register CSR_ESTAT,
+ * Since register CSR_ESTAT will sync software pending MSGINT status to
+ * hardware register and modify HW CSR MSGIS registers.
+ */
+ if (kvm_cpu_has_msgint(cs)) {
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
+ &env->CSR_MSGIS[0]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
+ &env->CSR_MSGIS[1]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
+ &env->CSR_MSGIS[2]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
+ &env->CSR_MSGIS[3]);
+ }
+
ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
&env->CSR_TVAL);
@@ -534,6 +560,20 @@ static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState
level)
ret |= kvm_loongarch_put_pmu(cs);
+ if (kvm_cpu_has_msgint(cs)) {
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
+ &env->CSR_MSGIS[0]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
+ &env->CSR_MSGIS[1]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
+ &env->CSR_MSGIS[2]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
+ &env->CSR_MSGIS[3]);
+ }
+
/*
* timer cfg must be put at last since it is used to enable
* guest timer
@@ -983,6 +1023,12 @@ static bool kvm_feature_supported(CPUState *cs, enum
loongarch_features feature)
ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
return (ret == 0);
+ case LOONGARCH_FEATURE_MSGINT:
+ attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
+ attr.attr = KVM_LOONGARCH_VM_FEAT_MSGINT;
+ ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
+ return (ret == 0);
+
default:
return false;
}
@@ -1156,6 +1202,28 @@ static int kvm_cpu_check_pv_features(CPUState *cs, Error
**errp)
return 0;
}
+static int kvm_cpu_check_msgint(CPUState *cs, Error **errp)
+{
+ CPULoongArchState *env = cpu_env(cs);
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ bool kvm_supported;
+
+ kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_MSGINT);
+ env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 0);
+ if (cpu->msgint == ON_OFF_AUTO_ON) {
+ if (kvm_supported) {
+ env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
+ } else {
+ error_setg(errp, "'msgint' feature not supported by KVM on this
host");
+ return -ENOTSUP;
+ }
+ } else if ((cpu->msgint == ON_OFF_AUTO_AUTO) && kvm_supported) {
+ env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
+ }
+
+ return 0;
+}
+
int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
{
return 0;
@@ -1211,6 +1279,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}
+ ret = kvm_cpu_check_msgint(cs, &local_err);
+ if (ret < 0) {
+ error_report_err(local_err);
+ return ret;
+ }
+
return 0;
}
--
2.47.3