On AMD machines with SEV/SMD the physical address space needs to be reduced by a number of bits. Linux does this correctly and shows this information in /proc/cpuinfo. CPUID set by qemu however reports too big physical addresses i.e. 48 bit instead of 43.
This patch has been tested on both Intel and AMD. Signed-off-by: Jörg Thalheim <jo...@thalheim.io> --- target/i386/host-cpu.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c index 4ea9e354ea..0fb98ca566 100644 --- a/target/i386/host-cpu.c +++ b/target/i386/host-cpu.c @@ -13,22 +13,39 @@ #include "qapi/error.h" #include "sysemu/sysemu.h" +static uint32_t sme_sev_bits(void) { + uint32_t eax, ebx; + // get AMD Encrypted Memory Capabilities information according to AMD doc 24594—Rev. 3.32 + host_cpuid(0x8000001f, 0, &eax, &ebx, NULL, NULL); + // bits: + // 0:1 SME + // 1:2 SEV + // ... + if (eax & 1 || eax & 2) { + // bits: + // 11:6 PhysAddrReduction + return (ebx >> 6) & 0x3f; + } else { + return 0; + } +} + /* Note: Only safe for use on x86(-64) hosts */ static uint32_t host_cpu_phys_bits(void) { - uint32_t eax; + uint32_t eax, ebx; uint32_t host_phys_bits; host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL); if (eax >= 0x80000008) { - host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL); + host_cpuid(0x80000008, 0, &eax, &ebx, NULL, NULL); /* * Note: According to AMD doc 25481 rev 2.34 they have a field * at 23:16 that can specify a maximum physical address bits for * the guest that can override this value; but I've not seen * anything with that set. */ - host_phys_bits = eax & 0xff; + host_phys_bits = (eax & 0xff) - sme_sev_bits(); } else { /* * It's an odd 64 bit machine that doesn't have the leaf for -- 2.32.0