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

Commit 52a5c155 authored by Wanpeng Li's avatar Wanpeng Li Committed by Radim Krčmář
Browse files

KVM: async_pf: Let guest support delivery of async_pf from guest mode



Adds another flag bit (bit 2) to MSR_KVM_ASYNC_PF_EN. If bit 2 is 1,
async page faults are delivered to L1 as #PF vmexits; if bit 2 is 0,
kvm_can_do_async_pf returns 0 if in guest mode.

This is similar to what svm.c wanted to do all along, but it is only
enabled for Linux as L1 hypervisor.  Foreign hypervisors must never
receive async page faults as vmexits, because they'd probably be very
confused about that.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Signed-off-by: default avatarWanpeng Li <wanpeng.li@hotmail.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent adfe20fb
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -166,10 +166,11 @@ MSR_KVM_SYSTEM_TIME: 0x12
MSR_KVM_ASYNC_PF_EN: 0x4b564d02
	data: Bits 63-6 hold 64-byte aligned physical address of a
	64 byte memory area which must be in guest RAM and must be
	zeroed. Bits 5-2 are reserved and should be zero. Bit 0 is 1
	zeroed. Bits 5-3 are reserved and should be zero. Bit 0 is 1
	when asynchronous page faults are enabled on the vcpu 0 when
	disabled. Bit 1 is 1 if asynchronous page faults can be injected
	when vcpu is in cpl == 0.
	when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
	are delivered to L1 as #PF vmexits.

	First 4 byte of 64 byte memory location will be written to by
	the hypervisor at the time of asynchronous page fault (APF)
+1 −0
Original line number Diff line number Diff line
@@ -653,6 +653,7 @@ struct kvm_vcpu_arch {
		bool send_user_only;
		u32 host_apf_reason;
		unsigned long nested_apf_token;
		bool delivery_as_pf_vmexit;
	} apf;

	/* OSVW MSRs (AMD only) */
+1 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ struct kvm_clock_pairing {

#define KVM_ASYNC_PF_ENABLED			(1 << 0)
#define KVM_ASYNC_PF_SEND_ALWAYS		(1 << 1)
#define KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT	(1 << 2)

/* Operations for KVM_HC_MMU_OP */
#define KVM_MMU_OP_WRITE_PTE            1
+6 −1
Original line number Diff line number Diff line
@@ -330,7 +330,12 @@ static void kvm_guest_cpu_init(void)
#ifdef CONFIG_PREEMPT
		pa |= KVM_ASYNC_PF_SEND_ALWAYS;
#endif
		wrmsrl(MSR_KVM_ASYNC_PF_EN, pa | KVM_ASYNC_PF_ENABLED);
		pa |= KVM_ASYNC_PF_ENABLED;

		/* Async page fault support for L1 hypervisor is optional */
		if (wrmsr_safe(MSR_KVM_ASYNC_PF_EN,
			(pa | KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT) & 0xffffffff, pa >> 32) < 0)
			wrmsrl(MSR_KVM_ASYNC_PF_EN, pa);
		__this_cpu_write(apf_reason.enabled, 1);
		printk(KERN_INFO"KVM setup async PF for cpu %d\n",
		       smp_processor_id());
+1 −1
Original line number Diff line number Diff line
@@ -3749,7 +3749,7 @@ bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu)
		     kvm_event_needs_reinjection(vcpu)))
		return false;

	if (is_guest_mode(vcpu))
	if (!vcpu->arch.apf.delivery_as_pf_vmexit && is_guest_mode(vcpu))
		return false;

	return kvm_x86_ops->interrupt_allowed(vcpu);
Loading