encode_topo_cpuid1f() asserts count <= CPU_TOPOLOGY_LEVEL_SOCKET, but
count is the subleaf index passed straight from the guest's ECX;
cpu_x86_cpuid() does not clamp it for leaf 0x1f. On a TCG vCPU exposing
0x1f, any CPUID(0x1f) with ECX > 5 aborts QEMU. SeaBIOS already trips
this during POST (its cpuid() helper leaves a stale ECX from the
EFLAGS.ID probe), and guests reach it too,the kernel walks 0x1f
subleaves in a loop and /dev/cpu/*/cpuid forwards arbitrary subleaves.
Per the SDM, CPUID never faults and a subleaf past the last topology
level returns the invalid encoding (EAX=EBX=0, ECX level type 0, EDX the
x2APIC ID), exactly as the legacy 0xB leaf already does. Return that
instead of asserting. KVM is unaffected.
Affected models: SapphireRapids (v4+), GraniteRapids (v3+), SierraForest
(v3+), ClearwaterForest (v3+), DiamondRapids and YongFeng (v3+).
Fixes: 822bce9f58df ("i386/cpu: Decouple CPUID[0x1F] subleaf with specific topology level")
Signed-off-by: Ewan Hai <ewanhai-oc@zhaoxin.com>
---
target/i386/cpu.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 8929a75c7c..e035e4cf45 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -427,7 +427,14 @@ static void encode_topo_cpuid1f(CPUX86State *env, uint32_t count,
unsigned long level, base_level, next_level;
uint32_t num_threads_next_level, offset_next_level;
- assert(count <= CPU_TOPOLOGY_LEVEL_SOCKET);
+ /* Out-of-range subleaf: SDM mandates the invalid encoding, no fault. */
+ if (count > CPU_TOPOLOGY_LEVEL_SOCKET) {
+ *eax = 0;
+ *ebx = 0;
+ *ecx = count & 0xff;
+ *edx = cpu->apic_id;
+ return;
+ }
/*
* Find the No.(count + 1) topology level in avail_cpu_topo bitmap.
base-commit: cc329c491768b2d91eb0b0984f3baa0bf805776d
--
2.34.1