Skip to content

Commit 3edd683

Browse files
Mohammed Gamalbonzini
authored andcommitted
KVM: x86: Add a capability for GUEST_MAXPHYADDR < HOST_MAXPHYADDR support
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: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 8c4182b commit 3edd683

File tree

5 files changed

+31
-1
lines changed

5 files changed

+31
-1
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ struct kvm_arch_async_pf {
12631263
};
12641264

12651265
extern u64 __read_mostly host_efer;
1266-
1266+
extern bool __read_mostly allow_smaller_maxphyaddr;
12671267
extern struct kvm_x86_ops kvm_x86_ops;
12681268

12691269
#define __KVM_HAVE_ARCH_VM_ALLOC

arch/x86/kvm/svm/svm.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,21 @@ static __init int svm_hardware_setup(void)
924924

925925
svm_set_cpu_caps();
926926

927+
/*
928+
* It seems that on AMD processors PTE's accessed bit is
929+
* being set by the CPU hardware before the NPF vmexit.
930+
* This is not expected behaviour and our tests fail because
931+
* of it.
932+
* A workaround here is to disable support for
933+
* GUEST_MAXPHYADDR < HOST_MAXPHYADDR if NPT is enabled.
934+
* In this case userspace can know if there is support using
935+
* KVM_CAP_SMALLER_MAXPHYADDR extension and decide how to handle
936+
* it
937+
* If future AMD CPU models change the behaviour described above,
938+
* this variable can be changed accordingly
939+
*/
940+
allow_smaller_maxphyaddr = !npt_enabled;
941+
927942
return 0;
928943

929944
err:

arch/x86/kvm/vmx/vmx.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8309,6 +8309,13 @@ static int __init vmx_init(void)
83098309
#endif
83108310
vmx_check_vmcs12_offsets();
83118311

8312+
/*
8313+
* Intel processors don't have problems with
8314+
* GUEST_MAXPHYADDR < HOST_MAXPHYADDR so enable
8315+
* it for VMX by default
8316+
*/
8317+
allow_smaller_maxphyaddr = true;
8318+
83128319
return 0;
83138320
}
83148321
module_init(vmx_init);

arch/x86/kvm/x86.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ static struct kvm_shared_msrs __percpu *shared_msrs;
187187
u64 __read_mostly host_efer;
188188
EXPORT_SYMBOL_GPL(host_efer);
189189

190+
bool __read_mostly allow_smaller_maxphyaddr;
191+
EXPORT_SYMBOL_GPL(allow_smaller_maxphyaddr);
192+
190193
static u64 __read_mostly host_xss;
191194
u64 __read_mostly supported_xss;
192195
EXPORT_SYMBOL_GPL(supported_xss);
@@ -3574,6 +3577,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
35743577
case KVM_CAP_HYPERV_ENLIGHTENED_VMCS:
35753578
r = kvm_x86_ops.nested_ops->enable_evmcs != NULL;
35763579
break;
3580+
case KVM_CAP_SMALLER_MAXPHYADDR:
3581+
r = (int) allow_smaller_maxphyaddr;
3582+
break;
35773583
default:
35783584
break;
35793585
}

include/uapi/linux/kvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,8 @@ struct kvm_ppc_resize_hpt {
10331033
#define KVM_CAP_HALT_POLL 182
10341034
#define KVM_CAP_ASYNC_PF_INT 183
10351035
#define KVM_CAP_LAST_CPU 184
1036+
#define KVM_CAP_SMALLER_MAXPHYADDR 185
1037+
10361038

10371039
#ifdef KVM_CAP_IRQ_ROUTING
10381040

0 commit comments

Comments
 (0)