forked from Minki/linux
KVM: Fix vcpu freeing for guest smp
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>
This commit is contained in:
parent
313899477f
commit
7b53aa5650
@ -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)
|
||||
@ -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]);
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user