[PATCH 03/22] KVM: x86/mmu: adjust MMIO generation bit allocation and allowed mask

Paolo Bonzini posted 22 patches 2 weeks ago
There is a newer version of this series
[PATCH 03/22] KVM: x86/mmu: adjust MMIO generation bit allocation and allowed mask
Posted by Paolo Bonzini 2 weeks ago
From: Jon Kohler <jon@nutanix.com>

Update SPTE_MMIO_ALLOWED_MASK to allow EPT user executable (bit 10) to
be treated like EPT RWX bit2:0, as when mode-based execute control is
enabled, bit 10 can act like a "present" bit.

No functional changes intended.

Cc: Kai Huang <kai.huang@intel.com>
Signed-off-by: Jon Kohler <jon@nutanix.com>
Message-ID: <20251223054806.1611168-4-jon@nutanix.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/mmu/spte.h | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h
index 0fc83c9064c5..b60666778f61 100644
--- a/arch/x86/kvm/mmu/spte.h
+++ b/arch/x86/kvm/mmu/spte.h
@@ -96,11 +96,11 @@ static_assert(!(EPT_SPTE_MMU_WRITABLE & SHADOW_ACC_TRACK_SAVED_MASK));
 #undef SHADOW_ACC_TRACK_SAVED_MASK
 
 /*
- * Due to limited space in PTEs, the MMIO generation is a 19 bit subset of
+ * Due to limited space in PTEs, the MMIO generation is an 18 bit subset of
  * the memslots generation and is derived as follows:
  *
- * Bits 0-7 of the MMIO generation are propagated to spte bits 3-10
- * Bits 8-18 of the MMIO generation are propagated to spte bits 52-62
+ * Bits 0-6 of the MMIO generation are propagated to spte bits 3-9
+ * Bits 7-17 of the MMIO generation are propagated to spte bits 52-62
  *
  * The KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS flag is intentionally not included in
  * the MMIO generation number, as doing so would require stealing a bit from
@@ -111,7 +111,7 @@ static_assert(!(EPT_SPTE_MMU_WRITABLE & SHADOW_ACC_TRACK_SAVED_MASK));
  */
 
 #define MMIO_SPTE_GEN_LOW_START		3
-#define MMIO_SPTE_GEN_LOW_END		10
+#define MMIO_SPTE_GEN_LOW_END		9
 
 #define MMIO_SPTE_GEN_HIGH_START	52
 #define MMIO_SPTE_GEN_HIGH_END		62
@@ -133,7 +133,8 @@ static_assert(!(SPTE_MMU_PRESENT_MASK &
  * 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))
+#define SPTE_MMIO_ALLOWED_MASK (BIT_ULL(63) | GENMASK_ULL(51, 12) | \
+				BIT_ULL(10) | GENMASK_ULL(2, 0))
 static_assert(!(SPTE_MMIO_ALLOWED_MASK &
 		(SPTE_MMU_PRESENT_MASK | MMIO_SPTE_GEN_LOW_MASK | MMIO_SPTE_GEN_HIGH_MASK)));
 
@@ -141,7 +142,7 @@ static_assert(!(SPTE_MMIO_ALLOWED_MASK &
 #define MMIO_SPTE_GEN_HIGH_BITS		(MMIO_SPTE_GEN_HIGH_END - MMIO_SPTE_GEN_HIGH_START + 1)
 
 /* remember to adjust the comment above as well if you change these */
-static_assert(MMIO_SPTE_GEN_LOW_BITS == 8 && MMIO_SPTE_GEN_HIGH_BITS == 11);
+static_assert(MMIO_SPTE_GEN_LOW_BITS == 7 && MMIO_SPTE_GEN_HIGH_BITS == 11);
 
 #define MMIO_SPTE_GEN_LOW_SHIFT		(MMIO_SPTE_GEN_LOW_START - 0)
 #define MMIO_SPTE_GEN_HIGH_SHIFT	(MMIO_SPTE_GEN_HIGH_START - MMIO_SPTE_GEN_LOW_BITS)
-- 
2.52.0
Re: [PATCH 03/22] KVM: x86/mmu: adjust MMIO generation bit allocation and allowed mask
Posted by Huang, Kai 1 week, 3 days ago
>  /*
> - * Due to limited space in PTEs, the MMIO generation is a 19 bit subset of
> + * Due to limited space in PTEs, the MMIO generation is an 18 bit subset of
>   * the memslots generation and is derived as follows:

Is "a -> an" unintentional change?

>   *
> - * Bits 0-7 of the MMIO generation are propagated to spte bits 3-10
> - * Bits 8-18 of the MMIO generation are propagated to spte bits 52-62
> + * Bits 0-6 of the MMIO generation are propagated to spte bits 3-9
> + * Bits 7-17 of the MMIO generation are propagated to spte bits 52-62
>   *
>   * The KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS flag is intentionally not included in
>   * the MMIO generation number, as doing so would require stealing a bit from
> @@ -111,7 +111,7 @@ static_assert(!(EPT_SPTE_MMU_WRITABLE & SHADOW_ACC_TRACK_SAVED_MASK));
>   */
>  
>  #define MMIO_SPTE_GEN_LOW_START		3
> -#define MMIO_SPTE_GEN_LOW_END		10
> +#define MMIO_SPTE_GEN_LOW_END		9
>  
>  #define MMIO_SPTE_GEN_HIGH_START	52
>  #define MMIO_SPTE_GEN_HIGH_END		62
> @@ -133,7 +133,8 @@ static_assert(!(SPTE_MMU_PRESENT_MASK &
>   * 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))
> +#define SPTE_MMIO_ALLOWED_MASK (BIT_ULL(63) | GENMASK_ULL(51, 12) | \
> +				BIT_ULL(10) | GENMASK_ULL(2, 0))
>  static_assert(!(SPTE_MMIO_ALLOWED_MASK &
>  		(SPTE_MMU_PRESENT_MASK | MMIO_SPTE_GEN_LOW_MASK | MMIO_SPTE_GEN_HIGH_MASK)));
>  
> @@ -141,7 +142,7 @@ static_assert(!(SPTE_MMIO_ALLOWED_MASK &
>  #define MMIO_SPTE_GEN_HIGH_BITS		(MMIO_SPTE_GEN_HIGH_END - MMIO_SPTE_GEN_HIGH_START + 1)
>  
>  /* remember to adjust the comment above as well if you change these */
> -static_assert(MMIO_SPTE_GEN_LOW_BITS == 8 && MMIO_SPTE_GEN_HIGH_BITS == 11);
> +static_assert(MMIO_SPTE_GEN_LOW_BITS == 7 && MMIO_SPTE_GEN_HIGH_BITS == 11);
>  
>  #define MMIO_SPTE_GEN_LOW_SHIFT		(MMIO_SPTE_GEN_LOW_START - 0)
>  #define MMIO_SPTE_GEN_HIGH_SHIFT	(MMIO_SPTE_GEN_HIGH_START - MMIO_SPTE_GEN_LOW_BITS)

Besides the changes to MMIO_GEN, the FROZEN_SPTE seems to have bit 10 set:

    #define FROZEN_SPTE (SHADOW_NONPRESENT_VALUE | 0x5a0ULL)

When MBEC is enabled, IIUC such SPTE will be treated as present by hardware
if CPU supports execution-only SPTE.

Also, when MBEC is enabled, per SDM if CPU doesn't support execution-only,
an SPTE with bit 0 clear but with bit 10 set will trigger EPT
miscofiguration, rather than EPT violation.

So seems we should exclude bit 10 from FROZEN_SPTE.

Re: [PATCH 03/22] KVM: x86/mmu: adjust MMIO generation bit allocation and allowed mask
Posted by Paolo Bonzini 1 week, 3 days ago
On 3/24/26 04:48, Huang, Kai wrote:
> 
>>   /*
>> - * Due to limited space in PTEs, the MMIO generation is a 19 bit subset of
>> + * Due to limited space in PTEs, the MMIO generation is an 18 bit subset of
>>    * the memslots generation and is derived as follows:
> 
> Is "a -> an" unintentional change?

No, "a nineteen-bit" -> "an eighteen-bit". :)

> Besides the changes to MMIO_GEN, the FROZEN_SPTE seems to have bit 10 set:
> 
>      #define FROZEN_SPTE (SHADOW_NONPRESENT_VALUE | 0x5a0ULL)
> 
> When MBEC is enabled, IIUC such SPTE will be treated as present by hardware
> if CPU supports execution-only SPTE.
> 
> Also, when MBEC is enabled, per SDM if CPU doesn't support execution-only,
> an SPTE with bit 0 clear but with bit 10 set will trigger EPT
> miscofiguration, rather than EPT violation.
> 
> So seems we should exclude bit 10 from FROZEN_SPTE.

True, good catch (so 0x5a0 should become 0x1a0).

Paolo