diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2022-02-11 02:45:34 +0200 |
---|---|---|
committer | Idan Horowitz <idan.horowitz@gmail.com> | 2022-02-11 02:45:34 +0200 |
commit | 1aad64fbe4d96ce3d3a7bc57ea5d59ac98f58bcf (patch) | |
tree | 3ec2d7bd72634fecf8fff9314ec5a5b33f2488cc /Kernel/Arch/x86 | |
parent | b683e8ab77ce05085272239dcd177bfe1d76f4c6 (diff) | |
download | serenity-1aad64fbe4d96ce3d3a7bc57ea5d59ac98f58bcf.zip |
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.
Diffstat (limited to 'Kernel/Arch/x86')
-rw-r--r-- | Kernel/Arch/x86/Processor.h | 3 | ||||
-rw-r--r-- | Kernel/Arch/x86/common/Processor.cpp | 24 |
2 files changed, 27 insertions, 0 deletions
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<u32> 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(); |