Skip to contentSkip to conversation

KVM: x86: Minor emulator cleanup

PATCH In review Sean Christopherson 3 participants 12 messages Feb 18, 2020 – Feb 21, 2020

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v2 cover KVM: x86: Minor emulator cleanup

Three small patches to move emulator specific variables from 'struct kvm_vcpu_arch' to 'struct x86_emulate_ctxt'.

v2:
- Rebase to kvm/queue, 2c2787938512 ("KVM: selftests: Stop ...")

Sean Christopherson (3):
KVM: x86: Add EMULTYPE_PF when emulation is triggered by a page fault
KVM: x86: Move gpa_val and gpa_available into the emulator context
KVM: x86: Move #PF retry tracking variables into emulation context

 arch/x86/include/asm/kvm_emulate.h |  8 ++++++
 arch/x86/include/asm/kvm_host.h    | 19 ++++++-------
 arch/x86/kvm/mmu/mmu.c             | 10 ++-----
 arch/x86/kvm/x86.c                 | 45 +++++++++++++++++++-----------
 4 files changed, 48 insertions(+), 34 deletions(-)
Signature · 1 line
2.24.1
#1 lore raw

PATCH v2 1/3 KVM: x86: Add EMULTYPE_PF when emulation is triggered by a page fault

Add a new emulation type flag to explicitly mark emulation related to a page fault. Move the propation of the GPA into the emulator from the page fault handler into x86_emulate_instruction, using EMULTYPE_PF as an indicator that cr2 is valid. Similarly, don't propagate cr2 into the exception.address when it's *not* valid.

---
 arch/x86/include/asm/kvm_host.h | 12 +++++++++---
 arch/x86/kvm/mmu/mmu.c          | 10 ++--------
 arch/x86/kvm/x86.c              | 25 +++++++++++++++++++------
 3 files changed, 30 insertions(+), 17 deletions(-)
arch/x86/include/asm/kvm_host.h +9 -3
index 4dffbc10d3f8..10c1e8f472b6 100644
@@ -1370,8 +1370,9 @@ extern u64 kvm_mce_cap_supported;
  *		   decode the instruction length.  For use *only* by
  *		   kvm_x86_ops->skip_emulated_instruction() implementations.
  *
- * EMULTYPE_ALLOW_RETRY - Set when the emulator should resume the guest to
- *			  retry native execution under certain conditions.
+ * EMULTYPE_ALLOW_RETRY_PF - Set when the emulator should resume the guest to
+ *			     retry native execution under certain conditions,
+ *			     Can only be set in conjunction with EMULTYPE_PF.
  *
  * EMULTYPE_TRAP_UD_FORCED - Set when emulating an intercepted #UD that was
  *			     triggered by KVM's magic "force emulation" prefix,
@@ -1384,13 +1385,18 @@ extern u64 kvm_mce_cap_supported;
  *			backdoor emulation, which is opt in via module param.
  *			VMware backoor emulation handles select instructions
  *			and reinjects the #GP for all other cases.
+ *
+ * EMULTYPE_PF - Set when emulating MMIO by way of an intercepted #PF, in which
+ *		 case the CR2/GPA value pass on the stack is valid.
  */
 #define EMULTYPE_NO_DECODE	    (1 << 0)
 #define EMULTYPE_TRAP_UD	    (1 << 1)
 #define EMULTYPE_SKIP		    (1 << 2)
-#define EMULTYPE_ALLOW_RETRY	    (1 << 3)
+#define EMULTYPE_ALLOW_RETRY_PF	    (1 << 3)
 #define EMULTYPE_TRAP_UD_FORCED	    (1 << 4)
 #define EMULTYPE_VMWARE_GP	    (1 << 5)
+#define EMULTYPE_PF		    (1 << 6)
+
 int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
 int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
 					void *insn, int insn_len);
arch/x86/kvm/mmu/mmu.c +2 -8
index 7011a4e54866..258624d46588 100644
@@ -5416,18 +5416,12 @@ EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
 int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
 		       void *insn, int insn_len)
 {
-	int r, emulation_type = 0;
+	int r, emulation_type = EMULTYPE_PF;
 	bool direct = vcpu->arch.mmu->direct_map;
 
 	if (WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa)))
 		return RET_PF_RETRY;
 
-	/* With shadow page tables, fault_address contains a GVA or nGPA.  */
-	if (vcpu->arch.mmu->direct_map) {
-		vcpu->arch.gpa_available = true;
-		vcpu->arch.gpa_val = cr2_or_gpa;
-	}
-
 	r = RET_PF_INVALID;
 	if (unlikely(error_code & PFERR_RSVD_MASK)) {
 		r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct);
@@ -5472,7 +5466,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
 	 * for L1 isn't going to magically fix whatever issue cause L2 to fail.
 	 */
 	if (!mmio_info_in_cache(vcpu, cr2_or_gpa, direct) && !is_guest_mode(vcpu))
-		emulation_type = EMULTYPE_ALLOW_RETRY;
+		emulation_type |= EMULTYPE_ALLOW_RETRY_PF;
 emulate:
 	/*
 	 * On AMD platforms, under certain conditions insn_len may be zero on #NPF.
arch/x86/kvm/x86.c +19 -6
index fbabb2f06273..92af6c5a69e3 100644
@@ -6483,10 +6483,11 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 	gpa_t gpa = cr2_or_gpa;
 	kvm_pfn_t pfn;
 
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
 		return false;
 
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
 		return false;
 
 	if (!vcpu->arch.mmu->direct_map) {
@@ -6574,10 +6575,11 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	 */
 	vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
 
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
 		return false;
 
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
 		return false;
 
 	if (x86_page_table_writing_insn(ctxt))
@@ -6830,8 +6832,19 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 	}
 
 restart:
-	/* Save the faulting GPA (cr2) in the address field */
-	ctxt->exception.address = cr2_or_gpa;
+	if (emulation_type & EMULTYPE_PF) {
+		/* Save the faulting GPA (cr2) in the address field */
+		ctxt->exception.address = cr2_or_gpa;
+
+		/* With shadow page tables, cr2 contains a GVA or nGPA. */
+		if (vcpu->arch.mmu->direct_map) {
+			vcpu->arch.gpa_available = true;
+			vcpu->arch.gpa_val = cr2_or_gpa;
+		}
+	} else {
+		/* Sanitize the address out of an abundance of paranoia. */
+		ctxt->exception.address = 0;
+	}
 
 	r = x86_emulate_insn(ctxt);
 
Signature · 1 line
2.24.1
#2 lore raw

Re: [PATCH v2 1/3] KVM: x86: Add EMULTYPE_PF when emulation is triggered by a page fault

Quoted 32 lines · Sean Christopherson

Add a new emulation type flag to explicitly mark emulation related to a page fault. Move the propation of the GPA into the emulator from the page fault handler into x86_emulate_instruction, using EMULTYPE_PF as an indicator that cr2 is valid. Similarly, don't propagate cr2 into the exception.address when it's *not* valid.

---
  arch/x86/include/asm/kvm_host.h | 12 +++++++++---
  arch/x86/kvm/mmu/mmu.c          | 10 ++--------
  arch/x86/kvm/x86.c              | 25 +++++++++++++++++++------
  3 files changed, 30 insertions(+), 17 deletions(-)
arch/x86/include/asm/kvm_host.h +3 -2
index 4dffbc10d3f8..10c1e8f472b6 100644
@@ -1370,8 +1370,9 @@ extern u64 kvm_mce_cap_supported;
   *		   decode the instruction length.  For use *only* by
   *		   kvm_x86_ops->skip_emulated_instruction() implementations.
   *
- * EMULTYPE_ALLOW_RETRY - Set when the emulator should resume the guest to
- *			  retry native execution under certain conditions.
+ * EMULTYPE_ALLOW_RETRY_PF - Set when the emulator should resume the guest to
+ *			     retry native execution under certain conditions,
+ *			     Can only be set in conjunction with EMULTYPE_PF.
   *
   * EMULTYPE_TRAP_UD_FORCED - Set when emulating an intercepted #UD that was
   *			     triggered by KVM's magic "force emulation" prefix,
@@ -1384,13 +1385,18 @@ extern u64 kvm_mce_cap_supported;
   *			backdoor emulation, which is opt in via module param.
   *			VMware backoor emulation handles select instructions

arch/x86/include/asm/kvm_host.h extern u64 kvm_mce_cap_supported; · line 1395

Quoted 10 lines
arch/x86/include/asm/kvm_host.h +4 -1
   *			and reinjects the #GP for all other cases.
+ *
+ * EMULTYPE_PF - Set when emulating MMIO by way of an intercepted #PF, in which
+ *		 case the CR2/GPA value pass on the stack is valid.
   */
  #define EMULTYPE_NO_DECODE	    (1 << 0)
  #define EMULTYPE_TRAP_UD	    (1 << 1)
  #define EMULTYPE_SKIP		    (1 << 2)
-#define EMULTYPE_ALLOW_RETRY	    (1 << 3)
+#define EMULTYPE_ALLOW_RETRY_PF	    (1 << 3)

How about naming it as EMULTYPE_PF_ALLOW_RETRY and exchanging the bit position with EMULTYPE_PF ?

Quoted 95 lines
arch/x86/include/asm/kvm_host.h +2 -0
  #define EMULTYPE_TRAP_UD_FORCED	    (1 << 4)
  #define EMULTYPE_VMWARE_GP	    (1 << 5)
+#define EMULTYPE_PF		    (1 << 6)
+
  int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
  int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
  					void *insn, int insn_len);
arch/x86/kvm/mmu/mmu.c +2 -8
index 7011a4e54866..258624d46588 100644
@@ -5416,18 +5416,12 @@ EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
  int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
  		       void *insn, int insn_len)
  {
-	int r, emulation_type = 0;
+	int r, emulation_type = EMULTYPE_PF;
  	bool direct = vcpu->arch.mmu->direct_map;
 
  	if (WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa)))
  		return RET_PF_RETRY;
 
-	/* With shadow page tables, fault_address contains a GVA or nGPA.  */
-	if (vcpu->arch.mmu->direct_map) {
-		vcpu->arch.gpa_available = true;
-		vcpu->arch.gpa_val = cr2_or_gpa;
-	}
-
  	r = RET_PF_INVALID;
  	if (unlikely(error_code & PFERR_RSVD_MASK)) {
  		r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct);
@@ -5472,7 +5466,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
  	 * for L1 isn't going to magically fix whatever issue cause L2 to fail.
  	 */
  	if (!mmio_info_in_cache(vcpu, cr2_or_gpa, direct) && !is_guest_mode(vcpu))
-		emulation_type = EMULTYPE_ALLOW_RETRY;
+		emulation_type |= EMULTYPE_ALLOW_RETRY_PF;
  emulate:
  	/*
  	 * On AMD platforms, under certain conditions insn_len may be zero on #NPF.
arch/x86/kvm/x86.c +19 -6
index fbabb2f06273..92af6c5a69e3 100644
@@ -6483,10 +6483,11 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
  	gpa_t gpa = cr2_or_gpa;
  	kvm_pfn_t pfn;
 
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
  		return false;
 
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
  		return false;
 
  	if (!vcpu->arch.mmu->direct_map) {
@@ -6574,10 +6575,11 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
  	 */
  	vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
 
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
  		return false;
 
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
  		return false;
 
  	if (x86_page_table_writing_insn(ctxt))
@@ -6830,8 +6832,19 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
  	}
 
  restart:
-	/* Save the faulting GPA (cr2) in the address field */
-	ctxt->exception.address = cr2_or_gpa;
+	if (emulation_type & EMULTYPE_PF) {
+		/* Save the faulting GPA (cr2) in the address field */
+		ctxt->exception.address = cr2_or_gpa;
+
+		/* With shadow page tables, cr2 contains a GVA or nGPA. */
+		if (vcpu->arch.mmu->direct_map) {
+			vcpu->arch.gpa_available = true;
+			vcpu->arch.gpa_val = cr2_or_gpa;
+		}
+	} else {
+		/* Sanitize the address out of an abundance of paranoia. */
+		ctxt->exception.address = 0;
+	}
 
  	r = x86_emulate_insn(ctxt);
 
#3 lore raw

Re: [PATCH v2 1/3] KVM: x86: Add EMULTYPE_PF when emulation is triggered by a page fault

Quoted 38 lines · Xiaoyao Li
Quoted 37 lines · Sean Christopherson

Add a new emulation type flag to explicitly mark emulation related to a page fault. Move the propation of the GPA into the emulator from the page fault handler into x86_emulate_instruction, using EMULTYPE_PF as an indicator that cr2 is valid. Similarly, don't propagate cr2 into the exception.address when it's *not* valid.

---
 arch/x86/include/asm/kvm_host.h | 12 +++++++++---
 arch/x86/kvm/mmu/mmu.c          | 10 ++--------
 arch/x86/kvm/x86.c              | 25 +++++++++++++++++++------
 3 files changed, 30 insertions(+), 17 deletions(-)
arch/x86/include/asm/kvm_host.h +6 -2
index 4dffbc10d3f8..10c1e8f472b6 100644
@@ -1370,8 +1370,9 @@ extern u64 kvm_mce_cap_supported;
  *		   decode the instruction length.  For use *only* by
  *		   kvm_x86_ops->skip_emulated_instruction() implementations.
  *
- * EMULTYPE_ALLOW_RETRY - Set when the emulator should resume the guest to
- *			  retry native execution under certain conditions.
+ * EMULTYPE_ALLOW_RETRY_PF - Set when the emulator should resume the guest to
+ *			     retry native execution under certain conditions,
+ *			     Can only be set in conjunction with EMULTYPE_PF.
  *
  * EMULTYPE_TRAP_UD_FORCED - Set when emulating an intercepted #UD that was
  *			     triggered by KVM's magic "force emulation" prefix,
@@ -1384,13 +1385,18 @@ extern u64 kvm_mce_cap_supported;
  *			backdoor emulation, which is opt in via module param.
  *			VMware backoor emulation handles select instructions
  *			and reinjects the #GP for all other cases.
+ *
+ * EMULTYPE_PF - Set when emulating MMIO by way of an intercepted #PF, in which
+ *		 case the CR2/GPA value pass on the stack is valid.
  */
Quoted 8 lines

arch/x86/include/asm/kvm_host.h extern u64 kvm_mce_cap_supported; · line 1395

Quoted 5 lines
arch/x86/include/asm/kvm_host.h +1 -1
 #define EMULTYPE_NO_DECODE	    (1 << 0)
 #define EMULTYPE_TRAP_UD	    (1 << 1)
 #define EMULTYPE_SKIP		    (1 << 2)
-#define EMULTYPE_ALLOW_RETRY	    (1 << 3)
+#define EMULTYPE_ALLOW_RETRY_PF	    (1 << 3)

How about naming it as EMULTYPE_PF_ALLOW_RETRY and exchanging the bit position with EMULTYPE_PF ?

Hmm, EMULTYPE_PF_ALLOW_RETRY does sound better. I'm on the fence regarding shuffling the bits. If I were to shuffle the bits, I'd do a more thorough reorder so that the #UD and #PF types are consecutive, e.g.

	#define EMULTYPE_NO_DECODE	    (1 << 0)
	#define EMULTYPE_TRAP_UD	    (1 << 1)
	#define EMULTYPE_TRAP_UD_FORCED	    (1 << 2)
	#define EMULTYPE_SKIP		    (1 << 3)
	#define EMULTYPE_VMWARE_GP	    (1 << 4)
	#define EMULTYPE_PF		    (1 << 5)
	#define EMULTYPE_PF_ALLOW_RETRY	    (1 << 6)

Part of me really wants to do that, the other part of me thinks it's unnecessary thrash.

Quoted 85 lines
Quoted 84 lines
arch/x86/include/asm/kvm_host.h +2 -0
 #define EMULTYPE_TRAP_UD_FORCED	    (1 << 4)
 #define EMULTYPE_VMWARE_GP	    (1 << 5)
+#define EMULTYPE_PF		    (1 << 6)
+
 int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
 int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
 					void *insn, int insn_len);
arch/x86/kvm/mmu/mmu.c +2 -8
index 7011a4e54866..258624d46588 100644
@@ -5416,18 +5416,12 @@ EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
 int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
 		       void *insn, int insn_len)
 {
-	int r, emulation_type = 0;
+	int r, emulation_type = EMULTYPE_PF;
 	bool direct = vcpu->arch.mmu->direct_map;
 	if (WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa)))
 		return RET_PF_RETRY;
-	/* With shadow page tables, fault_address contains a GVA or nGPA.  */
-	if (vcpu->arch.mmu->direct_map) {
-		vcpu->arch.gpa_available = true;
-		vcpu->arch.gpa_val = cr2_or_gpa;
-	}
-
 	r = RET_PF_INVALID;
 	if (unlikely(error_code & PFERR_RSVD_MASK)) {
 		r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct);
@@ -5472,7 +5466,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
 	 * for L1 isn't going to magically fix whatever issue cause L2 to fail.
 	 */
 	if (!mmio_info_in_cache(vcpu, cr2_or_gpa, direct) && !is_guest_mode(vcpu))
-		emulation_type = EMULTYPE_ALLOW_RETRY;
+		emulation_type |= EMULTYPE_ALLOW_RETRY_PF;
 emulate:
 	/*
 	 * On AMD platforms, under certain conditions insn_len may be zero on #NPF.
arch/x86/kvm/x86.c +19 -6
index fbabb2f06273..92af6c5a69e3 100644
@@ -6483,10 +6483,11 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 	gpa_t gpa = cr2_or_gpa;
 	kvm_pfn_t pfn;
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
 		return false;
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
 		return false;
 	if (!vcpu->arch.mmu->direct_map) {
@@ -6574,10 +6575,11 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	 */
 	vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
 		return false;
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
 		return false;
 	if (x86_page_table_writing_insn(ctxt))
@@ -6830,8 +6832,19 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 	}
 restart:
-	/* Save the faulting GPA (cr2) in the address field */
-	ctxt->exception.address = cr2_or_gpa;
+	if (emulation_type & EMULTYPE_PF) {
+		/* Save the faulting GPA (cr2) in the address field */
+		ctxt->exception.address = cr2_or_gpa;
+
+		/* With shadow page tables, cr2 contains a GVA or nGPA. */
+		if (vcpu->arch.mmu->direct_map) {
+			vcpu->arch.gpa_available = true;
+			vcpu->arch.gpa_val = cr2_or_gpa;
+		}
+	} else {
+		/* Sanitize the address out of an abundance of paranoia. */
+		ctxt->exception.address = 0;
+	}
 	r = x86_emulate_insn(ctxt);
 
#4 lore raw

Re: [PATCH v2 1/3] KVM: x86: Add EMULTYPE_PF when emulation is triggered by a page fault

Quoted 60 lines · Sean Christopherson
Quoted 38 lines · Xiaoyao Li
Quoted 37 lines · Sean Christopherson

Add a new emulation type flag to explicitly mark emulation related to a page fault. Move the propation of the GPA into the emulator from the page fault handler into x86_emulate_instruction, using EMULTYPE_PF as an indicator that cr2 is valid. Similarly, don't propagate cr2 into the exception.address when it's *not* valid.

---
  arch/x86/include/asm/kvm_host.h | 12 +++++++++---
  arch/x86/kvm/mmu/mmu.c          | 10 ++--------
  arch/x86/kvm/x86.c              | 25 +++++++++++++++++++------
  3 files changed, 30 insertions(+), 17 deletions(-)
arch/x86/include/asm/kvm_host.h +6 -2
index 4dffbc10d3f8..10c1e8f472b6 100644
@@ -1370,8 +1370,9 @@ extern u64 kvm_mce_cap_supported;
   *		   decode the instruction length.  For use *only* by
   *		   kvm_x86_ops->skip_emulated_instruction() implementations.
   *
- * EMULTYPE_ALLOW_RETRY - Set when the emulator should resume the guest to
- *			  retry native execution under certain conditions.
+ * EMULTYPE_ALLOW_RETRY_PF - Set when the emulator should resume the guest to
+ *			     retry native execution under certain conditions,
+ *			     Can only be set in conjunction with EMULTYPE_PF.
   *
   * EMULTYPE_TRAP_UD_FORCED - Set when emulating an intercepted #UD that was
   *			     triggered by KVM's magic "force emulation" prefix,
@@ -1384,13 +1385,18 @@ extern u64 kvm_mce_cap_supported;
   *			backdoor emulation, which is opt in via module param.
   *			VMware backoor emulation handles select instructions
   *			and reinjects the #GP for all other cases.
+ *
+ * EMULTYPE_PF - Set when emulating MMIO by way of an intercepted #PF, in which
+ *		 case the CR2/GPA value pass on the stack is valid.
   */
Quoted 8 lines

arch/x86/include/asm/kvm_host.h extern u64 kvm_mce_cap_supported; · line 1395

Quoted 5 lines
arch/x86/include/asm/kvm_host.h +1 -1
  #define EMULTYPE_NO_DECODE	    (1 << 0)
  #define EMULTYPE_TRAP_UD	    (1 << 1)
  #define EMULTYPE_SKIP		    (1 << 2)
-#define EMULTYPE_ALLOW_RETRY	    (1 << 3)
+#define EMULTYPE_ALLOW_RETRY_PF	    (1 << 3)

How about naming it as EMULTYPE_PF_ALLOW_RETRY and exchanging the bit position with EMULTYPE_PF ?

Hmm, EMULTYPE_PF_ALLOW_RETRY does sound better. I'm on the fence regarding shuffling the bits. If I were to shuffle the bits, I'd do a more thorough reorder so that the #UD and #PF types are consecutive, e.g.

	#define EMULTYPE_NO_DECODE	    (1 << 0)
	#define EMULTYPE_TRAP_UD	    (1 << 1)
	#define EMULTYPE_TRAP_UD_FORCED	    (1 << 2)
	#define EMULTYPE_SKIP		    (1 << 3)
	#define EMULTYPE_VMWARE_GP	    (1 << 4)
	#define EMULTYPE_PF		    (1 << 5)
	#define EMULTYPE_PF_ALLOW_RETRY	    (1 << 6)
Quoted 3 lines

Part of me really wants to do that, the other part of me thinks it's unnecessary thrash.

I'm fine with thorough reorder, it helps read the codes. It's up to Paolo, anyway.

Quoted 85 lines
Quoted 85 lines
Quoted 84 lines
arch/x86/include/asm/kvm_host.h +2 -0
  #define EMULTYPE_TRAP_UD_FORCED	    (1 << 4)
  #define EMULTYPE_VMWARE_GP	    (1 << 5)
+#define EMULTYPE_PF		    (1 << 6)
+
  int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
  int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
  					void *insn, int insn_len);
arch/x86/kvm/mmu/mmu.c +2 -8
index 7011a4e54866..258624d46588 100644
@@ -5416,18 +5416,12 @@ EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
  int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
  		       void *insn, int insn_len)
  {
-	int r, emulation_type = 0;
+	int r, emulation_type = EMULTYPE_PF;
  	bool direct = vcpu->arch.mmu->direct_map;
  	if (WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa)))
  		return RET_PF_RETRY;
-	/* With shadow page tables, fault_address contains a GVA or nGPA.  */
-	if (vcpu->arch.mmu->direct_map) {
-		vcpu->arch.gpa_available = true;
-		vcpu->arch.gpa_val = cr2_or_gpa;
-	}
-
  	r = RET_PF_INVALID;
  	if (unlikely(error_code & PFERR_RSVD_MASK)) {
  		r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct);
@@ -5472,7 +5466,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
  	 * for L1 isn't going to magically fix whatever issue cause L2 to fail.
  	 */
  	if (!mmio_info_in_cache(vcpu, cr2_or_gpa, direct) && !is_guest_mode(vcpu))
-		emulation_type = EMULTYPE_ALLOW_RETRY;
+		emulation_type |= EMULTYPE_ALLOW_RETRY_PF;
  emulate:
  	/*
  	 * On AMD platforms, under certain conditions insn_len may be zero on #NPF.
arch/x86/kvm/x86.c +19 -6
index fbabb2f06273..92af6c5a69e3 100644
@@ -6483,10 +6483,11 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
  	gpa_t gpa = cr2_or_gpa;
  	kvm_pfn_t pfn;
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
  		return false;
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
  		return false;
  	if (!vcpu->arch.mmu->direct_map) {
@@ -6574,10 +6575,11 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
  	 */
  	vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
-	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
+	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
  		return false;
-	if (WARN_ON_ONCE(is_guest_mode(vcpu)))
+	if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
+	    WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
  		return false;
  	if (x86_page_table_writing_insn(ctxt))
@@ -6830,8 +6832,19 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
  	}
  restart:
-	/* Save the faulting GPA (cr2) in the address field */
-	ctxt->exception.address = cr2_or_gpa;
+	if (emulation_type & EMULTYPE_PF) {
+		/* Save the faulting GPA (cr2) in the address field */
+		ctxt->exception.address = cr2_or_gpa;
+
+		/* With shadow page tables, cr2 contains a GVA or nGPA. */
+		if (vcpu->arch.mmu->direct_map) {
+			vcpu->arch.gpa_available = true;
+			vcpu->arch.gpa_val = cr2_or_gpa;
+		}
+	} else {
+		/* Sanitize the address out of an abundance of paranoia. */
+		ctxt->exception.address = 0;
+	}
  	r = x86_emulate_insn(ctxt);
 
maintainer
#5 lore raw

Re: [PATCH v2 1/3] KVM: x86: Add EMULTYPE_PF when emulation is triggered by a page fault

In reply to Sean Christopherson
Quoted 5 lines · Sean Christopherson
Quoted 2 lines

How about naming it as EMULTYPE_PF_ALLOW_RETRY and exchanging the bit position with EMULTYPE_PF ?

Hmm, EMULTYPE_PF_ALLOW_RETRY does sound better. I'm on the fence regarding shuffling the bits. If I were to shuffle the bits, I'd do a more thorough reorder so that the #UD and #PF types are consecutive, e.g.

Let's just change the name, I can do it.

Paolo

#6 lore raw

PATCH v2 2/3 KVM: x86: Move gpa_val and gpa_available into the emulator context

In reply to Sean Christopherson

Move the GPA tracking into the emulator context now that the context is guaranteed to be initialized via __init_emulate_ctxt() prior to dereferencing gpa_{available,val}, i.e. now that seeing a stale gpa_available will also trigger a WARN due to an invalid context.

---
 arch/x86/include/asm/kvm_emulate.h |  4 ++++
 arch/x86/include/asm/kvm_host.h    |  4 ----
 arch/x86/kvm/x86.c                 | 13 ++++++-------
 3 files changed, 10 insertions(+), 11 deletions(-)
arch/x86/include/asm/kvm_emulate.h +4 -0
index 03946eb3e2b9..a4ef19a6e612 100644
@@ -311,6 +311,10 @@ struct x86_emulate_ctxt {
 	bool have_exception;
 	struct x86_exception exception;
 
+	/* GPA available */
+	bool gpa_available;
+	gpa_t gpa_val;
+
 	/*
 	 * decode cache
 	 */
arch/x86/include/asm/kvm_host.h +0 -4
index 10c1e8f472b6..9c79c41eb5f6 100644
@@ -798,10 +798,6 @@ struct kvm_vcpu_arch {
 	int pending_ioapic_eoi;
 	int pending_external_vector;
 
-	/* GPA available */
-	bool gpa_available;
-	gpa_t gpa_val;
-
 	/* be preempted when it's in kernel-mode(cpl=0) */
 	bool preempted_in_kernel;
 
arch/x86/kvm/x86.c +6 -7
index 92af6c5a69e3..f88b72932c35 100644
@@ -5736,10 +5736,9 @@ static int emulator_read_write_onepage(unsigned long addr, void *val,
 	 * operation using rep will only have the initial GPA from the NPF
 	 * occurred.
 	 */
-	if (vcpu->arch.gpa_available &&
-	    emulator_can_use_gpa(ctxt) &&
-	    (addr & ~PAGE_MASK) == (vcpu->arch.gpa_val & ~PAGE_MASK)) {
-		gpa = vcpu->arch.gpa_val;
+	if (ctxt->gpa_available && emulator_can_use_gpa(ctxt) &&
+	    (addr & ~PAGE_MASK) == (ctxt->gpa_val & ~PAGE_MASK)) {
+		gpa = ctxt->gpa_val;
 		ret = vcpu_is_mmio_gpa(vcpu, addr, gpa, write);
 	} else {
 		ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write);
@@ -6408,6 +6407,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 
 	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 
+	ctxt->gpa_available = false;
 	ctxt->eflags = kvm_get_rflags(vcpu);
 	ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0;
 
@@ -6838,8 +6838,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 
 		/* With shadow page tables, cr2 contains a GVA or nGPA. */
 		if (vcpu->arch.mmu->direct_map) {
-			vcpu->arch.gpa_available = true;
-			vcpu->arch.gpa_val = cr2_or_gpa;
+			ctxt->gpa_available = true;
+			ctxt->gpa_val = cr2_or_gpa;
 		}
 	} else {
 		/* Sanitize the address out of an abundance of paranoia. */
@@ -8443,7 +8443,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 	if (vcpu->arch.apic_attention)
 		kvm_lapic_sync_from_vapic(vcpu);
 
-	vcpu->arch.gpa_available = false;
 	r = kvm_x86_ops->handle_exit(vcpu, exit_fastpath);
 	return r;
 
Signature · 1 line
2.24.1
#7 lore raw

PATCH v2 3/3 KVM: x86: Move #PF retry tracking variables into emulation context

In reply to Sean Christopherson

Move last_retry_eip and last_retry_addr into the emulation context as they are specific to retrying an instruction after emulation failure.

---
 arch/x86/include/asm/kvm_emulate.h |  4 ++++
 arch/x86/include/asm/kvm_host.h    |  3 ---
 arch/x86/kvm/x86.c                 | 11 ++++++-----
 3 files changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/kvm_emulate.h +4 -0
index a4ef19a6e612..a26c8de414e8 100644
@@ -315,6 +315,10 @@ struct x86_emulate_ctxt {
 	bool gpa_available;
 	gpa_t gpa_val;
 
+	/* Track EIP and CR2/GPA when retrying faulting instruction on #PF. */
+	unsigned long last_retry_eip;
+	unsigned long last_retry_addr;
+
 	/*
 	 * decode cache
 	 */
arch/x86/include/asm/kvm_host.h +0 -3
index 9c79c41eb5f6..6312ea32bb41 100644
@@ -752,9 +752,6 @@ struct kvm_vcpu_arch {
 
 	cpumask_var_t wbinvd_dirty_mask;
 
-	unsigned long last_retry_eip;
-	unsigned long last_retry_addr;
-
 	struct {
 		bool halted;
 		gfn_t gfns[roundup_pow_of_two(ASYNC_PF_PER_VCPU)];
arch/x86/kvm/x86.c +6 -5
index f88b72932c35..d19eb776f297 100644
@@ -6407,6 +6407,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 
 	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 
+	/* last_retry_{eip,addr} are persistent and must not be init'd here. */
 	ctxt->gpa_available = false;
 	ctxt->eflags = kvm_get_rflags(vcpu);
 	ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0;
@@ -6557,8 +6558,8 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 	unsigned long last_retry_eip, last_retry_addr, gpa = cr2_or_gpa;
 
-	last_retry_eip = vcpu->arch.last_retry_eip;
-	last_retry_addr = vcpu->arch.last_retry_addr;
+	last_retry_eip = ctxt->last_retry_eip;
+	last_retry_addr = ctxt->last_retry_addr;
 
 	/*
 	 * If the emulation is caused by #PF and it is non-page_table
@@ -6573,7 +6574,7 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	 * and the address again, we can break out of the potential infinite
 	 * loop.
 	 */
-	vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
+	ctxt->last_retry_eip = ctxt->last_retry_addr = 0;
 
 	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
 		return false;
@@ -6588,8 +6589,8 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	if (ctxt->eip == last_retry_eip && last_retry_addr == cr2_or_gpa)
 		return false;
 
-	vcpu->arch.last_retry_eip = ctxt->eip;
-	vcpu->arch.last_retry_addr = cr2_or_gpa;
+	ctxt->last_retry_eip = ctxt->eip;
+	ctxt->last_retry_addr = cr2_or_gpa;
 
 	if (!vcpu->arch.mmu->direct_map)
 		gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL);
Signature · 1 line
2.24.1
maintainer
#8 lore raw

Re: [PATCH v2 3/3] KVM: x86: Move #PF retry tracking variables into emulation context

Quoted 4 lines · Sean Christopherson

Move last_retry_eip and last_retry_addr into the emulation context as they are specific to retrying an instruction after emulation failure.

I'm not sure about this, since it's not used by emulate.c. The other two patches are good.

Paolo

Quoted 79 lines
---
 arch/x86/include/asm/kvm_emulate.h |  4 ++++
 arch/x86/include/asm/kvm_host.h    |  3 ---
 arch/x86/kvm/x86.c                 | 11 ++++++-----
 3 files changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/kvm_emulate.h +4 -0
index a4ef19a6e612..a26c8de414e8 100644
@@ -315,6 +315,10 @@ struct x86_emulate_ctxt {
 	bool gpa_available;
 	gpa_t gpa_val;
 
+	/* Track EIP and CR2/GPA when retrying faulting instruction on #PF. */
+	unsigned long last_retry_eip;
+	unsigned long last_retry_addr;
+
 	/*
 	 * decode cache
 	 */
arch/x86/include/asm/kvm_host.h +0 -3
index 9c79c41eb5f6..6312ea32bb41 100644
@@ -752,9 +752,6 @@ struct kvm_vcpu_arch {
 
 	cpumask_var_t wbinvd_dirty_mask;
 
-	unsigned long last_retry_eip;
-	unsigned long last_retry_addr;
-
 	struct {
 		bool halted;
 		gfn_t gfns[roundup_pow_of_two(ASYNC_PF_PER_VCPU)];
arch/x86/kvm/x86.c +6 -5
index f88b72932c35..d19eb776f297 100644
@@ -6407,6 +6407,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 
 	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 
+	/* last_retry_{eip,addr} are persistent and must not be init'd here. */
 	ctxt->gpa_available = false;
 	ctxt->eflags = kvm_get_rflags(vcpu);
 	ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0;
@@ -6557,8 +6558,8 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 	unsigned long last_retry_eip, last_retry_addr, gpa = cr2_or_gpa;
 
-	last_retry_eip = vcpu->arch.last_retry_eip;
-	last_retry_addr = vcpu->arch.last_retry_addr;
+	last_retry_eip = ctxt->last_retry_eip;
+	last_retry_addr = ctxt->last_retry_addr;
 
 	/*
 	 * If the emulation is caused by #PF and it is non-page_table
@@ -6573,7 +6574,7 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	 * and the address again, we can break out of the potential infinite
 	 * loop.
 	 */
-	vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
+	ctxt->last_retry_eip = ctxt->last_retry_addr = 0;
 
 	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
 		return false;
@@ -6588,8 +6589,8 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	if (ctxt->eip == last_retry_eip && last_retry_addr == cr2_or_gpa)
 		return false;
 
-	vcpu->arch.last_retry_eip = ctxt->eip;
-	vcpu->arch.last_retry_addr = cr2_or_gpa;
+	ctxt->last_retry_eip = ctxt->eip;
+	ctxt->last_retry_addr = cr2_or_gpa;
 
 	if (!vcpu->arch.mmu->direct_map)
 		gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL);
#9 lore raw

Re: [PATCH v2 3/3] KVM: x86: Move #PF retry tracking variables into emulation context

Quoted 8 lines · Paolo Bonzini
Quoted 4 lines · Sean Christopherson

Move last_retry_eip and last_retry_addr into the emulation context as they are specific to retrying an instruction after emulation failure.

I'm not sure about this, since it's not used by emulate.c. The other two patches are good.

The easy solution to that is to move retry_instruction() into emulate.c. That would also allow making x86_page_table_writing_insn() static. All other functions invoked from retry_instruction() are exposed via kvm_host.h.

Moving last_retry_* into the emulator context hopefully makes it more clear that this code is the only user of the variables, e.g. last_retry_eip can't be set by some other non-emulator flow.

	if (ctxt->eip == last_retry_eip && last_retry_addr == cr2)
		return false;

	vcpu->arch.last_retry_eip = ctxt->eip;
	vcpu->arch.last_retry_addr = cr2;
Quoted 80 lines
Quoted 79 lines
---
 arch/x86/include/asm/kvm_emulate.h |  4 ++++
 arch/x86/include/asm/kvm_host.h    |  3 ---
 arch/x86/kvm/x86.c                 | 11 ++++++-----
 3 files changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/kvm_emulate.h +4 -0
index a4ef19a6e612..a26c8de414e8 100644
@@ -315,6 +315,10 @@ struct x86_emulate_ctxt {
 	bool gpa_available;
 	gpa_t gpa_val;
 
+	/* Track EIP and CR2/GPA when retrying faulting instruction on #PF. */
+	unsigned long last_retry_eip;
+	unsigned long last_retry_addr;
+
 	/*
 	 * decode cache
 	 */
arch/x86/include/asm/kvm_host.h +0 -3
index 9c79c41eb5f6..6312ea32bb41 100644
@@ -752,9 +752,6 @@ struct kvm_vcpu_arch {
 
 	cpumask_var_t wbinvd_dirty_mask;
 
-	unsigned long last_retry_eip;
-	unsigned long last_retry_addr;
-
 	struct {
 		bool halted;
 		gfn_t gfns[roundup_pow_of_two(ASYNC_PF_PER_VCPU)];
arch/x86/kvm/x86.c +6 -5
index f88b72932c35..d19eb776f297 100644
@@ -6407,6 +6407,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 
 	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 
+	/* last_retry_{eip,addr} are persistent and must not be init'd here. */
 	ctxt->gpa_available = false;
 	ctxt->eflags = kvm_get_rflags(vcpu);
 	ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0;
@@ -6557,8 +6558,8 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 	unsigned long last_retry_eip, last_retry_addr, gpa = cr2_or_gpa;
 
-	last_retry_eip = vcpu->arch.last_retry_eip;
-	last_retry_addr = vcpu->arch.last_retry_addr;
+	last_retry_eip = ctxt->last_retry_eip;
+	last_retry_addr = ctxt->last_retry_addr;
 
 	/*
 	 * If the emulation is caused by #PF and it is non-page_table
@@ -6573,7 +6574,7 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	 * and the address again, we can break out of the potential infinite
 	 * loop.
 	 */
-	vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
+	ctxt->last_retry_eip = ctxt->last_retry_addr = 0;
 
 	if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
 		return false;
@@ -6588,8 +6589,8 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	if (ctxt->eip == last_retry_eip && last_retry_addr == cr2_or_gpa)
 		return false;
 
-	vcpu->arch.last_retry_eip = ctxt->eip;
-	vcpu->arch.last_retry_addr = cr2_or_gpa;
+	ctxt->last_retry_eip = ctxt->eip;
+	ctxt->last_retry_addr = cr2_or_gpa;
 
 	if (!vcpu->arch.mmu->direct_map)
 		gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL);
maintainer
#10 lore raw

Re: [PATCH v2 3/3] KVM: x86: Move #PF retry tracking variables into emulation context

Quoted 3 lines · Sean Christopherson

The easy solution to that is to move retry_instruction() into emulate.c. That would also allow making x86_page_table_writing_insn() static. All other functions invoked from retry_instruction() are exposed via kvm_host.h.

emulate.c is supposed to invoke no (or almost no) function outside the ctxt->ops struct. In particular, retry_instruction() invokes kvm_mmu_gva_to_gpa_write and kvm_mmu_unprotect_page.

Paolo

#11 lore raw

Re: [PATCH v2 3/3] KVM: x86: Move #PF retry tracking variables into emulation context

Quoted 8 lines · Paolo Bonzini
Quoted 3 lines · Sean Christopherson

The easy solution to that is to move retry_instruction() into emulate.c. That would also allow making x86_page_table_writing_insn() static. All other functions invoked from retry_instruction() are exposed via kvm_host.h.

emulate.c is supposed to invoke no (or almost no) function outside the ctxt->ops struct. In particular, retry_instruction() invokes kvm_mmu_gva_to_gpa_write and kvm_mmu_unprotect_page.

Ah, right. We could split the logic, e.g.

	if (x86_retry_pf_instruction(ctxt, cr2_or_gpa, emulation_type)) {
		gpa_t = gpa = cr2_or_gpa;

		if (!vcpu->arch.mmu->direct_map)
			gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL);

		kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa));
		return 1;
	}

but that's probably a net negative in terms of clarity. And there's also vcpu->arch.write_fault_to_shadow_pgtable, which is consumed only by reexecute_instruction(), and I 100% agree that that variable should stay in vcpu->arch. Moving one flag used to retry #PF instructions and not the other would be weird.

That was a long winded way of saying I agree we should drop this patch :-)