feat(cpuid): leaf 0x15 TSC / core-crystal ratio (patch 0026)
Real Intel CPUs enumerate leaf 0x15 (TSC/crystal ratio); QEMU returns 0. Fill it consistently with leaf 0x16 (TSC == base freq). Intel persona only. Module getters spoof_cpu_crystal_hz/tsc_num/tsc_den. Inert without a seed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
qemu-spoof: CPUID leaf 0x15 (TSC / core-crystal ratio)
|
||||
|
||||
Stock QEMU returns 0 for leaf 0x15; real Intel CPUs enumerate the TSC / nominal
|
||||
core-crystal clock ratio. Fill EAX(denominator)/EBX(numerator)/ECX(crystal Hz) from
|
||||
the module so TSC == the leaf-0x16 base frequency (24 MHz crystal * base_mhz / 24).
|
||||
Intel only; the getters return 0 for an AMD persona or when off, matching stock.
|
||||
(spoof.h include in target/i386 is added by 0013.)
|
||||
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||
index c6fd1dc..aa0dd73 100644
|
||||
--- a/target/i386/cpu.c
|
||||
+++ b/target/i386/cpu.c
|
||||
@@ -8811,6 +8811,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
}
|
||||
break;
|
||||
}
|
||||
+ case 0x15:
|
||||
+ /* qemu-spoof: TSC / nominal core-crystal ratio (stock QEMU returns 0).
|
||||
+ * The getters return 0 when off or for an AMD persona, matching stock. */
|
||||
+ *eax = (uint32_t)spoof_cpu_tsc_den(0);
|
||||
+ *ebx = (uint32_t)spoof_cpu_tsc_num(0);
|
||||
+ *ecx = (uint32_t)spoof_cpu_crystal_hz(0);
|
||||
+ *edx = 0;
|
||||
+ break;
|
||||
case 0x1C: /* Last Branch Records Information Leaf */
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
@@ -29,6 +29,12 @@ int spoof_cpu_bus_mhz(int def)
|
||||
{
|
||||
return spoof_on() ? 100 : def;
|
||||
}
|
||||
/* CPUID leaf 0x15 (TSC / nominal core-crystal ratio). Intel enumerates it; AMD does
|
||||
* not, so return the default for an AMD persona. Chosen so TSC == base frequency:
|
||||
* ECX(24 MHz) * EBX(base_mhz) / EAX(24) = base_mhz * 1e6 Hz, consistent with 0x16. */
|
||||
int spoof_cpu_crystal_hz(int def) { return (spoof_on() && !spoof_anchor_vendor()) ? 24000000 : def; }
|
||||
int spoof_cpu_tsc_num(int def) { return (spoof_on() && !spoof_anchor_vendor()) ? spoof_cpu_base_mhz(0) : def; }
|
||||
int spoof_cpu_tsc_den(int def) { return (spoof_on() && !spoof_anchor_vendor()) ? 24 : def; }
|
||||
/* Microcode revision, returned already positioned for the MSR (IA32_UCODE_REV
|
||||
* 0x8B): Intel reports the revision in bits 63:32, AMD the patch level in 31:0.
|
||||
* Stock QEMU/KVM defaults (Intel 0x1_00000000, AMD 0x01000065) follow the same
|
||||
|
||||
@@ -52,6 +52,9 @@ const char *spoof_kvm_signature(const char *def); /* 12 bytes; vendor-ancho
|
||||
int spoof_cpu_base_mhz(int def); /* CPUID leaf 0x16 base freq */
|
||||
int spoof_cpu_max_mhz(int def); /* CPUID leaf 0x16 max freq */
|
||||
int spoof_cpu_bus_mhz(int def); /* CPUID leaf 0x16 bus freq */
|
||||
int spoof_cpu_crystal_hz(int def); /* CPUID leaf 0x15 ECX (Intel core crystal) */
|
||||
int spoof_cpu_tsc_num(int def); /* leaf 0x15 EBX (TSC ratio numerator) */
|
||||
int spoof_cpu_tsc_den(int def); /* leaf 0x15 EAX (TSC ratio denominator) */
|
||||
uint64_t spoof_cpu_microcode(uint64_t def); /* IA32_UCODE_REV, vendor-positioned */
|
||||
|
||||
/* ---- PCI (spoof-pci.c) ---------------------------------------------------- */
|
||||
|
||||
Reference in New Issue
Block a user