Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 965b58a5 authored by Ingo Molnar's avatar Ingo Molnar Committed by Linus Torvalds
Browse files

[PATCH] KVM: Fix GFP_KERNEL alloc in atomic section bug



KVM does kmalloc() in an atomic section while having preemption disabled via
vcpu_load().  Fix this by moving the ->*_msr setup from the vcpu_setup method
to the vcpu_create method.

(This is also a small speedup for setting up a vcpu, which can in theory be
more frequent than the vcpu_create method).

Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent cd36beec
Loading
Loading
Loading
Loading
+21 −11
Original line number Original line Diff line number Diff line
@@ -1094,14 +1094,6 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
	rdmsrl(MSR_IA32_SYSENTER_EIP, a);
	rdmsrl(MSR_IA32_SYSENTER_EIP, a);
	vmcs_writel(HOST_IA32_SYSENTER_EIP, a);   /* 22.2.3 */
	vmcs_writel(HOST_IA32_SYSENTER_EIP, a);   /* 22.2.3 */


	ret = -ENOMEM;
	vcpu->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!vcpu->guest_msrs)
		goto out;
	vcpu->host_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!vcpu->host_msrs)
		goto out_free_guest_msrs;

	for (i = 0; i < NR_VMX_MSR; ++i) {
	for (i = 0; i < NR_VMX_MSR; ++i) {
		u32 index = vmx_msr_index[i];
		u32 index = vmx_msr_index[i];
		u32 data_low, data_high;
		u32 data_low, data_high;
@@ -1155,8 +1147,6 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)


	return 0;
	return 0;


out_free_guest_msrs:
	kfree(vcpu->guest_msrs);
out:
out:
	return ret;
	return ret;
}
}
@@ -1906,13 +1896,33 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
{
{
	struct vmcs *vmcs;
	struct vmcs *vmcs;


	vcpu->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!vcpu->guest_msrs)
		return -ENOMEM;

	vcpu->host_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!vcpu->host_msrs)
		goto out_free_guest_msrs;

	vmcs = alloc_vmcs();
	vmcs = alloc_vmcs();
	if (!vmcs)
	if (!vmcs)
		return -ENOMEM;
		goto out_free_msrs;

	vmcs_clear(vmcs);
	vmcs_clear(vmcs);
	vcpu->vmcs = vmcs;
	vcpu->vmcs = vmcs;
	vcpu->launched = 0;
	vcpu->launched = 0;

	return 0;
	return 0;

out_free_msrs:
	kfree(vcpu->host_msrs);
	vcpu->host_msrs = NULL;

out_free_guest_msrs:
	kfree(vcpu->guest_msrs);
	vcpu->guest_msrs = NULL;

	return -ENOMEM;
}
}


static struct kvm_arch_ops vmx_arch_ops = {
static struct kvm_arch_ops vmx_arch_ops = {