KVM: MMU: document clear_spte_count
authorXiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Wed, 19 Jun 2013 09:09:20 +0000 (17:09 +0800)
committerGleb Natapov <gleb@redhat.com>
Thu, 27 Jun 2013 11:20:42 +0000 (14:20 +0300)
Document it to Documentation/virtual/kvm/mmu.txt

Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Documentation/virtual/kvm/mmu.txt
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/mmu.c

index 869abcc48315874820d9609675149d2bc4510aff..f514a3fad9b983be1d03af8fb2fd86b390579979 100644 (file)
@@ -210,6 +210,11 @@ Shadow pages contain the following information:
     A bitmap indicating which sptes in spt point (directly or indirectly) at
     pages that may be unsynchronized.  Used to quickly locate all unsychronized
     pages reachable from a given page.
+  clear_spte_count:
+    Only present on 32-bit hosts, where a 64-bit spte cannot be written
+    atomically.  The reader uses this while running out of the MMU lock
+    to detect in-progress updates and retry them until the writer has
+    finished the write.
 
 Reverse map
 ===========
index 966f2650b6abf8e4fe536a0eda478ad478cb9884..5d28c11d5e218c3f11219691697d14dc5f9645cd 100644 (file)
@@ -226,6 +226,10 @@ struct kvm_mmu_page {
        DECLARE_BITMAP(unsync_child_bitmap, 512);
 
 #ifdef CONFIG_X86_32
+       /*
+        * Used out of the mmu-lock to avoid reading spte values while an
+        * update is in progress; see the comments in __get_spte_lockless().
+        */
        int clear_spte_count;
 #endif
 
index 7113a0fb544cdc019f20d7f9bda1c9543bec7979..f385a4cf4bfde8117fddeff8dd0337cabc3f9f24 100644 (file)
@@ -466,9 +466,20 @@ static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
 /*
  * The idea using the light way get the spte on x86_32 guest is from
  * gup_get_pte(arch/x86/mm/gup.c).
- * The difference is we can not catch the spte tlb flush if we leave
- * guest mode, so we emulate it by increase clear_spte_count when spte
- * is cleared.
+ *
+ * An spte tlb flush may be pending, because kvm_set_pte_rmapp
+ * coalesces them and we are running out of the MMU lock.  Therefore
+ * we need to protect against in-progress updates of the spte.
+ *
+ * Reading the spte while an update is in progress may get the old value
+ * for the high part of the spte.  The race is fine for a present->non-present
+ * change (because the high part of the spte is ignored for non-present spte),
+ * but for a present->present change we must reread the spte.
+ *
+ * All such changes are done in two steps (present->non-present and
+ * non-present->present), hence it is enough to count the number of
+ * present->non-present updates: if it changed while reading the spte,
+ * we might have hit the race.  This is done using clear_spte_count.
  */
 static u64 __get_spte_lockless(u64 *sptep)
 {