mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
[PATCH] kvm: fix GFP_KERNEL allocation in atomic section in kvm_dev_ioctl_create_vcpu()
fix an GFP_KERNEL allocation in atomic section: kvm_dev_ioctl_create_vcpu() called kvm_mmu_init(), which calls alloc_pages(), while holding the vcpu. The fix is to set up the MMU state in two phases: kvm_mmu_create() and kvm_mmu_setup(). (NOTE: free_vcpus does an kvm_mmu_destroy() call so there's no need for any extra teardown branch on allocation/init failure here.) Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: Avi Kivity <avi@qumranet.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
55a54f79e0
commit
8018c27b26
@ -319,7 +319,8 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module);
|
|||||||
void kvm_exit_arch(void);
|
void kvm_exit_arch(void);
|
||||||
|
|
||||||
void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
|
void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
|
||||||
int kvm_mmu_init(struct kvm_vcpu *vcpu);
|
int kvm_mmu_create(struct kvm_vcpu *vcpu);
|
||||||
|
int kvm_mmu_setup(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
|
int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
|
||||||
void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot);
|
void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot);
|
||||||
|
@ -522,12 +522,14 @@ static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n)
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out_free_vcpus;
|
goto out_free_vcpus;
|
||||||
|
|
||||||
|
r = kvm_mmu_create(vcpu);
|
||||||
|
if (r < 0)
|
||||||
|
goto out_free_vcpus;
|
||||||
|
|
||||||
kvm_arch_ops->vcpu_load(vcpu);
|
kvm_arch_ops->vcpu_load(vcpu);
|
||||||
|
r = kvm_mmu_setup(vcpu);
|
||||||
r = kvm_arch_ops->vcpu_setup(vcpu);
|
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
r = kvm_mmu_init(vcpu);
|
r = kvm_arch_ops->vcpu_setup(vcpu);
|
||||||
|
|
||||||
vcpu_put(vcpu);
|
vcpu_put(vcpu);
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -639,28 +639,22 @@ error_1:
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_mmu_init(struct kvm_vcpu *vcpu)
|
int kvm_mmu_create(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
int r;
|
|
||||||
|
|
||||||
ASSERT(vcpu);
|
ASSERT(vcpu);
|
||||||
ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
|
ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
|
||||||
ASSERT(list_empty(&vcpu->free_pages));
|
ASSERT(list_empty(&vcpu->free_pages));
|
||||||
|
|
||||||
r = alloc_mmu_pages(vcpu);
|
return alloc_mmu_pages(vcpu);
|
||||||
if (r)
|
}
|
||||||
goto out;
|
|
||||||
|
|
||||||
r = init_kvm_mmu(vcpu);
|
int kvm_mmu_setup(struct kvm_vcpu *vcpu)
|
||||||
if (r)
|
{
|
||||||
goto out_free_pages;
|
ASSERT(vcpu);
|
||||||
|
ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
|
||||||
|
ASSERT(!list_empty(&vcpu->free_pages));
|
||||||
|
|
||||||
return 0;
|
return init_kvm_mmu(vcpu);
|
||||||
|
|
||||||
out_free_pages:
|
|
||||||
free_mmu_pages(vcpu);
|
|
||||||
out:
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
|
void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
|
||||||
|
Loading…
Reference in New Issue
Block a user