Skip to content

Commit 92daa48

Browse files
Sean Christophersonbonzini
authored andcommitted
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. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 999eabc commit 92daa48

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,8 +1381,9 @@ extern u64 kvm_mce_cap_supported;
13811381
* decode the instruction length. For use *only* by
13821382
* kvm_x86_ops->skip_emulated_instruction() implementations.
13831383
*
1384-
* EMULTYPE_ALLOW_RETRY - Set when the emulator should resume the guest to
1385-
* retry native execution under certain conditions.
1384+
* EMULTYPE_ALLOW_RETRY_PF - Set when the emulator should resume the guest to
1385+
* retry native execution under certain conditions,
1386+
* Can only be set in conjunction with EMULTYPE_PF.
13861387
*
13871388
* EMULTYPE_TRAP_UD_FORCED - Set when emulating an intercepted #UD that was
13881389
* triggered by KVM's magic "force emulation" prefix,
@@ -1395,13 +1396,18 @@ extern u64 kvm_mce_cap_supported;
13951396
* backdoor emulation, which is opt in via module param.
13961397
* VMware backoor emulation handles select instructions
13971398
* and reinjects the #GP for all other cases.
1399+
*
1400+
* EMULTYPE_PF - Set when emulating MMIO by way of an intercepted #PF, in which
1401+
* case the CR2/GPA value pass on the stack is valid.
13981402
*/
13991403
#define EMULTYPE_NO_DECODE (1 << 0)
14001404
#define EMULTYPE_TRAP_UD (1 << 1)
14011405
#define EMULTYPE_SKIP (1 << 2)
1402-
#define EMULTYPE_ALLOW_RETRY (1 << 3)
1406+
#define EMULTYPE_ALLOW_RETRY_PF (1 << 3)
14031407
#define EMULTYPE_TRAP_UD_FORCED (1 << 4)
14041408
#define EMULTYPE_VMWARE_GP (1 << 5)
1409+
#define EMULTYPE_PF (1 << 6)
1410+
14051411
int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
14061412
int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
14071413
void *insn, int insn_len);

arch/x86/kvm/mmu/mmu.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5415,18 +5415,12 @@ EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
54155415
int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
54165416
void *insn, int insn_len)
54175417
{
5418-
int r, emulation_type = 0;
5418+
int r, emulation_type = EMULTYPE_PF;
54195419
bool direct = vcpu->arch.mmu->direct_map;
54205420

54215421
if (WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa)))
54225422
return RET_PF_RETRY;
54235423

5424-
/* With shadow page tables, fault_address contains a GVA or nGPA. */
5425-
if (vcpu->arch.mmu->direct_map) {
5426-
vcpu->arch.gpa_available = true;
5427-
vcpu->arch.gpa_val = cr2_or_gpa;
5428-
}
5429-
54305424
r = RET_PF_INVALID;
54315425
if (unlikely(error_code & PFERR_RSVD_MASK)) {
54325426
r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct);
@@ -5470,7 +5464,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
54705464
* for L1 isn't going to magically fix whatever issue cause L2 to fail.
54715465
*/
54725466
if (!mmio_info_in_cache(vcpu, cr2_or_gpa, direct) && !is_guest_mode(vcpu))
5473-
emulation_type = EMULTYPE_ALLOW_RETRY;
5467+
emulation_type |= EMULTYPE_ALLOW_RETRY_PF;
54745468
emulate:
54755469
/*
54765470
* On AMD platforms, under certain conditions insn_len may be zero on #NPF.

arch/x86/kvm/x86.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6492,10 +6492,11 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
64926492
gpa_t gpa = cr2_or_gpa;
64936493
kvm_pfn_t pfn;
64946494

6495-
if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
6495+
if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
64966496
return false;
64976497

6498-
if (WARN_ON_ONCE(is_guest_mode(vcpu)))
6498+
if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
6499+
WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
64996500
return false;
65006501

65016502
if (!vcpu->arch.mmu->direct_map) {
@@ -6583,10 +6584,11 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
65836584
*/
65846585
vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
65856586

6586-
if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
6587+
if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF))
65876588
return false;
65886589

6589-
if (WARN_ON_ONCE(is_guest_mode(vcpu)))
6590+
if (WARN_ON_ONCE(is_guest_mode(vcpu)) ||
6591+
WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))
65906592
return false;
65916593

65926594
if (x86_page_table_writing_insn(ctxt))
@@ -6839,8 +6841,19 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
68396841
}
68406842

68416843
restart:
6842-
/* Save the faulting GPA (cr2) in the address field */
6843-
ctxt->exception.address = cr2_or_gpa;
6844+
if (emulation_type & EMULTYPE_PF) {
6845+
/* Save the faulting GPA (cr2) in the address field */
6846+
ctxt->exception.address = cr2_or_gpa;
6847+
6848+
/* With shadow page tables, cr2 contains a GVA or nGPA. */
6849+
if (vcpu->arch.mmu->direct_map) {
6850+
vcpu->arch.gpa_available = true;
6851+
vcpu->arch.gpa_val = cr2_or_gpa;
6852+
}
6853+
} else {
6854+
/* Sanitize the address out of an abundance of paranoia. */
6855+
ctxt->exception.address = 0;
6856+
}
68446857

68456858
r = x86_emulate_insn(ctxt);
68466859

0 commit comments

Comments
 (0)