[patch 10/13] KVM: MMU: sync roots on mmu reload

Marcelo Tosatti
2008-09-06T19:27:39Z

[-- Attachment #1: kvm-oos-hook-cr3 --]
[-- Type: text/plain, Size: 3099 bytes --]

Bring the pages for the root being switched to back in sync.

Index: kvm/arch/x86/kvm/mmu.c
===================================================================
--- kvm.orig/arch/x86/kvm/mmu.c
+++ kvm/arch/x86/kvm/mmu.c
@@ -1065,6 +1065,20 @@ static int kvm_unsync_page(struct kvm_vc
return mmu_unsync_page(vcpu, sp);
}

+static int mmu_sync_root(struct kvm_vcpu *vcpu, struct kvm_mmu_page *root_sp)
+{
+ struct kvm_mmu_page *sp, *n;
+ int ret = 0;
+
+ list_for_each_entry_safe(sp, n, &root_sp->unsync_pages, oos_link) {
+ ret = 1;
+ kvm_sync_page(vcpu, sp);
+ }
+
+ OOS_ASSERT(list_empty(&root_sp->unsync_pages));
+ return ret;
+}
+
static int set_shared_mmu_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
{
struct kvm_mmu_page *root_sp;
@@ -1075,6 +1089,8 @@ static int set_shared_mmu_page(struct kv
kvm_sync_page(vcpu, sp);
} else if (sp->root_gfn != -1) {
root_sp = kvm_mmu_lookup_page_root(vcpu, sp->root_gfn);
+ if (root_sp)
+ ret = mmu_sync_root(vcpu, root_sp);
}

sp->root_gfn = -1;
@@ -1716,6 +1732,37 @@ static void mmu_alloc_roots(struct kvm_v
vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root);
}

+static void mmu_sync_roots(struct kvm_vcpu *vcpu)
+{
+ int i;
+ struct kvm_mmu_page *sp;
+
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ return;
+ if (vcpu->arch.mmu.shadow_root_level == PT64_ROOT_LEVEL) {
+ hpa_t root = vcpu->arch.mmu.root_hpa;
+ sp = page_header(root);
+ mmu_sync_root(vcpu, sp);
+ return;
+ }
+ for (i = 0; i < 4; ++i) {
+ hpa_t root = vcpu->arch.mmu.pae_root[i];
+
+ if (root) {
+ root &= PT64_BASE_ADDR_MASK;
+ sp = page_header(root);
+ mmu_sync_root(vcpu, sp);
+ }
+ }
+}
+
+void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
+{
+ spin_lock(&vcpu->kvm->mmu_lock);
+ mmu_sync_roots(vcpu);
+ spin_unlock(&vcpu->kvm->mmu_lock);
+}
+
static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
{
return vaddr;
@@ -1960,6 +2007,7 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu)
spin_lock(&vcpu->kvm->mmu_lock);
kvm_mmu_free_some_pages(vcpu);
mmu_alloc_roots(vcpu);
+ mmu_sync_roots(vcpu);
spin_unlock(&vcpu->kvm->mmu_lock);
kvm_x86_ops->set_cr3(vcpu, vcpu->arch.mmu.root_hpa);
kvm_mmu_flush_tlb(vcpu);
Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
@@ -582,6 +582,7 @@ EXPORT_SYMBOL_GPL(kvm_set_cr4);
void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
{
if (cr3 == vcpu->arch.cr3 && !pdptrs_changed(vcpu)) {
+ kvm_mmu_sync_roots(vcpu);
kvm_mmu_flush_tlb(vcpu);
return;
}
Index: kvm/include/asm-x86/kvm_host.h
===================================================================
--- kvm.orig/include/asm-x86/kvm_host.h
+++ kvm/include/asm-x86/kvm_host.h
@@ -610,6 +610,7 @@ int kvm_mmu_unprotect_page_virt(struct k
void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
int kvm_mmu_load(struct kvm_vcpu *vcpu);
void kvm_mmu_unload(struct kvm_vcpu *vcpu);
+void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);

int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);

--