@samitouri / QOSamiQemu / commits / 1128e3b592

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>

Akihiko Odaki committed May 5, 2026 at 09:25 UTC 1128e3b5921e8d8e7f7514370941407dbcc74732
1 file changed +22 -16
target/arm/kvm.c
+22 -16
@@ -273,7 +273,7 @@ static uint32_t kvm_arm_sve_get_vls(int fd)
273 return vls[0] & MAKE_64BIT_MASK(0, ARM_MAX_VQ);
274 }
275
276 -static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
276 +static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
277 {
278 /* Identify the feature bits corresponding to the host CPU, and
279 * fill out the ARMHostCPUClass fields accordingly. To do this
@@ -287,6 +287,13 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
287 uint64_t features = 0;
288 int err;
289
290 + ahcf->target = QEMU_KVM_ARM_TARGET_NONE;
291 + ahcf->dtb_compatible = "arm,armv8";
292 +
293 + if (!kvm_enabled()) {
294 + return;
295 + }
296 +
297 /*
298 * target = -1 informs kvm_arm_create_scratch_host_vcpu()
299 * to use the preferred target
@@ -326,11 +333,9 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
333 }
334
335 if (!kvm_arm_create_scratch_host_vcpu(fdarray, &init)) {
329 - return false;
336 + return;
337 }
338
332 - ahcf->target = init.target;
333 - ahcf->dtb_compatible = "arm,armv8";
339 int fd = fdarray[2];
340
341 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)
459 kvm_arm_destroy_scratch_host_vcpu(fdarray);
460
461 if (err < 0) {
457 - return false;
462 + return;
463 }
464
465 /*
@@ -471,9 +476,8 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
476 features |= 1ULL << ARM_FEATURE_EL2;
477 }
478
479 + ahcf->target = init.target;
480 ahcf->features = features;
475 -
476 - return true;
481 }
482
483 void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
@@ -481,18 +485,20 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
485 CPUARMState *env = &cpu->env;
486
487 if (!arm_host_cpu_features.dtb_compatible) {
484 - if (!kvm_enabled() ||
485 - !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) {
486 - /* We can't report this error yet, so flag that we need to
487 - * in arm_cpu_realizefn().
488 - */
489 - cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
490 - cpu->host_cpu_probe_failed = true;
491 - return;
492 - }
488 + kvm_arm_get_host_cpu_features(&arm_host_cpu_features);
489 }
490
491 cpu->kvm_target = arm_host_cpu_features.target;
492 +
493 + if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
494 + /*
495 + * We can't report this error yet, so flag that we need to
496 + * in arm_cpu_realizefn().
497 + */
498 + cpu->host_cpu_probe_failed = true;
499 + return;
500 + }
501 +
502 cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible;
503 cpu->isar = arm_host_cpu_features.isar;
504 cpu->sve_vq.supported = arm_host_cpu_features.sve_vq_supported;