Jelajahi Sumber

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.
Idan Horowitz 3 tahun lalu
induk
melakukan
1aad64fbe4
2 mengubah file dengan 27 tambahan dan 0 penghapusan
  1. 3 0
      Kernel/Arch/x86/Processor.h
  2. 24 0
      Kernel/Arch/x86/common/Processor.cpp

+ 3 - 0
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;

+ 24 - 0
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();