summaryrefslogtreecommitdiff
path: root/Kernel/Arch/x86
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2022-02-11 02:45:34 +0200
committerIdan Horowitz <idan.horowitz@gmail.com>2022-02-11 02:45:34 +0200
commit1aad64fbe4d96ce3d3a7bc57ea5d59ac98f58bcf (patch)
tree3ec2d7bd72634fecf8fff9314ec5a5b33f2488cc /Kernel/Arch/x86
parentb683e8ab77ce05085272239dcd177bfe1d76f4c6 (diff)
downloadserenity-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.h3
-rw-r--r--Kernel/Arch/x86/common/Processor.cpp24
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();