Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Browse files Browse the repository at this point in the history
Pull kvm fixes from Paolo Bonzini:
 "generic:
   - fix memory leak on failure to create VM

  x86:
   - fix MMU corner case with AMD nested paging disabled"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: vmx, svm: always run with EFER.NXE=1 when shadow paging is active
  kvm: call kvm_arch_destroy_vm if vm creation fails
  kvm: Allocate memslots and buses before calling kvm_arch_init_vm
  • Loading branch information
Linus Torvalds committed Nov 1, 2019
2 parents 1461624 + 9167ab7 commit b88866b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 35 deletions.
10 changes: 8 additions & 2 deletions arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,8 +734,14 @@ static int get_npt_level(struct kvm_vcpu *vcpu)
static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
{
vcpu->arch.efer = efer;
if (!npt_enabled && !(efer & EFER_LMA))
efer &= ~EFER_LME;

if (!npt_enabled) {
/* Shadow paging assumes NX to be available. */
efer |= EFER_NX;

if (!(efer & EFER_LMA))
efer &= ~EFER_LME;
}

to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME;
mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
Expand Down
14 changes: 3 additions & 11 deletions arch/x86/kvm/vmx/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,17 +969,9 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
u64 guest_efer = vmx->vcpu.arch.efer;
u64 ignore_bits = 0;

if (!enable_ept) {
/*
* NX is needed to handle CR0.WP=1, CR4.SMEP=1. Testing
* host CPUID is more efficient than testing guest CPUID
* or CR4. Host SMEP is anyway a requirement for guest SMEP.
*/
if (boot_cpu_has(X86_FEATURE_SMEP))
guest_efer |= EFER_NX;
else if (!(guest_efer & EFER_NX))
ignore_bits |= EFER_NX;
}
/* Shadow paging assumes NX to be available. */
if (!enable_ept)
guest_efer |= EFER_NX;

/*
* LMA and LME handled by hardware; SCE meaningless outside long mode.
Expand Down
48 changes: 26 additions & 22 deletions virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,8 +627,9 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)

static struct kvm *kvm_create_vm(unsigned long type)
{
int r, i;
struct kvm *kvm = kvm_arch_alloc_vm();
int r = -ENOMEM;
int i;

if (!kvm)
return ERR_PTR(-ENOMEM);
Expand All @@ -640,44 +641,45 @@ static struct kvm *kvm_create_vm(unsigned long type)
mutex_init(&kvm->lock);
mutex_init(&kvm->irq_lock);
mutex_init(&kvm->slots_lock);
refcount_set(&kvm->users_count, 1);
INIT_LIST_HEAD(&kvm->devices);

r = kvm_arch_init_vm(kvm, type);
if (r)
goto out_err_no_disable;

r = hardware_enable_all();
if (r)
goto out_err_no_disable;

#ifdef CONFIG_HAVE_KVM_IRQFD
INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list);
#endif

BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX);

r = -ENOMEM;
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
struct kvm_memslots *slots = kvm_alloc_memslots();

if (!slots)
goto out_err_no_srcu;
goto out_err_no_arch_destroy_vm;
/* Generations must be different for each address space. */
slots->generation = i;
rcu_assign_pointer(kvm->memslots[i], slots);
}

if (init_srcu_struct(&kvm->srcu))
goto out_err_no_srcu;
if (init_srcu_struct(&kvm->irq_srcu))
goto out_err_no_irq_srcu;
for (i = 0; i < KVM_NR_BUSES; i++) {
rcu_assign_pointer(kvm->buses[i],
kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL_ACCOUNT));
if (!kvm->buses[i])
goto out_err;
goto out_err_no_arch_destroy_vm;
}

refcount_set(&kvm->users_count, 1);
r = kvm_arch_init_vm(kvm, type);
if (r)
goto out_err_no_arch_destroy_vm;

r = hardware_enable_all();
if (r)
goto out_err_no_disable;

#ifdef CONFIG_HAVE_KVM_IRQFD
INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list);
#endif

if (init_srcu_struct(&kvm->srcu))
goto out_err_no_srcu;
if (init_srcu_struct(&kvm->irq_srcu))
goto out_err_no_irq_srcu;

r = kvm_init_mmu_notifier(kvm);
if (r)
goto out_err;
Expand All @@ -697,7 +699,9 @@ static struct kvm *kvm_create_vm(unsigned long type)
out_err_no_srcu:
hardware_disable_all();
out_err_no_disable:
refcount_set(&kvm->users_count, 0);
kvm_arch_destroy_vm(kvm);
WARN_ON_ONCE(!refcount_dec_and_test(&kvm->users_count));
out_err_no_arch_destroy_vm:
for (i = 0; i < KVM_NR_BUSES; i++)
kfree(kvm_get_bus(kvm, i));
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
Expand Down

0 comments on commit b88866b

Please sign in to comment.