Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-10 Thread Gleb Natapov
On Sat, Oct 09, 2010 at 08:42:00PM +0200, Avi Kivity wrote:
  On 10/07/2010 07:21 PM, Gleb Natapov wrote:
 On Thu, Oct 07, 2010 at 02:29:07PM +0200, Avi Kivity wrote:
On 10/04/2010 05:56 PM, Gleb Natapov wrote:
   When page is swapped in it is mapped into guest memory only after guest
   tries to access it again and generate another fault. To save this fault
   we can map it immediately since we know that guest is going to access
   the page. Do it only when tdp is enabled for now. Shadow paging case is
   more complicated. CR[034] and EFER registers should be switched before
   doing mapping and then switched back.
 
   With non-pv apf, I don't think we can do shadow paging.  The guest
 Yes, with non-pv this trick will not work without tdp. I haven't even
 considered it for that case.
 
 
 What about nnpt?  The same issues exist.
 
I am not sure how nntp works. What is the problem there? In case of tdp
prefault instantiates page in direct_map, how nntp interfere with that?

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-09 Thread Avi Kivity

 On 10/07/2010 07:21 PM, Gleb Natapov wrote:

On Thu, Oct 07, 2010 at 02:29:07PM +0200, Avi Kivity wrote:
   On 10/04/2010 05:56 PM, Gleb Natapov wrote:
  When page is swapped in it is mapped into guest memory only after guest
  tries to access it again and generate another fault. To save this fault
  we can map it immediately since we know that guest is going to access
  the page. Do it only when tdp is enabled for now. Shadow paging case is
  more complicated. CR[034] and EFER registers should be switched before
  doing mapping and then switched back.

  With non-pv apf, I don't think we can do shadow paging.  The guest
Yes, with non-pv this trick will not work without tdp. I haven't even
considered it for that case.



What about nnpt?  The same issues exist.

--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-08 Thread Marcelo Tosatti
On Thu, Oct 07, 2010 at 08:44:57PM +0200, Gleb Natapov wrote:
 On Wed, Oct 06, 2010 at 11:20:50AM -0300, Marcelo Tosatti wrote:
  On Wed, Oct 06, 2010 at 01:07:04PM +0200, Gleb Natapov wrote:
Can't you set a bit in vcpu-requests instead, and handle it in out:
at the end of vcpu_enter_guest? 

To have a single entry point for pagefaults, after vmexit handling.
   Jumping to out: will skip vmexit handling anyway, so we will not reuse
   same call site anyway. I don't see yet why the way you propose will have
   an advantage.
  
  What i meant was to call pagefault handler after vmexit handling.
  
  Because the way it is in your patch now, with pre pagefault on entry,
  one has to make an effort to verify ordering wrt other events on entry
  processing.
  
 What events do you have in mind?

TLB flushing, event injection, etc.

  With pre pagefault after vmexit, its more natural.
  
 I do not see non-ugly way to pass information that is needed to perform
 the prefault to the place you want me to put it. We can skip guest entry
 in case prefault was done which will have the same effect as your
 proposal, but I want to have a good reason to do so since otherwise we
 will just do more work for nothing on guest entry.

The reason is that it becomes similar to normal pagefault handling. I
don't have a specific bug to give you as example.

 
  Does that make sense?
 
 --
   Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-07 Thread Avi Kivity

 On 10/04/2010 05:56 PM, Gleb Natapov wrote:

When page is swapped in it is mapped into guest memory only after guest
tries to access it again and generate another fault. To save this fault
we can map it immediately since we know that guest is going to access
the page. Do it only when tdp is enabled for now. Shadow paging case is
more complicated. CR[034] and EFER registers should be switched before
doing mapping and then switched back.


With non-pv apf, I don't think we can do shadow paging.  The guest isn't 
aware of the apf, so as far as it is concerned it is allowed to kill the 
process and replace it with something else:


  guest process x: apf
  kvm: timer intr
  guest kernel: context switch
  very fast guest admin: pkill -9 x
  guest kernel: destroy x's cr3
  guest kernel: reuse x's cr3 for new process y
  kvm: retry fault, instantiating x's page in y's page table

Even with tdp, we have the same case for nnpt (just s/kernel/hypervisor/ 
and s/process/guest/).  What we really need is to only instantiate the 
page for direct maps, which are independent of the guest.


Could be done like this:

- at apf time, walk shadow mmu
- if !sp-role.direct, abort
- take reference to sp
- on apf completion, instantiate spte in sp

--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-07 Thread Gleb Natapov
On Thu, Oct 07, 2010 at 02:29:07PM +0200, Avi Kivity wrote:
  On 10/04/2010 05:56 PM, Gleb Natapov wrote:
 When page is swapped in it is mapped into guest memory only after guest
 tries to access it again and generate another fault. To save this fault
 we can map it immediately since we know that guest is going to access
 the page. Do it only when tdp is enabled for now. Shadow paging case is
 more complicated. CR[034] and EFER registers should be switched before
 doing mapping and then switched back.
 
 With non-pv apf, I don't think we can do shadow paging.  The guest
Yes, with non-pv this trick will not work without tdp. I haven't even
considered it for that case.

 isn't aware of the apf, so as far as it is concerned it is allowed
 to kill the process and replace it with something else:
 
   guest process x: apf
   kvm: timer intr
   guest kernel: context switch
   very fast guest admin: pkill -9 x
   guest kernel: destroy x's cr3
   guest kernel: reuse x's cr3 for new process y
   kvm: retry fault, instantiating x's page in y's page table
 
 Even with tdp, we have the same case for nnpt (just
 s/kernel/hypervisor/ and s/process/guest/).  What we really need is
 to only instantiate the page for direct maps, which are independent
 of the guest.
 
 Could be done like this:
 
 - at apf time, walk shadow mmu
 - if !sp-role.direct, abort
 - take reference to sp
 - on apf completion, instantiate spte in sp
 
 -- 
 I have a truly marvellous patch that fixes the bug which this
 signature is too narrow to contain.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-07 Thread Gleb Natapov
On Wed, Oct 06, 2010 at 11:20:50AM -0300, Marcelo Tosatti wrote:
 On Wed, Oct 06, 2010 at 01:07:04PM +0200, Gleb Natapov wrote:
   Can't you set a bit in vcpu-requests instead, and handle it in out:
   at the end of vcpu_enter_guest? 
   
   To have a single entry point for pagefaults, after vmexit handling.
  Jumping to out: will skip vmexit handling anyway, so we will not reuse
  same call site anyway. I don't see yet why the way you propose will have
  an advantage.
 
 What i meant was to call pagefault handler after vmexit handling.
 
 Because the way it is in your patch now, with pre pagefault on entry,
 one has to make an effort to verify ordering wrt other events on entry
 processing.
 
What events do you have in mind?

 With pre pagefault after vmexit, its more natural.
 
I do not see non-ugly way to pass information that is needed to perform
the prefault to the place you want me to put it. We can skip guest entry
in case prefault was done which will have the same effect as your
proposal, but I want to have a good reason to do so since otherwise we
will just do more work for nothing on guest entry.

 Does that make sense?

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-06 Thread Gleb Natapov
On Tue, Oct 05, 2010 at 12:54:09PM -0300, Marcelo Tosatti wrote:
 On Mon, Oct 04, 2010 at 05:56:25PM +0200, Gleb Natapov wrote:
  When page is swapped in it is mapped into guest memory only after guest
  tries to access it again and generate another fault. To save this fault
  we can map it immediately since we know that guest is going to access
  the page. Do it only when tdp is enabled for now. Shadow paging case is
  more complicated. CR[034] and EFER registers should be switched before
  doing mapping and then switched back.
  
  Acked-by: Rik van Riel r...@redhat.com
  Signed-off-by: Gleb Natapov g...@redhat.com
  ---
   arch/x86/include/asm/kvm_host.h |4 +++-
   arch/x86/kvm/mmu.c  |   16 
   arch/x86/kvm/paging_tmpl.h  |6 +++---
   arch/x86/kvm/x86.c  |7 +++
   virt/kvm/async_pf.c |2 ++
   5 files changed, 23 insertions(+), 12 deletions(-)
  
  diff --git a/arch/x86/include/asm/kvm_host.h 
  b/arch/x86/include/asm/kvm_host.h
  index 5f154d3..b9f263e 100644
  --- a/arch/x86/include/asm/kvm_host.h
  +++ b/arch/x86/include/asm/kvm_host.h
  @@ -240,7 +240,7 @@ struct kvm_mmu {
  void (*new_cr3)(struct kvm_vcpu *vcpu);
  void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
  unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
  -   int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
  +   int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err, bool 
  no_apf);
  void (*inject_page_fault)(struct kvm_vcpu *vcpu);
  void (*free)(struct kvm_vcpu *vcpu);
  gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
  @@ -838,6 +838,8 @@ void kvm_arch_async_page_not_present(struct kvm_vcpu 
  *vcpu,
   struct kvm_async_pf *work);
   void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
   struct kvm_async_pf *work);
  +void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
  +  struct kvm_async_pf *work);
   extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
   
   #endif /* _ASM_X86_KVM_HOST_H */
  diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
  index 4d49b5e..d85fda8 100644
  --- a/arch/x86/kvm/mmu.c
  +++ b/arch/x86/kvm/mmu.c
  @@ -2558,7 +2558,7 @@ static gpa_t nonpaging_gva_to_gpa_nested(struct 
  kvm_vcpu *vcpu, gva_t vaddr,
   }
   
   static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
  -   u32 error_code)
  +   u32 error_code, bool no_apf)
   {
  gfn_t gfn;
  int r;
  @@ -2594,8 +2594,8 @@ static bool can_do_async_pf(struct kvm_vcpu *vcpu)
  return kvm_x86_ops-interrupt_allowed(vcpu);
   }
   
  -static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva,
  -pfn_t *pfn)
  +static bool try_async_pf(struct kvm_vcpu *vcpu, bool no_apf, gfn_t gfn,
  +gva_t gva, pfn_t *pfn)
   {
  bool async;
   
  @@ -2606,7 +2606,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t 
  gfn, gva_t gva,
   
  put_page(pfn_to_page(*pfn));
   
  -   if (can_do_async_pf(vcpu)) {
  +   if (!no_apf  can_do_async_pf(vcpu)) {
  trace_kvm_try_async_get_page(async, *pfn);
  if (kvm_find_async_pf_gfn(vcpu, gfn)) {
  vcpu-async_pf.work = kvm_double_apf;
  @@ -2620,8 +2620,8 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t 
  gfn, gva_t gva,
  return false;
   }
   
  -static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
  -   u32 error_code)
  +static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
  + bool no_apf)
   {
  pfn_t pfn;
  int r;
  @@ -2643,7 +2643,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, 
  gva_t gpa,
  mmu_seq = vcpu-kvm-mmu_notifier_seq;
  smp_rmb();
   
  -   if (try_async_pf(vcpu, gfn, gpa, pfn))
  +   if (try_async_pf(vcpu, no_apf, gfn, gpa, pfn))
  return 0;
   
  /* mmio */
  @@ -3306,7 +3306,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t 
  cr2, u32 error_code)
  int r;
  enum emulation_result er;
   
  -   r = vcpu-arch.mmu.page_fault(vcpu, cr2, error_code);
  +   r = vcpu-arch.mmu.page_fault(vcpu, cr2, error_code, false);
  if (r  0)
  goto out;
   
  diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
  index 8154353..9ad90f8 100644
  --- a/arch/x86/kvm/paging_tmpl.h
  +++ b/arch/x86/kvm/paging_tmpl.h
  @@ -530,8 +530,8 @@ out_gpte_changed:
*  Returns: 1 if we need to emulate the instruction, 0 otherwise, or
*   a negative value on error.
*/
  -static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
  -  u32 error_code)
  +static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 
  error_code,
  +bool no_apf)
   {
  int write_fault = 

Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-06 Thread Marcelo Tosatti
On Wed, Oct 06, 2010 at 01:07:04PM +0200, Gleb Natapov wrote:
  Can't you set a bit in vcpu-requests instead, and handle it in out:
  at the end of vcpu_enter_guest? 
  
  To have a single entry point for pagefaults, after vmexit handling.
 Jumping to out: will skip vmexit handling anyway, so we will not reuse
 same call site anyway. I don't see yet why the way you propose will have
 an advantage.

What i meant was to call pagefault handler after vmexit handling.

Because the way it is in your patch now, with pre pagefault on entry,
one has to make an effort to verify ordering wrt other events on entry
processing.

With pre pagefault after vmexit, its more natural.

Does that make sense?

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 03/12] Retry fault before vmentry

2010-10-05 Thread Marcelo Tosatti
On Mon, Oct 04, 2010 at 05:56:25PM +0200, Gleb Natapov wrote:
 When page is swapped in it is mapped into guest memory only after guest
 tries to access it again and generate another fault. To save this fault
 we can map it immediately since we know that guest is going to access
 the page. Do it only when tdp is enabled for now. Shadow paging case is
 more complicated. CR[034] and EFER registers should be switched before
 doing mapping and then switched back.
 
 Acked-by: Rik van Riel r...@redhat.com
 Signed-off-by: Gleb Natapov g...@redhat.com
 ---
  arch/x86/include/asm/kvm_host.h |4 +++-
  arch/x86/kvm/mmu.c  |   16 
  arch/x86/kvm/paging_tmpl.h  |6 +++---
  arch/x86/kvm/x86.c  |7 +++
  virt/kvm/async_pf.c |2 ++
  5 files changed, 23 insertions(+), 12 deletions(-)
 
 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
 index 5f154d3..b9f263e 100644
 --- a/arch/x86/include/asm/kvm_host.h
 +++ b/arch/x86/include/asm/kvm_host.h
 @@ -240,7 +240,7 @@ struct kvm_mmu {
   void (*new_cr3)(struct kvm_vcpu *vcpu);
   void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
   unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
 - int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
 + int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err, bool 
 no_apf);
   void (*inject_page_fault)(struct kvm_vcpu *vcpu);
   void (*free)(struct kvm_vcpu *vcpu);
   gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
 @@ -838,6 +838,8 @@ void kvm_arch_async_page_not_present(struct kvm_vcpu 
 *vcpu,
struct kvm_async_pf *work);
  void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
struct kvm_async_pf *work);
 +void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
 +struct kvm_async_pf *work);
  extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
  
  #endif /* _ASM_X86_KVM_HOST_H */
 diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
 index 4d49b5e..d85fda8 100644
 --- a/arch/x86/kvm/mmu.c
 +++ b/arch/x86/kvm/mmu.c
 @@ -2558,7 +2558,7 @@ static gpa_t nonpaging_gva_to_gpa_nested(struct 
 kvm_vcpu *vcpu, gva_t vaddr,
  }
  
  static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
 - u32 error_code)
 + u32 error_code, bool no_apf)
  {
   gfn_t gfn;
   int r;
 @@ -2594,8 +2594,8 @@ static bool can_do_async_pf(struct kvm_vcpu *vcpu)
   return kvm_x86_ops-interrupt_allowed(vcpu);
  }
  
 -static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva,
 -  pfn_t *pfn)
 +static bool try_async_pf(struct kvm_vcpu *vcpu, bool no_apf, gfn_t gfn,
 +  gva_t gva, pfn_t *pfn)
  {
   bool async;
  
 @@ -2606,7 +2606,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t 
 gfn, gva_t gva,
  
   put_page(pfn_to_page(*pfn));
  
 - if (can_do_async_pf(vcpu)) {
 + if (!no_apf  can_do_async_pf(vcpu)) {
   trace_kvm_try_async_get_page(async, *pfn);
   if (kvm_find_async_pf_gfn(vcpu, gfn)) {
   vcpu-async_pf.work = kvm_double_apf;
 @@ -2620,8 +2620,8 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t 
 gfn, gva_t gva,
   return false;
  }
  
 -static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
 - u32 error_code)
 +static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
 +   bool no_apf)
  {
   pfn_t pfn;
   int r;
 @@ -2643,7 +2643,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t 
 gpa,
   mmu_seq = vcpu-kvm-mmu_notifier_seq;
   smp_rmb();
  
 - if (try_async_pf(vcpu, gfn, gpa, pfn))
 + if (try_async_pf(vcpu, no_apf, gfn, gpa, pfn))
   return 0;
  
   /* mmio */
 @@ -3306,7 +3306,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t 
 cr2, u32 error_code)
   int r;
   enum emulation_result er;
  
 - r = vcpu-arch.mmu.page_fault(vcpu, cr2, error_code);
 + r = vcpu-arch.mmu.page_fault(vcpu, cr2, error_code, false);
   if (r  0)
   goto out;
  
 diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
 index 8154353..9ad90f8 100644
 --- a/arch/x86/kvm/paging_tmpl.h
 +++ b/arch/x86/kvm/paging_tmpl.h
 @@ -530,8 +530,8 @@ out_gpte_changed:
   *  Returns: 1 if we need to emulate the instruction, 0 otherwise, or
   *   a negative value on error.
   */
 -static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
 -u32 error_code)
 +static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 
 error_code,
 +  bool no_apf)
  {
   int write_fault = error_code  PFERR_WRITE_MASK;
   int user_fault = error_code  PFERR_USER_MASK;
 @@ -574,7 +574,7 

[PATCH v6 03/12] Retry fault before vmentry

2010-10-04 Thread Gleb Natapov
When page is swapped in it is mapped into guest memory only after guest
tries to access it again and generate another fault. To save this fault
we can map it immediately since we know that guest is going to access
the page. Do it only when tdp is enabled for now. Shadow paging case is
more complicated. CR[034] and EFER registers should be switched before
doing mapping and then switched back.

Acked-by: Rik van Riel r...@redhat.com
Signed-off-by: Gleb Natapov g...@redhat.com
---
 arch/x86/include/asm/kvm_host.h |4 +++-
 arch/x86/kvm/mmu.c  |   16 
 arch/x86/kvm/paging_tmpl.h  |6 +++---
 arch/x86/kvm/x86.c  |7 +++
 virt/kvm/async_pf.c |2 ++
 5 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 5f154d3..b9f263e 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -240,7 +240,7 @@ struct kvm_mmu {
void (*new_cr3)(struct kvm_vcpu *vcpu);
void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
-   int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
+   int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err, bool 
no_apf);
void (*inject_page_fault)(struct kvm_vcpu *vcpu);
void (*free)(struct kvm_vcpu *vcpu);
gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
@@ -838,6 +838,8 @@ void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
 struct kvm_async_pf *work);
 void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
 struct kvm_async_pf *work);
+void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
+  struct kvm_async_pf *work);
 extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 #endif /* _ASM_X86_KVM_HOST_H */
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 4d49b5e..d85fda8 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2558,7 +2558,7 @@ static gpa_t nonpaging_gva_to_gpa_nested(struct kvm_vcpu 
*vcpu, gva_t vaddr,
 }
 
 static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
-   u32 error_code)
+   u32 error_code, bool no_apf)
 {
gfn_t gfn;
int r;
@@ -2594,8 +2594,8 @@ static bool can_do_async_pf(struct kvm_vcpu *vcpu)
return kvm_x86_ops-interrupt_allowed(vcpu);
 }
 
-static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva,
-pfn_t *pfn)
+static bool try_async_pf(struct kvm_vcpu *vcpu, bool no_apf, gfn_t gfn,
+gva_t gva, pfn_t *pfn)
 {
bool async;
 
@@ -2606,7 +2606,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t 
gfn, gva_t gva,
 
put_page(pfn_to_page(*pfn));
 
-   if (can_do_async_pf(vcpu)) {
+   if (!no_apf  can_do_async_pf(vcpu)) {
trace_kvm_try_async_get_page(async, *pfn);
if (kvm_find_async_pf_gfn(vcpu, gfn)) {
vcpu-async_pf.work = kvm_double_apf;
@@ -2620,8 +2620,8 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, gfn_t 
gfn, gva_t gva,
return false;
 }
 
-static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
-   u32 error_code)
+static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
+ bool no_apf)
 {
pfn_t pfn;
int r;
@@ -2643,7 +2643,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t 
gpa,
mmu_seq = vcpu-kvm-mmu_notifier_seq;
smp_rmb();
 
-   if (try_async_pf(vcpu, gfn, gpa, pfn))
+   if (try_async_pf(vcpu, no_apf, gfn, gpa, pfn))
return 0;
 
/* mmio */
@@ -3306,7 +3306,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, 
u32 error_code)
int r;
enum emulation_result er;
 
-   r = vcpu-arch.mmu.page_fault(vcpu, cr2, error_code);
+   r = vcpu-arch.mmu.page_fault(vcpu, cr2, error_code, false);
if (r  0)
goto out;
 
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 8154353..9ad90f8 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -530,8 +530,8 @@ out_gpte_changed:
  *  Returns: 1 if we need to emulate the instruction, 0 otherwise, or
  *   a negative value on error.
  */
-static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
-  u32 error_code)
+static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
+bool no_apf)
 {
int write_fault = error_code  PFERR_WRITE_MASK;
int user_fault = error_code  PFERR_USER_MASK;
@@ -574,7 +574,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t 
addr,
mmu_seq =