KVM: Add kvm_arch_vcpu_precreate() to handle pre-allocation issues
authorSean Christopherson <sean.j.christopherson@intel.com>
Wed, 18 Dec 2019 21:55:09 +0000 (13:55 -0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 24 Jan 2020 08:19:07 +0000 (09:19 +0100)
Add a pre-allocation arch hook to handle checks that are currently done
by arch specific code prior to allocating the vCPU object.  This paves
the way for moving the allocation to common KVM code.

Acked-by: Christoffer Dall <christoffer.dall@arm.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/mips/kvm/mips.c
arch/powerpc/kvm/powerpc.c
arch/s390/kvm/kvm-s390.c
arch/x86/kvm/x86.c
include/linux/kvm_host.h
virt/kvm/arm/arm.c
virt/kvm/kvm_main.c

index d72bceb10439f12e2dbd587d2d844d703c518277..2e14455aec4ea7b55c7bb51bdca9f47849ad3fdc 100644 (file)
@@ -280,6 +280,11 @@ static inline void dump_handler(const char *symbol, void *start, void *end)
        pr_debug("\tEND(%s)\n", symbol);
 }
 
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+       return 0;
+}
+
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
        int err, size;
index a2ba708f5cec8c2e2bce78cf183da5e46c15643e..998ef60ac4630a67d15c9a04846a254b31f53e49 100644 (file)
@@ -720,6 +720,11 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
        kvmppc_core_flush_memslot(kvm, slot);
 }
 
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+       return 0;
+}
+
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
        struct kvm_vcpu *vcpu;
index d9e6bf3d54f0f1547bd8fda5df4187e93b2a34ed..57c6838dff373101c4d783a6e712c1ac5b6f6e87 100644 (file)
@@ -3035,15 +3035,19 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return rc;
 }
 
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+       if (!kvm_is_ucontrol(kvm) && !sca_can_add_vcpu(kvm, id))
+               return -EINVAL;
+       return 0;
+}
+
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
                                      unsigned int id)
 {
        struct kvm_vcpu *vcpu;
        struct sie_page *sie_page;
-       int rc = -EINVAL;
-
-       if (!kvm_is_ucontrol(kvm) && !sca_can_add_vcpu(kvm, id))
-               goto out;
+       int rc;
 
        rc = -ENOMEM;
 
index 8188d6cac58882806088173ccfe0218759363bbf..661e3c40529f4ec4051d3c9b1b30f82de5ae3ffe 100644 (file)
@@ -9170,17 +9170,21 @@ static void fx_init(struct kvm_vcpu *vcpu)
        vcpu->arch.cr0 |= X86_CR0_ET;
 }
 
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+       if (kvm_check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0)
+               pr_warn_once("kvm: SMP vm created on host with unstable TSC; "
+                            "guest TSC will not be reliable\n");
+
+       return 0;
+}
+
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
                                                unsigned int id)
 {
        struct kvm_vcpu *vcpu;
        int r;
 
-       if (kvm_check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0)
-               printk_once(KERN_WARNING
-               "kvm: SMP vm created on host with unstable TSC; "
-               "guest TSC will not be reliable\n");
-
        vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL_ACCOUNT);
        if (!vcpu)
                return ERR_PTR(-ENOMEM);
index 4f7c8e2f378d5ada15c54817098ab673cb6470f2..59ac534233610a823c4bffbbfad8af528dbc1d3e 100644 (file)
@@ -874,6 +874,7 @@ void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu);
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu);
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id);
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id);
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu);
index adae134cec592dab850f799e0e3c45f365d0db06..af3ce2bb370d74a31b1ad0e6e9ebf88b1cbb1120 100644 (file)
@@ -279,21 +279,22 @@ void kvm_arch_free_vm(struct kvm *kvm)
                vfree(kvm);
 }
 
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+       if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
+               return -EBUSY;
+
+       if (id >= kvm->arch.max_vcpus)
+               return -EINVAL;
+
+       return 0;
+}
+
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
        int err;
        struct kvm_vcpu *vcpu;
 
-       if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) {
-               err = -EBUSY;
-               goto out;
-       }
-
-       if (id >= kvm->arch.max_vcpus) {
-               err = -EINVAL;
-               goto out;
-       }
-
        vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
        if (!vcpu) {
                err = -ENOMEM;
index 483c683408a2211a57204bf07de8ffc72dfa527f..7b52207f829c988c27be78931192d6e5f06d5706 100644 (file)
@@ -2728,6 +2728,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        kvm->created_vcpus++;
        mutex_unlock(&kvm->lock);
 
+       r = kvm_arch_vcpu_precreate(kvm, id);
+       if (r)
+               goto vcpu_decrement;
+
        vcpu = kvm_arch_vcpu_create(kvm, id);
        if (IS_ERR(vcpu)) {
                r = PTR_ERR(vcpu);