]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: x86/mmu: Add sanity check that MMIO SPTE mask doesn't overlap gen
authorSean Christopherson <seanjc@google.com>
Fri, 5 Aug 2022 19:41:33 +0000 (19:41 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 10 Aug 2022 19:08:26 +0000 (15:08 -0400)
Add compile-time and init-time sanity checks to ensure that the MMIO SPTE
mask doesn't overlap the MMIO SPTE generation or the MMU-present bit.
The generation currently avoids using bit 63, but that's as much
coincidence as it is strictly necessarly.  That will change in the future,
as TDX support will require setting bit 63 (SUPPRESS_VE) in the mask.

Explicitly carve out the bits that are allowed in the mask so that any
future shuffling of SPTE bits doesn't silently break MMIO caching (KVM
has broken MMIO caching more than once due to overlapping the generation
with other things).

Suggested-by: Kai Huang <kai.huang@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Kai Huang <kai.huang@intel.com>
Message-Id: <20220805194133.86299-1-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/mmu/spte.c
arch/x86/kvm/mmu/spte.h

index 03ca740bf7212a5c7803419039a38474ebe0c338..2e08b2a45361299fe071de8f766533b2d8dcecb6 100644 (file)
@@ -363,6 +363,14 @@ void kvm_mmu_set_mmio_spte_mask(u64 mmio_value, u64 mmio_mask, u64 access_mask)
        if (!enable_mmio_caching)
                mmio_value = 0;
 
+       /*
+        * The mask must contain only bits that are carved out specifically for
+        * the MMIO SPTE mask, e.g. to ensure there's no overlap with the MMIO
+        * generation.
+        */
+       if (WARN_ON(mmio_mask & ~SPTE_MMIO_ALLOWED_MASK))
+               mmio_value = 0;
+
        /*
         * Disable MMIO caching if the MMIO value collides with the bits that
         * are used to hold the relocated GFN when the L1TF mitigation is
index 9a9414b8d1d69c425790f9b32e5172231391a01e..f3744eea45f5dbb000240a688a81974f3e9a03db 100644 (file)
@@ -123,6 +123,20 @@ static_assert(!(EPT_SPTE_MMU_WRITABLE & SHADOW_ACC_TRACK_SAVED_MASK));
 static_assert(!(SPTE_MMU_PRESENT_MASK &
                (MMIO_SPTE_GEN_LOW_MASK | MMIO_SPTE_GEN_HIGH_MASK)));
 
+/*
+ * The SPTE MMIO mask must NOT overlap the MMIO generation bits or the
+ * MMU-present bit.  The generation obviously co-exists with the magic MMIO
+ * mask/value, and MMIO SPTEs are considered !MMU-present.
+ *
+ * The SPTE MMIO mask is allowed to use hardware "present" bits (i.e. all EPT
+ * RWX bits), all physical address bits (legal PA bits are used for "fast" MMIO
+ * and so they're off-limits for generation; additional checks ensure the mask
+ * doesn't overlap legal PA bits), and bit 63 (carved out for future usage).
+ */
+#define SPTE_MMIO_ALLOWED_MASK (BIT_ULL(63) | GENMASK_ULL(51, 12) | GENMASK_ULL(2, 0))
+static_assert(!(SPTE_MMIO_ALLOWED_MASK &
+               (SPTE_MMU_PRESENT_MASK | MMIO_SPTE_GEN_LOW_MASK | MMIO_SPTE_GEN_HIGH_MASK)));
+
 #define MMIO_SPTE_GEN_LOW_BITS         (MMIO_SPTE_GEN_LOW_END - MMIO_SPTE_GEN_LOW_START + 1)
 #define MMIO_SPTE_GEN_HIGH_BITS                (MMIO_SPTE_GEN_HIGH_END - MMIO_SPTE_GEN_HIGH_START + 1)