From e1548088ff544e4a4ae2c960bccf0eeff3a46297 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 8 Mar 2024 17:09:26 -0800 Subject: [PATCH] KVM: VMX: Drop support for forcing UC memory when guest CR0.CD=1 Drop KVM's emulation of CR0.CD=1 on Intel CPUs now that KVM no longer honors guest MTRR memtypes, as forcing UC memory for VMs with non-coherent DMA only makes sense if the guest is using something other than PAT to configure the memtype for the DMA region. Furthermore, KVM has forced WB memory for CR0.CD=1 since commit fb279950ba02 ("KVM: vmx: obey KVM_QUIRK_CD_NW_CLEARED"), and no known VMM in existence disables KVM_X86_QUIRK_CD_NW_CLEARED, let alone does so with non-coherent DMA. Lastly, commit fb279950ba02 ("KVM: vmx: obey KVM_QUIRK_CD_NW_CLEARED") was from the same author as commit b18d5431acc7 ("KVM: x86: fix CR0.CD virtualization"), and followed by a mere month. I.e. forcing UC memory was likely the result of code inspection or perhaps misdiagnosed failures, and not the necessitate by a concrete use case. Update KVM's documentation to note that KVM_X86_QUIRK_CD_NW_CLEARED is now AMD-only, and to take an erratum for lack of CR0.CD virtualization on Intel. Tested-by: Xiangfei Ma Tested-by: Yongwei Ma Link: https://lore.kernel.org/r/20240309010929.1403984-3-seanjc@google.com Signed-off-by: Sean Christopherson --- Documentation/virt/kvm/api.rst | 6 +++++- Documentation/virt/kvm/x86/errata.rst | 19 +++++++++++++++---- arch/x86/kvm/vmx/vmx.c | 4 ---- arch/x86/kvm/x86.c | 6 ------ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index a71d91978d9e..298167363706 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7953,7 +7953,11 @@ The valid bits in cap.args[0] are: When this quirk is disabled, the reset value is 0x10000 (APIC_LVT_MASKED). - KVM_X86_QUIRK_CD_NW_CLEARED By default, KVM clears CR0.CD and CR0.NW. + KVM_X86_QUIRK_CD_NW_CLEARED By default, KVM clears CR0.CD and CR0.NW on + AMD CPUs to workaround buggy guest firmware + that runs in perpetuity with CR0.CD, i.e. + with caches in "no fill" mode. + When this quirk is disabled, KVM does not change the value of CR0.CD and CR0.NW. diff --git a/Documentation/virt/kvm/x86/errata.rst b/Documentation/virt/kvm/x86/errata.rst index 1b70bad7325e..4116045a8744 100644 --- a/Documentation/virt/kvm/x86/errata.rst +++ b/Documentation/virt/kvm/x86/errata.rst @@ -51,7 +51,18 @@ matching the target APIC ID receive the interrupt). MTRRs ----- -KVM does not virtualization guest MTRR memory types. KVM emulates accesses to -MTRR MSRs, i.e. {RD,WR}MSR in the guest will behave as expected, but KVM does -not honor guest MTRRs when determining the effective memory type, and instead -treats all of guest memory as having Writeback (WB) MTRRs. \ No newline at end of file +KVM does not virtualize guest MTRR memory types. KVM emulates accesses to MTRR +MSRs, i.e. {RD,WR}MSR in the guest will behave as expected, but KVM does not +honor guest MTRRs when determining the effective memory type, and instead +treats all of guest memory as having Writeback (WB) MTRRs. + +CR0.CD +------ +KVM does not virtualize CR0.CD on Intel CPUs. Similar to MTRR MSRs, KVM +emulates CR0.CD accesses so that loads and stores from/to CR0 behave as +expected, but setting CR0.CD=1 has no impact on the cachaeability of guest +memory. + +Note, this erratum does not affect AMD CPUs, which fully virtualize CR0.CD in +hardware, i.e. put the CPU caches into "no fill" mode when CR0.CD=1, even when +running in the guest. \ No newline at end of file diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index dec3de308ea8..a3cc0bc30540 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7674,10 +7674,6 @@ u8 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IPAT_BIT; - if (kvm_read_cr0_bits(vcpu, X86_CR0_CD) && - !kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED)) - return (MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IPAT_BIT; - return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8e83c5decc81..869cfaa980bd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -963,12 +963,6 @@ void kvm_post_set_cr0(struct kvm_vcpu *vcpu, unsigned long old_cr0, unsigned lon if ((cr0 ^ old_cr0) & KVM_MMU_CR0_ROLE_BITS) kvm_mmu_reset_context(vcpu); - - if (((cr0 ^ old_cr0) & X86_CR0_CD) && - kvm_mmu_may_ignore_guest_pat() && - kvm_arch_has_noncoherent_dma(vcpu->kvm) && - !kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED)) - kvm_zap_gfn_range(vcpu->kvm, 0, ~0ULL); } EXPORT_SYMBOL_GPL(kvm_post_set_cr0); -- 2.50.1