Skip to content

Commit

Permalink
KVM: Fix vcpu freeing for guest smp
Browse files Browse the repository at this point in the history
A vcpu can pin up to four mmu shadow pages, which means the freeing
loop will never terminate.  Fix by first unpinning shadow pages on
all vcpus, then freeing shadow pages.

Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Avi Kivity committed Jul 16, 2007
1 parent 3138994 commit 7b53aa5
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
15 changes: 15 additions & 0 deletions drivers/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,16 @@ static void free_pio_guest_pages(struct kvm_vcpu *vcpu)
}
}

static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
{
if (!vcpu->vmcs)
return;

vcpu_load(vcpu);
kvm_mmu_unload(vcpu);
vcpu_put(vcpu);
}

static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
{
if (!vcpu->vmcs)
Expand All @@ -401,6 +411,11 @@ static void kvm_free_vcpus(struct kvm *kvm)
{
unsigned int i;

/*
* Unpin any mmu pages first.
*/
for (i = 0; i < KVM_MAX_VCPUS; ++i)
kvm_unload_vcpu_mmu(&kvm->vcpus[i]);
for (i = 0; i < KVM_MAX_VCPUS; ++i)
kvm_free_vcpu(&kvm->vcpus[i]);
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -838,11 +838,12 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
int i;
struct kvm_mmu_page *page;

if (!VALID_PAGE(vcpu->mmu.root_hpa))
return;
#ifdef CONFIG_X86_64
if (vcpu->mmu.shadow_root_level == PT64_ROOT_LEVEL) {
hpa_t root = vcpu->mmu.root_hpa;

ASSERT(VALID_PAGE(root));
page = page_header(root);
--page->root_count;
vcpu->mmu.root_hpa = INVALID_PAGE;
Expand All @@ -853,7 +854,6 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
hpa_t root = vcpu->mmu.pae_root[i];

if (root) {
ASSERT(VALID_PAGE(root));
root &= PT64_BASE_ADDR_MASK;
page = page_header(root);
--page->root_count;
Expand Down

0 comments on commit 7b53aa5

Please sign in to comment.