[PATCH] KVM: Enable hardware before doing arch VM initialization

Sean Christopherson sean.j.christopherson at intel.com
Wed Sep 23 14:57:57 EDT 2020

Swap the order of hardware_enable_all() and kvm_arch_init_vm() to
accommodate Intel's Trust Domain Extension (TDX), which needs VMX to be
fully enabled during VM init in order to make SEAMCALLs.

This also provides consistent ordering between kvm_create_vm() and
kvm_destroy_vm() with respect to calling kvm_arch_destroy_vm() and

Cc: Marc Zyngier <maz at kernel.org>
Cc: James Morse <james.morse at arm.com>
Cc: Julien Thierry <julien.thierry.kdev at gmail.com>
Cc: Suzuki K Poulose <suzuki.poulose at arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: Huacai Chen <chenhc at lemote.com>
Cc: Aleksandar Markovic <aleksandar.qemu.devel at gmail.com>
Cc: linux-mips at vger.kernel.org
Cc: Paul Mackerras <paulus at ozlabs.org>
Cc: kvm-ppc at vger.kernel.org
Cc: Christian Borntraeger <borntraeger at de.ibm.com>
Cc: Janosch Frank <frankja at linux.ibm.com>
Cc: David Hildenbrand <david at redhat.com>
Cc: Cornelia Huck <cohuck at redhat.com>
Cc: Claudio Imbrenda <imbrenda at linux.ibm.com>
Cc: Vitaly Kuznetsov <vkuznets at redhat.com>
Cc: Wanpeng Li <wanpengli at tencent.com>
Cc: Jim Mattson <jmattson at google.com>
Cc: Joerg Roedel <joro at 8bytes.org>
Signed-off-by: Sean Christopherson <sean.j.christopherson at intel.com>

Obviously not required until the TDX series comes along, but IMO KVM
should be consistent with respect to enabling and disabling virt support
in hardware.

Tested only on Intel hardware.  Unless I missed something, this only
affects x86, Arm and MIPS as hardware enabling is a nop for s390 and PPC.
Arm looks safe (based on my mostly clueless reading of the code), but I
have no idea if this will cause problem for MIPS, which is doing all kinds
of things in hardware_enable() that I don't pretend to fully understand.

 virt/kvm/kvm_main.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index cf88233b819a..58fa19bcfc90 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -766,7 +766,7 @@ static struct kvm *kvm_create_vm(unsigned long type)
 		struct kvm_memslots *slots = kvm_alloc_memslots();
 		if (!slots)
-			goto out_err_no_arch_destroy_vm;
+			goto out_err_no_disable;
 		/* Generations must be different for each address space. */
 		slots->generation = i;
 		rcu_assign_pointer(kvm->memslots[i], slots);
@@ -776,19 +776,19 @@ static struct kvm *kvm_create_vm(unsigned long type)
 			kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL_ACCOUNT));
 		if (!kvm->buses[i])
-			goto out_err_no_arch_destroy_vm;
+			goto out_err_no_disable;
 	kvm->max_halt_poll_ns = halt_poll_ns;
-	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;
+	r = kvm_arch_init_vm(kvm, type);
+	if (r)
+		goto out_err_no_arch_destroy_vm;
@@ -815,10 +815,10 @@ static struct kvm *kvm_create_vm(unsigned long type)
 		mmu_notifier_unregister(&kvm->mmu_notifier, current->mm);
-	hardware_disable_all();
+	hardware_disable_all();
 	for (i = 0; i < KVM_NR_BUSES; i++)
 		kfree(kvm_get_bus(kvm, i));

More information about the linux-arm-kernel mailing list