Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe2a3027 authored by Radim Krčmář's avatar Radim Krčmář Committed by Paolo Bonzini
Browse files

KVM: x86: fix backward migration with async_PF



Guests on new hypersiors might set KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT
bit when enabling async_PF, but this bit is reserved on old hypervisors,
which results in a failure upon migration.

To avoid breaking different cases, we are checking for CPUID feature bit
before enabling the feature and nothing else.

Fixes: 52a5c155 ("KVM: async_pf: Let guest support delivery of async_pf from guest mode")
Cc: <stable@vger.kernel.org>
Reviewed-by: default avatarWanpeng Li <wanpengli@tencent.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent f75e4924
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -58,6 +58,10 @@ KVM_FEATURE_PV_TLB_FLUSH || 9 || guest checks this feature bit
                                   ||       || before enabling paravirtualized
                                   ||       || before enabling paravirtualized
                                   ||       || tlb flush.
                                   ||       || tlb flush.
------------------------------------------------------------------------------
------------------------------------------------------------------------------
KVM_FEATURE_ASYNC_PF_VMEXIT        ||    10 || paravirtualized async PF VM exit
                                   ||       || can be enabled by setting bit 2
                                   ||       || when writing to msr 0x4b564d02
------------------------------------------------------------------------------
KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ||    24 || host will warn if no guest-side
KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ||    24 || host will warn if no guest-side
                                   ||       || per-cpu warps are expected in
                                   ||       || per-cpu warps are expected in
                                   ||       || kvmclock.
                                   ||       || kvmclock.
+2 −1
Original line number Original line Diff line number Diff line
@@ -170,7 +170,8 @@ MSR_KVM_ASYNC_PF_EN: 0x4b564d02
	when asynchronous page faults are enabled on the vcpu 0 when
	when asynchronous page faults are enabled on the vcpu 0 when
	disabled. Bit 1 is 1 if asynchronous page faults can be injected
	disabled. Bit 1 is 1 if asynchronous page faults can be injected
	when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
	when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
	are delivered to L1 as #PF vmexits.
	are delivered to L1 as #PF vmexits.  Bit 2 can be set only if
	KVM_FEATURE_ASYNC_PF_VMEXIT is present in CPUID.


	First 4 byte of 64 byte memory location will be written to by
	First 4 byte of 64 byte memory location will be written to by
	the hypervisor at the time of asynchronous page fault (APF)
	the hypervisor at the time of asynchronous page fault (APF)
+1 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
#define KVM_FEATURE_PV_EOI		6
#define KVM_FEATURE_PV_EOI		6
#define KVM_FEATURE_PV_UNHALT		7
#define KVM_FEATURE_PV_UNHALT		7
#define KVM_FEATURE_PV_TLB_FLUSH	9
#define KVM_FEATURE_PV_TLB_FLUSH	9
#define KVM_FEATURE_ASYNC_PF_VMEXIT	10


/* The last 8 bits are used to indicate how to interpret the flags field
/* The last 8 bits are used to indicate how to interpret the flags field
 * in pvclock structure. If no bits are set, all flags are ignored.
 * in pvclock structure. If no bits are set, all flags are ignored.
+4 −4
Original line number Original line Diff line number Diff line
@@ -341,9 +341,9 @@ static void kvm_guest_cpu_init(void)
#endif
#endif
		pa |= KVM_ASYNC_PF_ENABLED;
		pa |= KVM_ASYNC_PF_ENABLED;


		/* Async page fault support for L1 hypervisor is optional */
		if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_VMEXIT))
		if (wrmsr_safe(MSR_KVM_ASYNC_PF_EN,
			pa |= KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT;
			(pa | KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT) & 0xffffffff, pa >> 32) < 0)

		wrmsrl(MSR_KVM_ASYNC_PF_EN, pa);
		wrmsrl(MSR_KVM_ASYNC_PF_EN, pa);
		__this_cpu_write(apf_reason.enabled, 1);
		__this_cpu_write(apf_reason.enabled, 1);
		printk(KERN_INFO"KVM setup async PF for cpu %d\n",
		printk(KERN_INFO"KVM setup async PF for cpu %d\n",
+2 −1
Original line number Original line Diff line number Diff line
@@ -607,7 +607,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
			     (1 << KVM_FEATURE_PV_EOI) |
			     (1 << KVM_FEATURE_PV_EOI) |
			     (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
			     (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
			     (1 << KVM_FEATURE_PV_UNHALT) |
			     (1 << KVM_FEATURE_PV_UNHALT) |
			     (1 << KVM_FEATURE_PV_TLB_FLUSH);
			     (1 << KVM_FEATURE_PV_TLB_FLUSH) |
			     (1 << KVM_FEATURE_ASYNC_PF_VMEXIT);


		if (sched_info_on())
		if (sched_info_on())
			entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
			entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);