]> Git Repo - linux.git/commitdiff
KVM: x86: Add a capability for GUEST_MAXPHYADDR < HOST_MAXPHYADDR support
authorMohammed Gamal <[email protected]>
Fri, 10 Jul 2020 15:48:11 +0000 (17:48 +0200)
committerPaolo Bonzini <[email protected]>
Fri, 10 Jul 2020 21:01:53 +0000 (17:01 -0400)
This patch adds a new capability KVM_CAP_SMALLER_MAXPHYADDR which
allows userspace to query if the underlying architecture would
support GUEST_MAXPHYADDR < HOST_MAXPHYADDR and hence act accordingly
(e.g. qemu can decide if it should warn for -cpu ..,phys-bits=X)

The complications in this patch are due to unexpected (but documented)
behaviour we see with NPF vmexit handling in AMD processor.  If
SVM is modified to add guest physical address checks in the NPF
and guest #PF paths, we see the followning error multiple times in
the 'access' test in kvm-unit-tests:

            test pte.p pte.36 pde.p: FAIL: pte 2000021 expected 2000001
            Dump mapping: address: 0x123400000000
            ------L4: 24c3027
            ------L3: 24c4027
            ------L2: 24c5021
            ------L1: 1002000021

This is because the PTE's accessed bit is set by the CPU hardware before
the NPF vmexit. This is handled completely by hardware and cannot be fixed
in software.

Therefore, availability of the new capability depends on a boolean variable
allow_smaller_maxphyaddr which is set individually by VMX and SVM init
routines. On VMX it's always set to true, on SVM it's only set to true
when NPT is not enabled.

CC: Tom Lendacky <[email protected]>
CC: Babu Moger <[email protected]>
Signed-off-by: Mohammed Gamal <[email protected]>
Message-Id: <20200710154811[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
include/uapi/linux/kvm.h

index 1df95f10c9037a671d03ebfdcaefdcafd06fd4d7..1bab87a444d781ffc66e494a13cf1cdacc66d90f 100644 (file)
@@ -1263,7 +1263,7 @@ struct kvm_arch_async_pf {
 };
 
 extern u64 __read_mostly host_efer;
-
+extern bool __read_mostly allow_smaller_maxphyaddr;
 extern struct kvm_x86_ops kvm_x86_ops;
 
 #define __KVM_HAVE_ARCH_VM_ALLOC
index 2371b1e40f3922726b170407cd91b504051800c5..783330d0e7b889678b6a86e933b4d746e6539f39 100644 (file)
@@ -924,6 +924,21 @@ static __init int svm_hardware_setup(void)
 
        svm_set_cpu_caps();
 
+       /*
+        * It seems that on AMD processors PTE's accessed bit is
+        * being set by the CPU hardware before the NPF vmexit.
+        * This is not expected behaviour and our tests fail because
+        * of it.
+        * A workaround here is to disable support for
+        * GUEST_MAXPHYADDR < HOST_MAXPHYADDR if NPT is enabled.
+        * In this case userspace can know if there is support using
+        * KVM_CAP_SMALLER_MAXPHYADDR extension and decide how to handle
+        * it
+        * If future AMD CPU models change the behaviour described above,
+        * this variable can be changed accordingly
+        */
+       allow_smaller_maxphyaddr = !npt_enabled;
+
        return 0;
 
 err:
index 962a78c7dde5818246db943da24fc755a189e4e5..1bb59ae5016dc1e9d6ed8bfdee87c3ab64c29d8d 100644 (file)
@@ -8309,6 +8309,13 @@ static int __init vmx_init(void)
 #endif
        vmx_check_vmcs12_offsets();
 
+       /*
+        * Intel processors don't have problems with
+        * GUEST_MAXPHYADDR < HOST_MAXPHYADDR so enable
+        * it for VMX by default
+        */
+       allow_smaller_maxphyaddr = true;
+
        return 0;
 }
 module_init(vmx_init);
index 35abe69aad2858f8ecbc80fbc168b7f7cffdb836..95ef629228691e7bc132245b2a8931b1ed7b52fc 100644 (file)
@@ -187,6 +187,9 @@ static struct kvm_shared_msrs __percpu *shared_msrs;
 u64 __read_mostly host_efer;
 EXPORT_SYMBOL_GPL(host_efer);
 
+bool __read_mostly allow_smaller_maxphyaddr;
+EXPORT_SYMBOL_GPL(allow_smaller_maxphyaddr);
+
 static u64 __read_mostly host_xss;
 u64 __read_mostly supported_xss;
 EXPORT_SYMBOL_GPL(supported_xss);
@@ -3574,6 +3577,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_HYPERV_ENLIGHTENED_VMCS:
                r = kvm_x86_ops.nested_ops->enable_evmcs != NULL;
                break;
+       case KVM_CAP_SMALLER_MAXPHYADDR:
+               r = (int) allow_smaller_maxphyaddr;
+               break;
        default:
                break;
        }
index ff9b335620d08366b3314bad1acc6beb19734b3a..2c73dcfb3dbb02fd3e7a68cfc6caa57b493a31d2 100644 (file)
@@ -1033,6 +1033,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HALT_POLL 182
 #define KVM_CAP_ASYNC_PF_INT 183
 #define KVM_CAP_LAST_CPU 184
+#define KVM_CAP_SMALLER_MAXPHYADDR 185
+
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
This page took 0.094936 seconds and 4 git commands to generate.