From 1aad64fbe4d96ce3d3a7bc57ea5d59ac98f58bcf Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Fri, 11 Feb 2022 02:45:34 +0200 Subject: [PATCH] Kernel: Workaround QEMU hypervisor.framework CPUID max leaf bug This works around issue #10382 until it is fixed on QEMU's side. Patch from Anonymous. --- Kernel/Arch/x86/Processor.h | 3 +++ Kernel/Arch/x86/common/Processor.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Kernel/Arch/x86/Processor.h b/Kernel/Arch/x86/Processor.h index 7b9d430e48..c2e620d8c2 100644 --- a/Kernel/Arch/x86/Processor.h +++ b/Kernel/Arch/x86/Processor.h @@ -84,6 +84,9 @@ class Processor { static Atomic g_total_processors; u8 m_physical_address_bit_width; u8 m_virtual_address_bit_width; +#if ARCH(X86_64) + bool m_has_qemu_hvf_quirk; +#endif ProcessorInfo* m_info; Thread* m_current_thread; diff --git a/Kernel/Arch/x86/common/Processor.cpp b/Kernel/Arch/x86/common/Processor.cpp index d0c0217ba7..357e7a90e3 100644 --- a/Kernel/Arch/x86/common/Processor.cpp +++ b/Kernel/Arch/x86/common/Processor.cpp @@ -143,6 +143,10 @@ UNMAP_AFTER_INIT void Processor::cpu_detect() } } +#if ARCH(X86_64) + m_has_qemu_hvf_quirk = false; +#endif + if (max_extended_leaf >= 0x80000008) { // CPUID.80000008H:EAX[7:0] reports the physical-address width supported by the processor. CPUID cpuid(0x80000008); @@ -154,6 +158,22 @@ UNMAP_AFTER_INIT void Processor::cpu_detect() m_physical_address_bit_width = has_feature(CPUFeature::PAE) ? 36 : 32; // Processors that do not support CPUID function 80000008H, support a linear-address width of 32. m_virtual_address_bit_width = 32; +#if ARCH(X86_64) + // Workaround QEMU hypervisor.framework bug + // https://gitlab.com/qemu-project/qemu/-/issues/664 + // + // We detect this as follows: + // * We're in a hypervisor + // * hypervisor_leaf_range is null under Hypervisor.framework + // * m_physical_address_bit_width is 36 bits + if (has_feature(CPUFeature::HYPERVISOR)) { + CPUID hypervisor_leaf_range(0x40000000); + if (!hypervisor_leaf_range.ebx() && m_physical_address_bit_width == 36) { + m_has_qemu_hvf_quirk = true; + m_virtual_address_bit_width = 48; + } + } +#endif } CPUID extended_features(0x7); @@ -389,6 +409,10 @@ UNMAP_AFTER_INIT void Processor::initialize(u32 cpu) dmesgln("CPU[{}]: No RDRAND support detected, randomness will be poor", current_id()); dmesgln("CPU[{}]: Physical address bit width: {}", current_id(), m_physical_address_bit_width); dmesgln("CPU[{}]: Virtual address bit width: {}", current_id(), m_virtual_address_bit_width); +#if ARCH(X86_64) + if (m_has_qemu_hvf_quirk) + dmesgln("CPU[{}]: Applied correction for QEMU Hypervisor.framework quirk", current_id()); +#endif if (cpu == 0) idt_init();