[PATCH 0/4] KVM: x86/mmu: MMIO caching bug fixes

Sean Christopherson posted 4 patches 3 years, 8 months ago
There is a newer version of this series
arch/x86/include/asm/kvm_host.h |  2 +-
arch/x86/kvm/mmu.h              |  2 ++
arch/x86/kvm/mmu/mmu.c          |  6 +++++-
arch/x86/kvm/mmu/spte.c         | 20 ++++++++++++++++++++
arch/x86/kvm/mmu/spte.h         |  3 +--
arch/x86/kvm/svm/sev.c          | 10 ++++++++++
arch/x86/kvm/svm/svm.c          |  9 ++++++---
7 files changed, 45 insertions(+), 7 deletions(-)
[PATCH 0/4] KVM: x86/mmu: MMIO caching bug fixes
Posted by Sean Christopherson 3 years, 8 months ago
Fix two bugs I introduced when adding the enable_mmio_caching module param.

Bug #1 is that KVM unintentionally makes disabling caching due to a config
incompatibility "sticky", e.g. disabling caching because there are no
reserved PA bits prevents KVM from enabling when "switching" to an EPT
config (doesn't rely on PA bits) or when SVM adjusts the MMIO masks to
account for C-bit shenanigans (even if MAXPHYADDR=52 and C-bit=51, there
can be reserved PA bits due to the "real" MAXPHYADDR being reduced).

Bug #2 is that KVM doesn't explicitly check that MMIO caching is enabled
when doing SEV-ES setup.  Prior to the module param, MMIO caching was
guaranteed when SEV-ES could be enabled as SEV-ES-capable CPUs effectively
guarantee there will be at least one reserved PA bit (see above).  With
the module param, userspace can explicitly disable MMIO caching, thus
silently breaking SEV-ES.

I believe I tested all combinations of things getting disabled and enabled
by hacking kvm_mmu_reset_all_pte_masks() to disable MMIO caching on a much
lower MAXPHYADDR, e.g. 43 instead of 52.  That said, definitely wait for a
thumbs up from the AMD folks before queueing.

Sean Christopherson (4):
  KVM: x86: Tag kvm_mmu_x86_module_init() with __init
  KVM: x86/mmu: Fully re-evaluate MMIO caching when SPTE masks change
  KVM: SVM: Adjust MMIO masks (for caching) before doing SEV(-ES) setup
  KVM: SVM: Disable SEV-ES support if MMIO caching is disable

 arch/x86/include/asm/kvm_host.h |  2 +-
 arch/x86/kvm/mmu.h              |  2 ++
 arch/x86/kvm/mmu/mmu.c          |  6 +++++-
 arch/x86/kvm/mmu/spte.c         | 20 ++++++++++++++++++++
 arch/x86/kvm/mmu/spte.h         |  3 +--
 arch/x86/kvm/svm/sev.c          | 10 ++++++++++
 arch/x86/kvm/svm/svm.c          |  9 ++++++---
 7 files changed, 45 insertions(+), 7 deletions(-)


base-commit: 1a4d88a361af4f2e91861d632c6a1fe87a9665c2
-- 
2.37.1.455.g008518b4e5-goog
Re: [PATCH 0/4] KVM: x86/mmu: MMIO caching bug fixes
Posted by Michael Roth 3 years, 8 months ago
On Thu, Jul 28, 2022 at 10:17:55PM +0000, Sean Christopherson wrote:
> Fix two bugs I introduced when adding the enable_mmio_caching module param.
> 
> Bug #1 is that KVM unintentionally makes disabling caching due to a config
> incompatibility "sticky", e.g. disabling caching because there are no
> reserved PA bits prevents KVM from enabling when "switching" to an EPT
> config (doesn't rely on PA bits) or when SVM adjusts the MMIO masks to
> account for C-bit shenanigans (even if MAXPHYADDR=52 and C-bit=51, there
> can be reserved PA bits due to the "real" MAXPHYADDR being reduced).
> 
> Bug #2 is that KVM doesn't explicitly check that MMIO caching is enabled
> when doing SEV-ES setup.  Prior to the module param, MMIO caching was
> guaranteed when SEV-ES could be enabled as SEV-ES-capable CPUs effectively
> guarantee there will be at least one reserved PA bit (see above).  With
> the module param, userspace can explicitly disable MMIO caching, thus
> silently breaking SEV-ES.
> 
> I believe I tested all combinations of things getting disabled and enabled
> by hacking kvm_mmu_reset_all_pte_masks() to disable MMIO caching on a much
> lower MAXPHYADDR, e.g. 43 instead of 52.  That said, definitely wait for a
> thumbs up from the AMD folks before queueing.

I tested the below systems/configurations and everything looks good
to me.  Thanks for the quick fix!

  AMD Milan, MAXPHYADDR = 48 bits, kvm.mmio_caching=on (on by default)
  normal: pass
  SEV:    pass
  SEV-ES: pass
  
  AMD Milan, MAXPHYADDR = 48 bits, kvm.mmio_caching=off
  normal: pass
  SEV:    pass
  SEV-ES: fail (as expected, since kvm_amd.sev_es gets forced to off)
  
  AMD unreleased, MAXPHYADDR = 52 bits, kvm.mmio_caching=on (on by default)
  normal: pass
  SEV:    pass
  SEV-ES: pass
  
  AMD unreleased, MAXPHYADDR = 52 bits, kvm.mmio_caching=off
  normal: pass
  SEV:    pass
  SEV-ES: fail (as expected, since kvm_amd.sev_es gets forced to off)

> 
> Sean Christopherson (4):
>   KVM: x86: Tag kvm_mmu_x86_module_init() with __init
>   KVM: x86/mmu: Fully re-evaluate MMIO caching when SPTE masks change
>   KVM: SVM: Adjust MMIO masks (for caching) before doing SEV(-ES) setup
>   KVM: SVM: Disable SEV-ES support if MMIO caching is disable

Series:

Tested-by: Michael Roth <michael.roth@amd.com>

-Mike