Merge tag 'kvm-s390-next-5.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / s390 / kvm / kvm-s390.c
index e39f6ef97b09fc6b39f633773a48416f45f90856..d7ff30e45589935890ad1c1f67c0f36eaa4d480e 100644 (file)
@@ -2531,9 +2531,6 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
        if (vcpu->kvm->arch.use_cmma)
                kvm_s390_vcpu_unsetup_cmma(vcpu);
        free_page((unsigned long)(vcpu->arch.sie_block));
-
-       kvm_vcpu_uninit(vcpu);
-       kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
 
 static void kvm_free_vcpus(struct kvm *kvm)
@@ -2542,7 +2539,7 @@ static void kvm_free_vcpus(struct kvm *kvm)
        struct kvm_vcpu *vcpu;
 
        kvm_for_each_vcpu(i, vcpu, kvm)
-               kvm_arch_vcpu_destroy(vcpu);
+               kvm_vcpu_destroy(vcpu);
 
        mutex_lock(&kvm->lock);
        for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
@@ -2704,39 +2701,6 @@ static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
        return rc == 0 && id < KVM_S390_ESCA_CPU_SLOTS;
 }
 
-int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
-{
-       vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
-       kvm_clear_async_pf_completion_queue(vcpu);
-       vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX |
-                                   KVM_SYNC_GPRS |
-                                   KVM_SYNC_ACRS |
-                                   KVM_SYNC_CRS |
-                                   KVM_SYNC_ARCH0 |
-                                   KVM_SYNC_PFAULT;
-       kvm_s390_set_prefix(vcpu, 0);
-       if (test_kvm_facility(vcpu->kvm, 64))
-               vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
-       if (test_kvm_facility(vcpu->kvm, 82))
-               vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC;
-       if (test_kvm_facility(vcpu->kvm, 133))
-               vcpu->run->kvm_valid_regs |= KVM_SYNC_GSCB;
-       if (test_kvm_facility(vcpu->kvm, 156))
-               vcpu->run->kvm_valid_regs |= KVM_SYNC_ETOKEN;
-       /* fprs can be synchronized via vrs, even if the guest has no vx. With
-        * MACHINE_HAS_VX, (load|store)_fpu_regs() will work with vrs format.
-        */
-       if (MACHINE_HAS_VX)
-               vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
-       else
-               vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
-
-       if (kvm_is_ucontrol(vcpu->kvm))
-               return __kvm_ucontrol_vcpu_init(vcpu);
-
-       return 0;
-}
-
 /* needs disabled preemption to protect from TOD sync and vcpu_load/put */
 static void __start_cpu_timer_accounting(struct kvm_vcpu *vcpu)
 {
@@ -2934,7 +2898,7 @@ static void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu)
                vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list;
 }
 
-int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
 {
        int rc = 0;
 
@@ -3007,26 +2971,22 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return rc;
 }
 
-struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
-                                     unsigned int id)
+int kvm_arch_vcpu_precreate(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;
-
-       rc = -ENOMEM;
+               return -EINVAL;
+       return 0;
+}
 
-       vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
-       if (!vcpu)
-               goto out;
+int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+{
+       struct sie_page *sie_page;
+       int rc;
 
        BUILD_BUG_ON(sizeof(struct sie_page) != 4096);
        sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL);
        if (!sie_page)
-               goto out_free_cpu;
+               return -ENOMEM;
 
        vcpu->arch.sie_block = &sie_page->sie_block;
        vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb;
@@ -3035,27 +2995,59 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
        vcpu->arch.sie_block->mso = 0;
        vcpu->arch.sie_block->msl = sclp.hamax;
 
-       vcpu->arch.sie_block->icpua = id;
+       vcpu->arch.sie_block->icpua = vcpu->vcpu_id;
        spin_lock_init(&vcpu->arch.local_int.lock);
-       vcpu->arch.sie_block->gd = (u32)(u64)kvm->arch.gisa_int.origin;
+       vcpu->arch.sie_block->gd = (u32)(u64)vcpu->kvm->arch.gisa_int.origin;
        if (vcpu->arch.sie_block->gd && sclp.has_gisaf)
                vcpu->arch.sie_block->gd |= GISA_FORMAT1;
        seqcount_init(&vcpu->arch.cputm_seqcount);
 
-       rc = kvm_vcpu_init(vcpu, kvm, id);
+       vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+       kvm_clear_async_pf_completion_queue(vcpu);
+       vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX |
+                                   KVM_SYNC_GPRS |
+                                   KVM_SYNC_ACRS |
+                                   KVM_SYNC_CRS |
+                                   KVM_SYNC_ARCH0 |
+                                   KVM_SYNC_PFAULT;
+       kvm_s390_set_prefix(vcpu, 0);
+       if (test_kvm_facility(vcpu->kvm, 64))
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
+       if (test_kvm_facility(vcpu->kvm, 82))
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC;
+       if (test_kvm_facility(vcpu->kvm, 133))
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_GSCB;
+       if (test_kvm_facility(vcpu->kvm, 156))
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_ETOKEN;
+       /* fprs can be synchronized via vrs, even if the guest has no vx. With
+        * MACHINE_HAS_VX, (load|store)_fpu_regs() will work with vrs format.
+        */
+       if (MACHINE_HAS_VX)
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
+       else
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
+
+       if (kvm_is_ucontrol(vcpu->kvm)) {
+               rc = __kvm_ucontrol_vcpu_init(vcpu);
+               if (rc)
+                       goto out_free_sie_block;
+       }
+
+       VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%pK, sie block at 0x%pK",
+                vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
+       trace_kvm_s390_create_vcpu(vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
+
+       rc = kvm_s390_vcpu_setup(vcpu);
        if (rc)
-               goto out_free_sie_block;
-       VM_EVENT(kvm, 3, "create cpu %d at 0x%pK, sie block at 0x%pK", id, vcpu,
-                vcpu->arch.sie_block);
-       trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block);
+               goto out_ucontrol_uninit;
+       return 0;
 
-       return vcpu;
+out_ucontrol_uninit:
+       if (kvm_is_ucontrol(vcpu->kvm))
+               gmap_remove(vcpu->arch.gmap);
 out_free_sie_block:
        free_page((unsigned long)(vcpu->arch.sie_block));
-out_free_cpu:
-       kmem_cache_free(kvm_vcpu_cache, vcpu);
-out:
-       return ERR_PTR(rc);
+       return rc;
 }
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)