]> Pileus Git - ~andy/linux/blobdiff - arch/x86/kvm/mmu.c
Merge tag 'for-v3.11' of git://git.infradead.org/battery-2.6
[~andy/linux] / arch / x86 / kvm / mmu.c
index 5d9a1fb108f5e29bfc30a199e1cef8deb61aae6c..0d094da49541d171e7218c7340e63dce6d35674c 100644 (file)
@@ -205,9 +205,11 @@ EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask);
 #define MMIO_SPTE_GEN_LOW_SHIFT                3
 #define MMIO_SPTE_GEN_HIGH_SHIFT       52
 
+#define MMIO_GEN_SHIFT                 19
 #define MMIO_GEN_LOW_SHIFT             9
 #define MMIO_GEN_LOW_MASK              ((1 << MMIO_GEN_LOW_SHIFT) - 1)
-#define MMIO_MAX_GEN                   ((1 << 19) - 1)
+#define MMIO_GEN_MASK                  ((1 << MMIO_GEN_SHIFT) - 1)
+#define MMIO_MAX_GEN                   ((1 << MMIO_GEN_SHIFT) - 1)
 
 static u64 generation_mmio_spte_mask(unsigned int gen)
 {
@@ -231,17 +233,26 @@ static unsigned int get_mmio_spte_generation(u64 spte)
        return gen;
 }
 
+static unsigned int kvm_current_mmio_generation(struct kvm *kvm)
+{
+       /*
+        * Init kvm generation close to MMIO_MAX_GEN to easily test the
+        * code of handling generation number wrap-around.
+        */
+       return (kvm_memslots(kvm)->generation +
+                     MMIO_MAX_GEN - 150) & MMIO_GEN_MASK;
+}
+
 static void mark_mmio_spte(struct kvm *kvm, u64 *sptep, u64 gfn,
                           unsigned access)
 {
-       struct kvm_mmu_page *sp =  page_header(__pa(sptep));
-       u64 mask = generation_mmio_spte_mask(0);
+       unsigned int gen = kvm_current_mmio_generation(kvm);
+       u64 mask = generation_mmio_spte_mask(gen);
 
        access &= ACC_WRITE_MASK | ACC_USER_MASK;
        mask |= shadow_mmio_mask | access | gfn << PAGE_SHIFT;
-       sp->mmio_cached = true;
 
-       trace_mark_mmio_spte(sptep, gfn, access, 0);
+       trace_mark_mmio_spte(sptep, gfn, access, gen);
        mmu_spte_set(sptep, mask);
 }
 
@@ -273,6 +284,17 @@ static bool set_mmio_spte(struct kvm *kvm, u64 *sptep, gfn_t gfn,
        return false;
 }
 
+static bool check_mmio_spte(struct kvm *kvm, u64 spte)
+{
+       unsigned int kvm_gen, spte_gen;
+
+       kvm_gen = kvm_current_mmio_generation(kvm);
+       spte_gen = get_mmio_spte_generation(spte);
+
+       trace_check_mmio_spte(spte, kvm_gen, spte_gen);
+       return likely(kvm_gen == spte_gen);
+}
+
 static inline u64 rsvd_bits(int s, int e)
 {
        return ((1ULL << (e - s + 1)) - 1) << s;
@@ -444,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)
 {
@@ -3224,17 +3257,12 @@ static u64 walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr)
        return spte;
 }
 
-/*
- * If it is a real mmio page fault, return 1 and emulat the instruction
- * directly, return 0 to let CPU fault again on the address, -1 is
- * returned if bug is detected.
- */
 int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
 {
        u64 spte;
 
        if (quickly_check_mmio_pf(vcpu, addr, direct))
-               return 1;
+               return RET_MMIO_PF_EMULATE;
 
        spte = walk_shadow_page_get_mmio_spte(vcpu, addr);
 
@@ -3242,12 +3270,15 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
                gfn_t gfn = get_mmio_spte_gfn(spte);
                unsigned access = get_mmio_spte_access(spte);
 
+               if (!check_mmio_spte(vcpu->kvm, spte))
+                       return RET_MMIO_PF_INVALID;
+
                if (direct)
                        addr = 0;
 
                trace_handle_mmio_page_fault(addr, gfn, access);
                vcpu_cache_mmio_info(vcpu, addr, gfn, access);
-               return 1;
+               return RET_MMIO_PF_EMULATE;
        }
 
        /*
@@ -3255,13 +3286,13 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
         * it's a BUG if the gfn is not a mmio page.
         */
        if (direct && !check_direct_spte_mmio_pf(spte))
-               return -1;
+               return RET_MMIO_PF_BUG;
 
        /*
         * If the page table is zapped by other cpus, let CPU fault again on
         * the address.
         */
-       return 0;
+       return RET_MMIO_PF_RETRY;
 }
 EXPORT_SYMBOL_GPL(handle_mmio_page_fault_common);
 
@@ -3271,7 +3302,7 @@ static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr,
        int ret;
 
        ret = handle_mmio_page_fault_common(vcpu, addr, direct);
-       WARN_ON(ret < 0);
+       WARN_ON(ret == RET_MMIO_PF_BUG);
        return ret;
 }
 
@@ -3283,8 +3314,12 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
 
        pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
 
-       if (unlikely(error_code & PFERR_RSVD_MASK))
-               return handle_mmio_page_fault(vcpu, gva, error_code, true);
+       if (unlikely(error_code & PFERR_RSVD_MASK)) {
+               r = handle_mmio_page_fault(vcpu, gva, error_code, true);
+
+               if (likely(r != RET_MMIO_PF_INVALID))
+                       return r;
+       }
 
        r = mmu_topup_memory_caches(vcpu);
        if (r)
@@ -3360,8 +3395,12 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
        ASSERT(vcpu);
        ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa));
 
-       if (unlikely(error_code & PFERR_RSVD_MASK))
-               return handle_mmio_page_fault(vcpu, gpa, error_code, true);
+       if (unlikely(error_code & PFERR_RSVD_MASK)) {
+               r = handle_mmio_page_fault(vcpu, gpa, error_code, true);
+
+               if (likely(r != RET_MMIO_PF_INVALID))
+                       return r;
+       }
 
        r = mmu_topup_memory_caches(vcpu);
        if (r)
@@ -4334,27 +4373,24 @@ void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm)
        spin_unlock(&kvm->mmu_lock);
 }
 
-void kvm_mmu_zap_mmio_sptes(struct kvm *kvm)
+static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm)
 {
-       struct kvm_mmu_page *sp, *node;
-       LIST_HEAD(invalid_list);
-
-       spin_lock(&kvm->mmu_lock);
-restart:
-       list_for_each_entry_safe(sp, node, &kvm->arch.active_mmu_pages, link) {
-               if (!sp->mmio_cached)
-                       continue;
-               if (kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list))
-                       goto restart;
-       }
-
-       kvm_mmu_commit_zap_page(kvm, &invalid_list);
-       spin_unlock(&kvm->mmu_lock);
+       return unlikely(!list_empty_careful(&kvm->arch.zapped_obsolete_pages));
 }
 
-static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm)
+void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm)
 {
-       return unlikely(!list_empty_careful(&kvm->arch.zapped_obsolete_pages));
+       /*
+        * The very rare case: if the generation-number is round,
+        * zap all shadow pages.
+        *
+        * The max value is MMIO_MAX_GEN - 1 since it is not called
+        * when mark memslot invalid.
+        */
+       if (unlikely(kvm_current_mmio_generation(kvm) >= (MMIO_MAX_GEN - 1))) {
+               printk_ratelimited(KERN_INFO "kvm: zapping shadow pages for mmio generation wraparound\n");
+               kvm_mmu_invalidate_zap_all_pages(kvm);
+       }
 }
 
 static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)