Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > media > main-src > by-pkgid > aadbe78a25743146bb784eee19f007c5 > files > 396

kvm-83-164.el5_5.9.src.rpm

From bacd64eb0068d729ce68bbab731bfb1d6ec3d3c6 Mon Sep 17 00:00:00 2001
From: Marcelo Tosatti <mtosatti@redhat.com>
Date: Mon, 13 Jul 2009 17:15:53 -0300
Subject: [PATCH] KVM: fix missing locking in alloc_mmu_pages

n_requested_mmu_pages/n_free_mmu_pages are used by
kvm_mmu_change_mmu_pages to calculate the number of pages to zap.

alloc_mmu_pages, called from the vcpu initialization path, modifies this
variables without proper locking, which can result in a negative value
in kvm_mmu_change_mmu_pages (say, with cpu hotplug).

Also free_mmu_pages should only touch vcpu local data (this is already
fixed upstream).

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Bugzilla: 510770
Bugzilla: 505629
Message-ID: <20090713201553.GA14136@amt.cnet>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Izik Eidus <ieidus@redhat.com>
Acked-by: Juan Quintela <quintela@redhat.com>
Acked-by: john cooper <john.cooper@redhat.com>
Acked-by: Gleb Natapov <gleb@redhat.com>
---
 arch/x86/kvm/mmu.c |   14 ++++++++++----
 arch/x86/kvm/mmu.h |    2 ++
 arch/x86/kvm/x86.c |    1 +
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 6c1d15f..c58076d 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2760,16 +2760,20 @@ void kvm_disable_tdp(void)
 }
 EXPORT_SYMBOL_GPL(kvm_disable_tdp);
 
-static void free_mmu_pages(struct kvm_vcpu *vcpu)
+void kvm_mmu_free_all(struct kvm *kvm)
 {
 	struct kvm_mmu_page *sp;
 
-	while (!list_empty(&vcpu->kvm->arch.active_mmu_pages)) {
-		sp = container_of(vcpu->kvm->arch.active_mmu_pages.next,
+	while (!list_empty(&kvm->arch.active_mmu_pages)) {
+		sp = container_of(kvm->arch.active_mmu_pages.next,
 				  struct kvm_mmu_page, link);
-		kvm_mmu_zap_page(vcpu->kvm, sp);
+		kvm_mmu_zap_page(kvm, sp);
 		cond_resched();
 	}
+}
+
+static void free_mmu_pages(struct kvm_vcpu *vcpu)
+{
 	free_page((unsigned long)vcpu->arch.mmu.pae_root);
 }
 
@@ -2780,12 +2784,14 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu)
 
 	ASSERT(vcpu);
 
+	spin_lock(&vcpu->kvm->mmu_lock);
 	if (vcpu->kvm->arch.n_requested_mmu_pages)
 		vcpu->kvm->arch.n_free_mmu_pages =
 					vcpu->kvm->arch.n_requested_mmu_pages;
 	else
 		vcpu->kvm->arch.n_free_mmu_pages =
 					vcpu->kvm->arch.n_alloc_mmu_pages;
+	spin_unlock(&vcpu->kvm->mmu_lock);
 	/*
 	 * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.
 	 * Therefore we need to allocate shadow page tables in the first
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index eaab214..7beb917 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -37,6 +37,8 @@
 #define PT32_ROOT_LEVEL 2
 #define PT32E_ROOT_LEVEL 3
 
+void kvm_mmu_free_all(struct kvm *kvm);
+
 static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
 {
 	if (unlikely(vcpu->kvm->arch.n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ad7d148..f69c19b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4304,6 +4304,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 	kfree(kvm->arch.vpic);
 	kfree(kvm->arch.vioapic);
 	kvm_free_vcpus(kvm);
+	kvm_mmu_free_all(kvm);
 	kvm_free_physmem(kvm);
 	if (kvm->arch.apic_access_page)
 		put_page(kvm->arch.apic_access_page);
-- 
1.6.3.rc4.29.g8146