Commit 02844ac1 authored by David Matlack's avatar David Matlack Committed by Paolo Bonzini

KVM: x86/mmu: Consolidate comments about {Host,MMU}-writable

Consolidate the large comment above DEFAULT_SPTE_HOST_WRITABLE with the
large comment above is_writable_pte() into one comment. This comment
explains the different reasons why an SPTE may be non-writable and KVM
keeps track of that with the {Host,MMU}-writable bits.

No functional change intended.
Signed-off-by: default avatarDavid Matlack <dmatlack@google.com>
Message-Id: <20220125230723.1701061-1-dmatlack@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 1ca87e01
...@@ -549,11 +549,9 @@ static u64 mmu_spte_update_no_track(u64 *sptep, u64 new_spte) ...@@ -549,11 +549,9 @@ static u64 mmu_spte_update_no_track(u64 *sptep, u64 new_spte)
/* Rules for using mmu_spte_update: /* Rules for using mmu_spte_update:
* Update the state bits, it means the mapped pfn is not changed. * Update the state bits, it means the mapped pfn is not changed.
* *
* Whenever we overwrite a writable spte with a read-only one we * Whenever an MMU-writable SPTE is overwritten with a read-only SPTE, remote
* should flush remote TLBs. Otherwise rmap_write_protect * TLBs must be flushed. Otherwise rmap_write_protect will find a read-only
* will find a read-only spte, even though the writable spte * spte, even though the writable spte might be cached on a CPU's TLB.
* might be cached on a CPU's TLB, the return value indicates this
* case.
* *
* Returns true if the TLB needs to be flushed * Returns true if the TLB needs to be flushed
*/ */
...@@ -5844,7 +5842,7 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, ...@@ -5844,7 +5842,7 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
* will clear a separate software-only bit (MMU-writable) and skip the * will clear a separate software-only bit (MMU-writable) and skip the
* flush if-and-only-if this bit was already clear. * flush if-and-only-if this bit was already clear.
* *
* See DEFAULT_SPTE_MMU_WRITABLE for more details. * See is_writable_pte() for more details.
*/ */
if (flush) if (flush)
kvm_arch_flush_remote_tlbs_memslot(kvm, memslot); kvm_arch_flush_remote_tlbs_memslot(kvm, memslot);
......
...@@ -75,28 +75,8 @@ static_assert(SPTE_TDP_AD_ENABLED_MASK == 0); ...@@ -75,28 +75,8 @@ static_assert(SPTE_TDP_AD_ENABLED_MASK == 0);
static_assert(!(SPTE_TDP_AD_MASK & SHADOW_ACC_TRACK_SAVED_MASK)); static_assert(!(SPTE_TDP_AD_MASK & SHADOW_ACC_TRACK_SAVED_MASK));
/* /*
* *_SPTE_HOST_WRITABLE (aka Host-writable) indicates whether the host permits * {DEFAULT,EPT}_SPTE_{HOST,MMU}_WRITABLE are used to keep track of why a given
* writes to the guest page mapped by the SPTE. This bit is cleared on SPTEs * SPTE is write-protected. See is_writable_pte() for details.
* that map guest pages in read-only memslots and read-only VMAs.
*
* Invariants:
* - If Host-writable is clear, PT_WRITABLE_MASK must be clear.
*
*
* *_SPTE_MMU_WRITABLE (aka MMU-writable) indicates whether the shadow MMU
* allows writes to the guest page mapped by the SPTE. This bit is cleared when
* the guest page mapped by the SPTE contains a page table that is being
* monitored for shadow paging. In this case the SPTE can only be made writable
* by unsyncing the shadow page under the mmu_lock.
*
* Invariants:
* - If MMU-writable is clear, PT_WRITABLE_MASK must be clear.
* - If MMU-writable is set, Host-writable must be set.
*
* If MMU-writable is set, PT_WRITABLE_MASK is normally set but can be cleared
* to track writes for dirty logging. For such SPTEs, KVM will locklessly set
* PT_WRITABLE_MASK upon the next write from the guest and record the write in
* the dirty log (see fast_page_fault()).
*/ */
/* Bits 9 and 10 are ignored by all non-EPT PTEs. */ /* Bits 9 and 10 are ignored by all non-EPT PTEs. */
...@@ -340,37 +320,64 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check, ...@@ -340,37 +320,64 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
} }
/* /*
* Currently, we have two sorts of write-protection, a) the first one * An shadow-present leaf SPTE may be non-writable for 3 possible reasons:
* write-protects guest page to sync the guest modification, b) another one is *
* used to sync dirty bitmap when we do KVM_GET_DIRTY_LOG. The differences * 1. To intercept writes for dirty logging. KVM write-protects huge pages
* between these two sorts are: * so that they can be split be split down into the dirty logging
* 1) the first case clears MMU-writable bit. * granularity (4KiB) whenever the guest writes to them. KVM also
* 2) the first case requires flushing tlb immediately avoiding corrupting * write-protects 4KiB pages so that writes can be recorded in the dirty log
* shadow page table between all vcpus so it should be in the protection of * (e.g. if not using PML). SPTEs are write-protected for dirty logging
* mmu-lock. And the another case does not need to flush tlb until returning * during the VM-iotcls that enable dirty logging.
* the dirty bitmap to userspace since it only write-protects the page *
* logged in the bitmap, that means the page in the dirty bitmap is not * 2. To intercept writes to guest page tables that KVM is shadowing. When a
* missed, so it can flush tlb out of mmu-lock. * guest writes to its page table the corresponding shadow page table will
* be marked "unsync". That way KVM knows which shadow page tables need to
* be updated on the next TLB flush, INVLPG, etc. and which do not.
*
* 3. To prevent guest writes to read-only memory, such as for memory in a
* read-only memslot or guest memory backed by a read-only VMA. Writes to
* such pages are disallowed entirely.
*
* To keep track of why a given SPTE is write-protected, KVM uses 2
* software-only bits in the SPTE:
*
* shadow_mmu_writable_mask, aka MMU-writable -
* Cleared on SPTEs that KVM is currently write-protecting for shadow paging
* purposes (case 2 above).
*
* shadow_host_writable_mask, aka Host-writable -
* Cleared on SPTEs that are not host-writable (case 3 above)
*
* Note, not all possible combinations of PT_WRITABLE_MASK,
* shadow_mmu_writable_mask, and shadow_host_writable_mask are valid. A given
* SPTE can be in only one of the following states, which map to the
* aforementioned 3 cases:
*
* shadow_host_writable_mask | shadow_mmu_writable_mask | PT_WRITABLE_MASK
* ------------------------- | ------------------------ | ----------------
* 1 | 1 | 1 (writable)
* 1 | 1 | 0 (case 1)
* 1 | 0 | 0 (case 2)
* 0 | 0 | 0 (case 3)
* *
* So, there is the problem: the first case can meet the corrupted tlb caused * The valid combinations of these bits are checked by
* by another case which write-protects pages but without flush tlb * check_spte_writable_invariants() whenever an SPTE is modified.
* immediately. In order to making the first case be aware this problem we let
* it flush tlb if we try to write-protect a spte whose MMU-writable bit
* is set, it works since another case never touches MMU-writable bit.
* *
* Anyway, whenever a spte is updated (only permission and status bits are * Clearing the MMU-writable bit is always done under the MMU lock and always
* changed) we need to check whether the spte with MMU-writable becomes * accompanied by a TLB flush before dropping the lock to avoid corrupting the
* readonly, if that happens, we need to flush tlb. Fortunately, * shadow page tables between vCPUs. Write-protecting an SPTE for dirty logging
* mmu_spte_update() has already handled it perfectly. * (which does not clear the MMU-writable bit), does not flush TLBs before
* dropping the lock, as it only needs to synchronize guest writes with the
* dirty bitmap.
* *
* The rules to use MMU-writable and PT_WRITABLE_MASK: * So, there is the problem: clearing the MMU-writable bit can encounter a
* - if we want to see if it has writable tlb entry or if the spte can be * write-protected SPTE while CPUs still have writable mappings for that SPTE
* writable on the mmu mapping, check MMU-writable, this is the most * cached in their TLB. To address this, KVM always flushes TLBs when
* case, otherwise * write-protecting SPTEs if the MMU-writable bit is set on the old SPTE.
* - if we fix page fault on the spte or do write-protection by dirty logging,
* check PT_WRITABLE_MASK.
* *
* TODO: introduce APIs to split these two cases. * The Host-writable bit is not modified on present SPTEs, it is only set or
* cleared when an SPTE is first faulted in from non-present and then remains
* immutable.
*/ */
static inline bool is_writable_pte(unsigned long pte) static inline bool is_writable_pte(unsigned long pte)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment