Commit 4b110ab5fd for qemu.org
commit 4b110ab5fd47a77b8669d1d9c021cafb11d83112
Author: Eric Auger <eric.auger@redhat.com>
Date: Fri Oct 30 14:13:16 2026 +0100
hw/arm/virt: Make sure virt_get_caches() keeps on reading CLIDR_EL1 as 0
In KVM mode, virt_get_caches() currently gets a zero value for the
CLIDR_EL1 register. This is due to the fact CLIDR is never read from
host. This is a bug.
Soon we will initialize all writable isar.idreg[] from host and this
includes CLIDR_EL1. However, we cannot directly fix the initialization,
first because it would change the way caches are exposed to guest in
DT/ACPI descriptions and because some host values would be rejected
by the current QEMU code, especially in the case host has a unified
L1 cache which is currently not supported and triggers the following
error: "Unified type is not implemented at level 1" error.
So this issue will be fixed separately.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Khushit Shah <khushit.shah@nutanix.com>
Reviewed-by: Gustavo Romero <gromero@redhat.com>
Reviewed-by: Mohammadfaiz Bawa <mbawa@redhat.com>
Message-id: 20261030131406.461599-9-eric.auger@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 3ab3ad8c3b..637b44ff33 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -337,6 +337,21 @@ unsigned int virt_get_caches(const VirtMachineState *vms, CPUCoreCaches *caches)
ARMISARegisters *isar = &armcpu->isar;
uint32_t clidr = GET_IDREG(isar, CLIDR);
+ /*
+ * Commit f669de70011 ("hw/arm/virt: add cache hierarchy to device tree")
+ * read the CLIDR value from the isar array. However, in KVM mode, we failed
+ * to initialize that register value from host and the resulting bug is that
+ * we have always read 0.
+ *
+ * Soon we will initialize all writable isar.idreg[] from host, including
+ * CLIDR_EL1 but we will need to handle compat properly and also extend the
+ * support to unified L1 cache. For now do not pretend we have something
+ * different from 0.
+ */
+ if (kvm_enabled()) {
+ clidr = 0;
+ }
+
for (int cache_level = 1; cache_level <= CLIDR_CTYPE_MAX_CACHE_LEVEL;
cache_level++) {
uint8_t ctype =