KVM: VMX: Skip #PF(RSVD) intercepts when emulating smaller maxphyaddr

As part of smaller maxphyaddr emulation, kvm needs to intercept
present page faults to see if it needs to add the RSVD flag (bit 3) to
the error code. However, there is no need to intercept page faults
that already have the RSVD flag set. When setting up the page fault
intercept, add the RSVD flag into the #PF error code mask field (but
not the #PF error code match field) to skip the intercept when the
RSVD flag is already set.

Signed-off-by: Jim Mattson <jmattson@google.com>
Message-Id: <20210618235941.1041604-1-jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Jim Mattson 2021-06-18 16:59:41 -07:00 коммит произвёл Paolo Bonzini
Родитель 0485cf8dbe
Коммит 5140bc7d6b
1 изменённых файлов: 14 добавлений и 9 удалений

Просмотреть файл

@ -747,16 +747,21 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu)
if (is_guest_mode(vcpu))
eb |= get_vmcs12(vcpu)->exception_bitmap;
else {
/*
* If EPT is enabled, #PF is only trapped if MAXPHYADDR is mismatched
* between guest and host. In that case we only care about present
* faults. For vmcs02, however, PFEC_MASK and PFEC_MATCH are set in
* prepare_vmcs02_rare.
*/
bool selective_pf_trap = enable_ept && (eb & (1u << PF_VECTOR));
int mask = selective_pf_trap ? PFERR_PRESENT_MASK : 0;
int mask = 0, match = 0;
if (enable_ept && (eb & (1u << PF_VECTOR))) {
/*
* If EPT is enabled, #PF is currently only intercepted
* if MAXPHYADDR is smaller on the guest than on the
* host. In that case we only care about present,
* non-reserved faults. For vmcs02, however, PFEC_MASK
* and PFEC_MATCH are set in prepare_vmcs02_rare.
*/
mask = PFERR_PRESENT_MASK | PFERR_RSVD_MASK;
match = PFERR_PRESENT_MASK;
}
vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, mask);
vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, mask);
vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, match);
}
vmcs_write32(EXCEPTION_BITMAP, eb);