From: Wanpeng Li <[email protected]>

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.

Cc: Paolo Bonzini <[email protected]>
Cc: Radim Krčmář <[email protected]>
Signed-off-by: Wanpeng Li <[email protected]>
---
 Documentation/virtual/kvm/msr.txt    | 5 +++--
 arch/x86/include/asm/kvm_host.h      | 1 +
 arch/x86/include/uapi/asm/kvm_para.h | 1 +
 arch/x86/kernel/kvm.c                | 1 +
 arch/x86/kvm/mmu.c                   | 2 +-
 arch/x86/kvm/x86.c                   | 5 +++--
 6 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/Documentation/virtual/kvm/msr.txt 
b/Documentation/virtual/kvm/msr.txt
index 0a9ea51..1ebecc1 100644
--- a/Documentation/virtual/kvm/msr.txt
+++ b/Documentation/virtual/kvm/msr.txt
@@ -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)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d30576a..2766b2c 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -646,6 +646,7 @@ struct kvm_vcpu_arch {
                u64 msr_val;
                u32 id;
                bool send_user_only;
+               bool delivery_as_pf_vmexit;
        } apf;
 
        /* OSVW MSRs (AMD only) */
diff --git a/arch/x86/include/uapi/asm/kvm_para.h 
b/arch/x86/include/uapi/asm/kvm_para.h
index cff0bb6..a965e5b 100644
--- a/arch/x86/include/uapi/asm/kvm_para.h
+++ b/arch/x86/include/uapi/asm/kvm_para.h
@@ -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
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 43e10d6..1e29a77 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -330,6 +330,7 @@ static void kvm_guest_cpu_init(void)
 #ifdef CONFIG_PREEMPT
                pa |= KVM_ASYNC_PF_SEND_ALWAYS;
 #endif
+               pa |= KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT;
                wrmsrl(MSR_KVM_ASYNC_PF_EN, pa | KVM_ASYNC_PF_ENABLED);
                __this_cpu_write(apf_reason.enabled, 1);
                printk(KERN_INFO"KVM setup async PF for cpu %d\n",
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index cb82259..c49aecd 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3704,7 +3704,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);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d7f1a49..74cb944 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2061,8 +2061,8 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, 
u64 data)
 {
        gpa_t gpa = data & ~0x3f;
 
-       /* Bits 2:5 are reserved, Should be zero */
-       if (data & 0x3c)
+       /* Bits 3:5 are reserved, Should be zero */
+       if (data & 0x38)
                return 1;
 
        vcpu->arch.apf.msr_val = data;
@@ -2078,6 +2078,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, 
u64 data)
                return 1;
 
        vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS);
+       vcpu->arch.apf.delivery_as_pf_vmexit = data & 
KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT;
        kvm_async_pf_wakeup_all(vcpu);
        return 0;
 }
-- 
2.7.4

Reply via email to