@samitouri / QOSamiQemu / commits / dd45df326e

target/loongarch: Add kvm support dintc

This patch adds Kvm put/get msgint CSRs and check msgint feature. Signed-off-by: Song Gao <gaosong@loongson.cn> Reviewed-by: Bibo Mao <maobibo@loongson.cn> Message-ID: <20260813111000.446232-2-gaosong@loongson.cn>

Song Gao committed Aug 13, 2026 at 19:09 UTC dd45df326e420ed5fc3c181b716ff459beb4ac9e
3 files changed +77 -3
target/loongarch/cpu.c
+2 -3
@@ -451,9 +451,6 @@ static void loongarch_max_initfn(Object *obj)
451
452 cpu->ptw = ON_OFF_AUTO_AUTO;
453 if (tcg_enabled()) {
454 - cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
455 - cpu->msgint = ON_OFF_AUTO_AUTO;
456 -
454 uint32_t data = cpu->env.cpucfg[2];
455 data = FIELD_DP32(data, CPUCFG2, HPTW, 1);
456 /* Enable LA v1.1 instructions */
@@ -468,6 +465,8 @@ static void loongarch_max_initfn(Object *obj)
465 data = FIELD_DP32(data, CPUCFG3, DBAR_HINTS, 1);
466 cpu->env.cpucfg[3] = data;
467 }
468 + cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
469 + cpu->msgint = ON_OFF_AUTO_AUTO;
470 }
471
472 #if defined(CONFIG_KVM)
target/loongarch/cpu.h
+1
@@ -301,6 +301,7 @@ enum loongarch_features {
301 LOONGARCH_FEATURE_PV_IPI,
302 LOONGARCH_FEATURE_STEALTIME,
303 LOONGARCH_FEATURE_PTW,
304 + LOONGARCH_FEATURE_MSGINT,
305 };
306
307 typedef struct LoongArchBT {
target/loongarch/kvm/kvm.c
+74
@@ -36,6 +36,13 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
36 KVM_CAP_LAST_INFO
37 };
38
39 +static bool kvm_cpu_has_msgint(CPUState *cs)
40 +{
41 + LoongArchCPU *cpu = LOONGARCH_CPU(cs);
42 +
43 + return FIELD_EX64(cpu->env.cpucfg[1], CPUCFG1, MSG_INT);
44 +}
45 +
46 static int kvm_get_stealtime(CPUState *cs)
47 {
48 CPULoongArchState *env = cpu_env(cs);
@@ -362,6 +369,25 @@ static int kvm_loongarch_get_csr(CPUState *cs)
369
370 ret |= kvm_loongarch_get_pmu(cs);
371
372 + /*
373 + * CSR register MSGIS getting must be put after CSR register CSR_ESTAT,
374 + * Since register CSR_ESTAT will sync software pending MSGINT status to
375 + * hardware register and modify HW CSR MSGIS registers.
376 + */
377 + if (kvm_cpu_has_msgint(cs)) {
378 + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
379 + &sys->CSR_MSGIS[0]);
380 +
381 + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
382 + &sys->CSR_MSGIS[1]);
383 +
384 + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
385 + &sys->CSR_MSGIS[2]);
386 +
387 + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
388 + &sys->CSR_MSGIS[3]);
389 + }
390 +
391 ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
392 &sys->CSR_TVAL);
393
@@ -538,6 +564,20 @@ static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState level)
564
565 ret |= kvm_loongarch_put_pmu(cs);
566
567 + if (kvm_cpu_has_msgint(cs)) {
568 + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
569 + &sys->CSR_MSGIS[0]);
570 +
571 + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
572 + &sys->CSR_MSGIS[1]);
573 +
574 + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
575 + &sys->CSR_MSGIS[2]);
576 +
577 + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
578 + &sys->CSR_MSGIS[3]);
579 + }
580 +
581 /*
582 * timer cfg must be put at last since it is used to enable
583 * guest timer
@@ -993,6 +1033,12 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
1033 ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
1034 return (ret == 0);
1035
1036 + case LOONGARCH_FEATURE_MSGINT:
1037 + attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
1038 + attr.attr = KVM_LOONGARCH_VM_FEAT_MSGINT;
1039 + ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
1040 + return (ret == 0);
1041 +
1042 default:
1043 return false;
1044 }
@@ -1166,6 +1212,28 @@ static int kvm_cpu_check_pv_features(CPUState *cs, Error **errp)
1212 return 0;
1213 }
1214
1215 +static int kvm_cpu_check_msgint(CPUState *cs, Error **errp)
1216 +{
1217 + CPULoongArchState *env = cpu_env(cs);
1218 + LoongArchCPU *cpu = LOONGARCH_CPU(cs);
1219 + bool kvm_supported;
1220 +
1221 + kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_MSGINT);
1222 + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 0);
1223 + if (cpu->msgint == ON_OFF_AUTO_ON) {
1224 + if (kvm_supported) {
1225 + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
1226 + } else {
1227 + error_setg(errp, "'msgint' feature not supported by KVM on this host");
1228 + return -ENOTSUP;
1229 + }
1230 + } else if ((cpu->msgint == ON_OFF_AUTO_AUTO) && kvm_supported) {
1231 + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
1232 + }
1233 +
1234 + return 0;
1235 +}
1236 +
1237 int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
1238 {
1239 return 0;
@@ -1221,6 +1289,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
1289 return ret;
1290 }
1291
1292 + ret = kvm_cpu_check_msgint(cs, &local_err);
1293 + if (ret < 0) {
1294 + error_report_err(local_err);
1295 + return ret;
1296 + }
1297 +
1298 return 0;
1299 }
1300