diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2008-09-23 12:18:36 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2008-10-15 08:25:22 -0400 |
commit | ad8cfbe3fffdc09704f0808fde3934855620d545 (patch) | |
tree | 99ad3b8386c2908e29fbca6ad63318c1bc0ff1ed /arch/x86/kvm/mmu.c | |
parent | a7052897b3bcd568a9f5bfaa558957039e7e7ec0 (diff) |
KVM: MMU: mmu_parent_walk
Introduce a function to walk all parents of a given page, invoking a handler.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r-- | arch/x86/kvm/mmu.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index e89af1df4fcd..b82abee78f17 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -147,6 +147,8 @@ struct kvm_shadow_walk { | |||
147 | u64 addr, u64 *spte, int level); | 147 | u64 addr, u64 *spte, int level); |
148 | }; | 148 | }; |
149 | 149 | ||
150 | typedef int (*mmu_parent_walk_fn) (struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp); | ||
151 | |||
150 | static struct kmem_cache *pte_chain_cache; | 152 | static struct kmem_cache *pte_chain_cache; |
151 | static struct kmem_cache *rmap_desc_cache; | 153 | static struct kmem_cache *rmap_desc_cache; |
152 | static struct kmem_cache *mmu_page_header_cache; | 154 | static struct kmem_cache *mmu_page_header_cache; |
@@ -862,6 +864,31 @@ static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp, | |||
862 | BUG(); | 864 | BUG(); |
863 | } | 865 | } |
864 | 866 | ||
867 | |||
868 | static void mmu_parent_walk(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, | ||
869 | mmu_parent_walk_fn fn) | ||
870 | { | ||
871 | struct kvm_pte_chain *pte_chain; | ||
872 | struct hlist_node *node; | ||
873 | struct kvm_mmu_page *parent_sp; | ||
874 | int i; | ||
875 | |||
876 | if (!sp->multimapped && sp->parent_pte) { | ||
877 | parent_sp = page_header(__pa(sp->parent_pte)); | ||
878 | fn(vcpu, parent_sp); | ||
879 | mmu_parent_walk(vcpu, parent_sp, fn); | ||
880 | return; | ||
881 | } | ||
882 | hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link) | ||
883 | for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) { | ||
884 | if (!pte_chain->parent_ptes[i]) | ||
885 | break; | ||
886 | parent_sp = page_header(__pa(pte_chain->parent_ptes[i])); | ||
887 | fn(vcpu, parent_sp); | ||
888 | mmu_parent_walk(vcpu, parent_sp, fn); | ||
889 | } | ||
890 | } | ||
891 | |||
865 | static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu, | 892 | static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu, |
866 | struct kvm_mmu_page *sp) | 893 | struct kvm_mmu_page *sp) |
867 | { | 894 | { |