]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kvm/mmu.c
KVM: MMU: mmu_parent_walk
[linux-2.6-omap-h63xx.git] / arch / x86 / kvm / mmu.c
index e89af1df4fcd940b54855968a0cd3cfa250cd5ed..b82abee78f1769f63be393f86ec646f8ae326705 100644 (file)
@@ -147,6 +147,8 @@ struct kvm_shadow_walk {
                     u64 addr, u64 *spte, int level);
 };
 
+typedef int (*mmu_parent_walk_fn) (struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp);
+
 static struct kmem_cache *pte_chain_cache;
 static struct kmem_cache *rmap_desc_cache;
 static struct kmem_cache *mmu_page_header_cache;
@@ -862,6 +864,31 @@ static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp,
        BUG();
 }
 
+
+static void mmu_parent_walk(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+                           mmu_parent_walk_fn fn)
+{
+       struct kvm_pte_chain *pte_chain;
+       struct hlist_node *node;
+       struct kvm_mmu_page *parent_sp;
+       int i;
+
+       if (!sp->multimapped && sp->parent_pte) {
+               parent_sp = page_header(__pa(sp->parent_pte));
+               fn(vcpu, parent_sp);
+               mmu_parent_walk(vcpu, parent_sp, fn);
+               return;
+       }
+       hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
+               for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
+                       if (!pte_chain->parent_ptes[i])
+                               break;
+                       parent_sp = page_header(__pa(pte_chain->parent_ptes[i]));
+                       fn(vcpu, parent_sp);
+                       mmu_parent_walk(vcpu, parent_sp, fn);
+               }
+}
+
 static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
                                    struct kvm_mmu_page *sp)
 {