mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 23:27:06 +00:00
KVM: x86/mmu: Use high bits for host/mmu writable masks for EPT SPTEs
Use bits 57 and 58 for HOST_WRITABLE and MMU_WRITABLE when using EPT. This will allow using bit 11 as a constant MMU_PRESENT, which is desirable as checking for a shadow-present SPTE is one of the most common SPTE operations in KVM, particular in hot paths such as page faults. EPT is short on low available bits; currently only bit 11 is the only always-available bit. Bit 10 is also available, but only while KVM doesn't support mode-based execution. On the other hand, PAE paging doesn't have _any_ high available bits. Thus, using bit 11 is the only feasible option for MMU_PRESENT. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20210225204749.1512652-20-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
5fc3424f8b
commit
613a3f3797
2 changed files with 36 additions and 15 deletions
|
@ -295,6 +295,9 @@ void kvm_mmu_set_ept_masks(bool has_ad_bits, bool has_exec_only)
|
|||
shadow_acc_track_mask = VMX_EPT_RWX_MASK;
|
||||
shadow_me_mask = 0ull;
|
||||
|
||||
shadow_host_writable_mask = EPT_SPTE_HOST_WRITABLE;
|
||||
shadow_mmu_writable_mask = EPT_SPTE_MMU_WRITABLE;
|
||||
|
||||
/*
|
||||
* EPT Misconfigurations are generated if the value of bits 2:0
|
||||
* of an EPT paging-structure entry is 110b (write/execute).
|
||||
|
|
|
@ -57,8 +57,39 @@ static_assert(SPTE_TDP_AD_ENABLED_MASK == 0);
|
|||
(((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1))
|
||||
#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
|
||||
|
||||
#define DEFAULT_SPTE_HOST_WRITEABLE BIT_ULL(10)
|
||||
#define DEFAULT_SPTE_MMU_WRITEABLE BIT_ULL(11)
|
||||
/* Bits 9 and 10 are ignored by all non-EPT PTEs. */
|
||||
#define DEFAULT_SPTE_HOST_WRITEABLE BIT_ULL(9)
|
||||
#define DEFAULT_SPTE_MMU_WRITEABLE BIT_ULL(10)
|
||||
|
||||
/*
|
||||
* The mask/shift to use for saving the original R/X bits when marking the PTE
|
||||
* as not-present for access tracking purposes. We do not save the W bit as the
|
||||
* PTEs being access tracked also need to be dirty tracked, so the W bit will be
|
||||
* restored only when a write is attempted to the page. This mask obviously
|
||||
* must not overlap the A/D type mask.
|
||||
*/
|
||||
#define SHADOW_ACC_TRACK_SAVED_BITS_MASK (PT64_EPT_READABLE_MASK | \
|
||||
PT64_EPT_EXECUTABLE_MASK)
|
||||
#define SHADOW_ACC_TRACK_SAVED_BITS_SHIFT 54
|
||||
#define SHADOW_ACC_TRACK_SAVED_MASK (SHADOW_ACC_TRACK_SAVED_BITS_MASK << \
|
||||
SHADOW_ACC_TRACK_SAVED_BITS_SHIFT)
|
||||
static_assert(!(SPTE_TDP_AD_MASK & SHADOW_ACC_TRACK_SAVED_MASK));
|
||||
|
||||
/*
|
||||
* Low ignored bits are at a premium for EPT, use high ignored bits, taking care
|
||||
* to not overlap the A/D type mask or the saved access bits of access-tracked
|
||||
* SPTEs when A/D bits are disabled.
|
||||
*/
|
||||
#define EPT_SPTE_HOST_WRITABLE BIT_ULL(57)
|
||||
#define EPT_SPTE_MMU_WRITABLE BIT_ULL(58)
|
||||
|
||||
static_assert(!(EPT_SPTE_HOST_WRITABLE & SPTE_TDP_AD_MASK));
|
||||
static_assert(!(EPT_SPTE_MMU_WRITABLE & SPTE_TDP_AD_MASK));
|
||||
static_assert(!(EPT_SPTE_HOST_WRITABLE & SHADOW_ACC_TRACK_SAVED_MASK));
|
||||
static_assert(!(EPT_SPTE_MMU_WRITABLE & SHADOW_ACC_TRACK_SAVED_MASK));
|
||||
|
||||
/* Defined only to keep the above static asserts readable. */
|
||||
#undef SHADOW_ACC_TRACK_SAVED_MASK
|
||||
|
||||
/*
|
||||
* Due to limited space in PTEs, the MMIO generation is a 20 bit subset of
|
||||
|
@ -128,19 +159,6 @@ extern u64 __read_mostly shadow_nonpresent_or_rsvd_mask;
|
|||
*/
|
||||
#define SHADOW_NONPRESENT_OR_RSVD_MASK_LEN 5
|
||||
|
||||
/*
|
||||
* The mask/shift to use for saving the original R/X bits when marking the PTE
|
||||
* as not-present for access tracking purposes. We do not save the W bit as the
|
||||
* PTEs being access tracked also need to be dirty tracked, so the W bit will be
|
||||
* restored only when a write is attempted to the page. This mask obviously
|
||||
* must not overlap the A/D type mask.
|
||||
*/
|
||||
#define SHADOW_ACC_TRACK_SAVED_BITS_MASK (PT64_EPT_READABLE_MASK | \
|
||||
PT64_EPT_EXECUTABLE_MASK)
|
||||
#define SHADOW_ACC_TRACK_SAVED_BITS_SHIFT 54
|
||||
static_assert(!(SPTE_TDP_AD_MASK & (SHADOW_ACC_TRACK_SAVED_BITS_MASK <<
|
||||
SHADOW_ACC_TRACK_SAVED_BITS_SHIFT)));
|
||||
|
||||
/*
|
||||
* If a thread running without exclusive control of the MMU lock must perform a
|
||||
* multi-part operation on an SPTE, it can set the SPTE to REMOVED_SPTE as a
|
||||
|
|
Loading…
Reference in a new issue