OSDN Git Service

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 d72bceb..2e14455 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 a2ba708..998ef60 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 d9e6bf3..57c6838 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 8188d6c..661e3c4 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 4f7c8e2..59ac534 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 adae134..af3ce2b 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 483c683..7b52207 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);