Commit 4f1076b13f for qemu.org
commit 4f1076b13f8489bc7bb4239ec17f4b56819438ff
Author: Bibo Mao <maobibo@loongson.cn>
Date: Mon Sep 14 10:14:16 2026 +0800
target/loongarch/kvm: Check LoongArch Instruction Set version 1.1
Besides PTW and DINTC features, there are some small features about
LoongArch Instruction Set version 1.1, mainly they are about atomic
instruction enhancement.
For these features, there are no special property selection, and they
are enabled from CPU type selection such as host or max CPU type. Here
adds these features if host supports and they are enabled from the
specified CPU type.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <17746591750@163.com>
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 15082a01f8..0626c553d5 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -1234,6 +1234,65 @@ static int kvm_cpu_check_msgint(CPUState *cs, Error **errp)
return 0;
}
+/* Check LoongArch Instruction Set 1.1 others feature */
+static int kvm_cpu_check_misc_v1_1(CPUState *cs, Error **errp)
+{
+ int ret;
+ uint64_t val, field;
+ struct kvm_device_attr attr;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ uint32_t data;
+
+ val = 0;
+ attr.group = KVM_LOONGARCH_VCPU_CPUCFG;
+ attr.attr = 2;
+ attr.addr = (uint64_t)&val;
+ ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
+ if (!ret) {
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
+ }
+
+ /* Disable LA 1.1 features if host cpucfg2 get not supported */
+ if (ret) {
+ val = 0;
+ }
+
+ data = cpu->env.cpucfg[2];
+ val &= data;
+ field = FIELD_EX32((uint32_t)val, CPUCFG2, FRECIPE);
+ data = FIELD_DP32(data, CPUCFG2, FRECIPE, field);
+ field = FIELD_EX32((uint32_t)val, CPUCFG2, LAM_BH);
+ data = FIELD_DP32(data, CPUCFG2, LAM_BH, field);
+ field = FIELD_EX32((uint32_t)val, CPUCFG2, LAMCAS);
+ data = FIELD_DP32(data, CPUCFG2, LAMCAS, field);
+ field = FIELD_EX32((uint32_t)val, CPUCFG2, LLACQ_SCREL);
+ data = FIELD_DP32(data, CPUCFG2, LLACQ_SCREL, field);
+ field = FIELD_EX32((uint32_t)val, CPUCFG2, SCQ);
+ data = FIELD_DP32(data, CPUCFG2, SCQ, field);
+ cpu->env.cpucfg[2] = data;
+
+ val = 0;
+ attr.group = KVM_LOONGARCH_VCPU_CPUCFG;
+ attr.attr = 3;
+ attr.addr = (uint64_t)&val;
+ ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
+ if (!ret) {
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
+ }
+
+ /* Disable LA 1.1 features if host cpucfg3 get not supported */
+ if (ret) {
+ val = 0;
+ }
+
+ data = cpu->env.cpucfg[3];
+ val &= data;
+ field = FIELD_EX32((uint32_t)val, CPUCFG3, DBAR_HINTS);
+ data = FIELD_DP32(data, CPUCFG3, DBAR_HINTS, field);
+ cpu->env.cpucfg[3] = data;
+ return 0;
+}
+
int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
{
return 0;
@@ -1295,6 +1354,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}
+ ret = kvm_cpu_check_misc_v1_1(cs, &local_err);
+ if (ret < 0) {
+ error_report_err(local_err);
+ return ret;
+ }
+
return 0;
}