kvm: x86: mmu: Introduce a no-tracking version of mmu_spte_update
authorJunaid Shahid <junaids@google.com>
Wed, 7 Dec 2016 00:46:14 +0000 (16:46 -0800)
committerRadim Krčmář <rkrcmar@redhat.com>
Mon, 9 Jan 2017 13:46:09 +0000 (14:46 +0100)
mmu_spte_update() tracks changes in the accessed/dirty state of
the SPTE being updated and calls kvm_set_pfn_accessed/dirty
appropriately. However, in some cases (e.g. when aging the SPTE),
this shouldn't be done. mmu_spte_update_no_track() is introduced
for use in such cases.

Signed-off-by: Junaid Shahid <junaids@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/mmu.c

index cfef959693355ca45008cccd348a66d7b0f2de4a..b8b5259c8ebb2615c5b0712574a7988299a53a3b 100644 (file)
@@ -528,27 +528,19 @@ static void mmu_spte_set(u64 *sptep, u64 new_spte)
        __set_spte(sptep, new_spte);
 }
 
-/* Rules for using mmu_spte_update:
- * Update the state bits, it means the mapped pfn is not changed.
- *
- * Whenever we overwrite a writable spte with a read-only one we
- * should flush remote TLBs. Otherwise rmap_write_protect
- * will find a read-only spte, even though the writable spte
- * might be cached on a CPU's TLB, the return value indicates this
- * case.
- *
- * Returns true if the TLB needs to be flushed
+/*
+ * Update the SPTE (excluding the PFN), but do not track changes in its
+ * accessed/dirty status.
  */
-static bool mmu_spte_update(u64 *sptep, u64 new_spte)
+static u64 mmu_spte_update_no_track(u64 *sptep, u64 new_spte)
 {
        u64 old_spte = *sptep;
-       bool flush = false;
 
        WARN_ON(!is_shadow_present_pte(new_spte));
 
        if (!is_shadow_present_pte(old_spte)) {
                mmu_spte_set(sptep, new_spte);
-               return flush;
+               return old_spte;
        }
 
        if (!spte_has_volatile_bits(old_spte))
@@ -558,6 +550,28 @@ static bool mmu_spte_update(u64 *sptep, u64 new_spte)
 
        WARN_ON(spte_to_pfn(old_spte) != spte_to_pfn(new_spte));
 
+       return old_spte;
+}
+
+/* Rules for using mmu_spte_update:
+ * Update the state bits, it means the mapped pfn is not changed.
+ *
+ * Whenever we overwrite a writable spte with a read-only one we
+ * should flush remote TLBs. Otherwise rmap_write_protect
+ * will find a read-only spte, even though the writable spte
+ * might be cached on a CPU's TLB, the return value indicates this
+ * case.
+ *
+ * Returns true if the TLB needs to be flushed
+ */
+static bool mmu_spte_update(u64 *sptep, u64 new_spte)
+{
+       bool flush = false;
+       u64 old_spte = mmu_spte_update_no_track(sptep, new_spte);
+
+       if (!is_shadow_present_pte(old_spte))
+               return false;
+
        /*
         * For the spte updated out of mmu-lock is safe, since
         * we always atomically update it, see the comments in