[1/2] i386: kvm: Disable arch_capabilities if MSR can't be set
diff mbox series

Message ID 20190125220606.4864-2-ehabkost@redhat.com
State New
Headers show
  • i386: arch_capabilities fixes + migratability
Related show

Commit Message

Eduardo Habkost Jan. 25, 2019, 10:06 p.m. UTC
KVM has two bugs in the handling of MSR_IA32_ARCH_CAPABILITIES:

1) Linux commit commit 1eaafe91a0df ("kvm: x86: IA32_ARCH_CAPABILITIES
   is always supported") makes GET_SUPPORTED_CPUID return
   arch_capabilities even if running on SVM.  This makes "-cpu
   host,migratable=off" incorrectly expose arch_capabilities on CPUID on
   AMD hosts (where the MSR is not emulated by KVM).

   the MSR is not supported by the host CPU.  This makes QEMU not
   initialize the MSR properly at kvm_put_msrs() on those hosts.

Work around both bugs on the QEMU side, by checking if the MSR
was returned by KVM_GET_MSR_INDEX_LIST before returning the
feature flag on kvm_arch_get_supported_cpuid().

This has the unfortunate side effect of making arch_capabilities
unavailable on hosts without hardware support for the MSR until bug #2
is fixed on KVM, but I can't see another way to work around bug #1
without that side effect.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Jim Mattson <jmattson@google.com>
Cc: KarimAllah Ahmed <karahmed@amazon.de>
Cc: David Woodhouse <dwmw@amazon.co.uk>
Cc: Darren Kenny <darren.kenny@oracle.com>
 target/i386/kvm.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff mbox series

diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 9af4542fb8..4fa3e3806a 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -389,6 +389,15 @@  uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
         if (host_tsx_blacklisted()) {
             ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE);
+    } else if (function == 7 && index == 0 && reg == R_EDX) {
+        /*
+         * Linux incorrectly v4.17-v4.20 return ARCH_CAPABILITIES on SVM.
+         * We can detect the bug by checking if MSR_IA32_ARCH_CAPABILITIES is
+         * returned by KVM_GET_MSR_INDEX_LIST.
+         */
+        if (!has_msr_arch_capabs) {
+            ret &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES;
+        }
     } else if (function == 0x80000001 && reg == R_ECX) {
          * It's safe to enable TOPOEXT even if it's not returned by