Skip to content

Commit c53bbe2

Browse files
Maxim Levitskybonzini
authored andcommitted
KVM: x86: SVM: don't passthrough SMAP/SMEP/PKE bits in !NPT && !gCR0.PG case
When the guest doesn't enable paging, and NPT/EPT is disabled, we use guest't paging CR3's as KVM's shadow paging pointer and we are technically in direct mode as if we were to use NPT/EPT. In direct mode we create SPTEs with user mode permissions because usually in the direct mode the NPT/EPT doesn't need to restrict access based on guest CPL (there are MBE/GMET extenstions for that but KVM doesn't use them). In this special "use guest paging as direct" mode however, and if CR4.SMAP/CR4.SMEP are enabled, that will make the CPU fault on each access and KVM will enter endless loop of page faults. Since page protection doesn't have any meaning in !PG case, just don't passthrough these bits. The fix is the same as was done for VMX in commit: commit 656ec4a ("KVM: VMX: fix SMEP and SMAP without EPT") This fixes the boot of windows 10 without NPT for good. (Without this patch, BSP boots, but APs were stuck in endless loop of page faults, causing the VM boot with 1 CPU) Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Cc: stable@vger.kernel.org Message-Id: <20220207155447.840194-2-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent dd4589e commit c53bbe2

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

arch/x86/kvm/svm/svm.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,7 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
15851585
{
15861586
struct vcpu_svm *svm = to_svm(vcpu);
15871587
u64 hcr0 = cr0;
1588+
bool old_paging = is_paging(vcpu);
15881589

15891590
#ifdef CONFIG_X86_64
15901591
if (vcpu->arch.efer & EFER_LME && !vcpu->arch.guest_state_protected) {
@@ -1601,8 +1602,11 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
16011602
#endif
16021603
vcpu->arch.cr0 = cr0;
16031604

1604-
if (!npt_enabled)
1605+
if (!npt_enabled) {
16051606
hcr0 |= X86_CR0_PG | X86_CR0_WP;
1607+
if (old_paging != is_paging(vcpu))
1608+
svm_set_cr4(vcpu, kvm_read_cr4(vcpu));
1609+
}
16061610

16071611
/*
16081612
* re-enable caching here because the QEMU bios
@@ -1646,8 +1650,12 @@ void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
16461650
svm_flush_tlb(vcpu);
16471651

16481652
vcpu->arch.cr4 = cr4;
1649-
if (!npt_enabled)
1653+
if (!npt_enabled) {
16501654
cr4 |= X86_CR4_PAE;
1655+
1656+
if (!is_paging(vcpu))
1657+
cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE);
1658+
}
16511659
cr4 |= host_cr4_mce;
16521660
to_svm(vcpu)->vmcb->save.cr4 = cr4;
16531661
vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);

0 commit comments

Comments
 (0)