Commit 1128e3b592 for qemu.org

commit 1128e3b5921e8d8e7f7514370941407dbcc74732
Author: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Date:   Tue May 5 09:25:21 2026 +0100

    target/arm/kvm: Cache host CPU probe failure

    kvm_arm_set_cpu_features_from_host() does not properly handle host CPU
    probe failure with caching. The current algorithm can be summarized as
    follows:

        If dtb_compatible is not cached:
            If kvm_arm_create_scratch_host_vcpu() fails:
                Report failure

            Cache dtb_compatible

            If getting register values fails:
                Report failure

        Report success

    This algorithm has the following problems:

    - If kvm_arm_create_scratch_host_vcpu() fails, probing may be repeated.
    - If getting register values fails, later invocations incorrectly report
      success.

    Make two changes to fix them:

    - Cache dtb_compatible whenever a probe is attempted.
    - Record probe failure by assigning QEMU_KVM_ARM_TARGET_NONE to
      arm_host_cpu_features.target.

    Suggested-by: Peter Maydell <peter.maydell@linaro.org>
    Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
    Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
    Message-id: 20260428-features-v1-1-1841b39da7e6@rsg.ci.i.u-tokyo.ac.jp
    Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index d4a68874b8..7d194ea112 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -273,7 +273,7 @@ static uint32_t kvm_arm_sve_get_vls(int fd)
     return vls[0] & MAKE_64BIT_MASK(0, ARM_MAX_VQ);
 }

-static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
+static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
 {
     /* Identify the feature bits corresponding to the host CPU, and
      * fill out the ARMHostCPUClass fields accordingly. To do this
@@ -287,6 +287,13 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     uint64_t features = 0;
     int err;

+    ahcf->target = QEMU_KVM_ARM_TARGET_NONE;
+    ahcf->dtb_compatible = "arm,armv8";
+
+    if (!kvm_enabled()) {
+        return;
+    }
+
     /*
      * target = -1 informs kvm_arm_create_scratch_host_vcpu()
      * to use the preferred target
@@ -326,11 +333,9 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     }

     if (!kvm_arm_create_scratch_host_vcpu(fdarray, &init)) {
-        return false;
+        return;
     }

-    ahcf->target = init.target;
-    ahcf->dtb_compatible = "arm,armv8";
     int fd = fdarray[2];

     err = get_host_cpu_reg(fd, ahcf, ID_AA64PFR0_EL1_IDX);
@@ -454,7 +459,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     kvm_arm_destroy_scratch_host_vcpu(fdarray);

     if (err < 0) {
-        return false;
+        return;
     }

     /*
@@ -471,9 +476,8 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         features |= 1ULL << ARM_FEATURE_EL2;
     }

+    ahcf->target = init.target;
     ahcf->features = features;
-
-    return true;
 }

 void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
@@ -481,18 +485,20 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
     CPUARMState *env = &cpu->env;

     if (!arm_host_cpu_features.dtb_compatible) {
-        if (!kvm_enabled() ||
-            !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) {
-            /* We can't report this error yet, so flag that we need to
-             * in arm_cpu_realizefn().
-             */
-            cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
-            cpu->host_cpu_probe_failed = true;
-            return;
-        }
+        kvm_arm_get_host_cpu_features(&arm_host_cpu_features);
     }

     cpu->kvm_target = arm_host_cpu_features.target;
+
+    if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
+        /*
+         * We can't report this error yet, so flag that we need to
+         * in arm_cpu_realizefn().
+         */
+        cpu->host_cpu_probe_failed = true;
+        return;
+    }
+
     cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible;
     cpu->isar = arm_host_cpu_features.isar;
     cpu->sve_vq.supported = arm_host_cpu_features.sve_vq_supported;