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 8646c99217f285443a5973c1a62832767a4ddc48..d7ff30e45589935890ad1c1f67c0f36eaa4d480e 100644 (file)
@@ -529,6 +529,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_S390_CMMA_MIGRATION:
        case KVM_CAP_S390_AIS:
        case KVM_CAP_S390_AIS_MIGRATION:
+       case KVM_CAP_S390_VCPU_RESETS:
                r = 1;
                break;
        case KVM_CAP_S390_HPAGE_1M:
@@ -2808,35 +2809,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 
 }
 
-static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
-{
-       /* this equals initial cpu reset in pop, but we don't switch to ESA */
-       vcpu->arch.sie_block->gpsw.mask = 0UL;
-       vcpu->arch.sie_block->gpsw.addr = 0UL;
-       kvm_s390_set_prefix(vcpu, 0);
-       kvm_s390_set_cpu_timer(vcpu, 0);
-       vcpu->arch.sie_block->ckc       = 0UL;
-       vcpu->arch.sie_block->todpr     = 0;
-       memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
-       vcpu->arch.sie_block->gcr[0]  = CR0_UNUSED_56 |
-                                       CR0_INTERRUPT_KEY_SUBMASK |
-                                       CR0_MEASUREMENT_ALERT_SUBMASK;
-       vcpu->arch.sie_block->gcr[14] = CR14_UNUSED_32 |
-                                       CR14_UNUSED_33 |
-                                       CR14_EXTERNAL_DAMAGE_SUBMASK;
-       /* make sure the new fpc will be lazily loaded */
-       save_fpu_regs();
-       current->thread.fpu.fpc = 0;
-       vcpu->arch.sie_block->gbea = 1;
-       vcpu->arch.sie_block->pp = 0;
-       vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
-       vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
-       kvm_clear_async_pf_completion_queue(vcpu);
-       if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
-               kvm_s390_vcpu_stop(vcpu);
-       kvm_s390_clear_local_irqs(vcpu);
-}
-
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 {
        mutex_lock(&vcpu->kvm->lock);
@@ -3279,10 +3251,53 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
        return r;
 }
 
-static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
+static void kvm_arch_vcpu_ioctl_normal_reset(struct kvm_vcpu *vcpu)
 {
-       kvm_s390_vcpu_initial_reset(vcpu);
-       return 0;
+       vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_RI;
+       vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+       memset(vcpu->run->s.regs.riccb, 0, sizeof(vcpu->run->s.regs.riccb));
+
+       kvm_clear_async_pf_completion_queue(vcpu);
+       if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+               kvm_s390_vcpu_stop(vcpu);
+       kvm_s390_clear_local_irqs(vcpu);
+}
+
+static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
+{
+       /* Initial reset is a superset of the normal reset */
+       kvm_arch_vcpu_ioctl_normal_reset(vcpu);
+
+       /* this equals initial cpu reset in pop, but we don't switch to ESA */
+       vcpu->arch.sie_block->gpsw.mask = 0;
+       vcpu->arch.sie_block->gpsw.addr = 0;
+       kvm_s390_set_prefix(vcpu, 0);
+       kvm_s390_set_cpu_timer(vcpu, 0);
+       vcpu->arch.sie_block->ckc = 0;
+       vcpu->arch.sie_block->todpr = 0;
+       memset(vcpu->arch.sie_block->gcr, 0, sizeof(vcpu->arch.sie_block->gcr));
+       vcpu->arch.sie_block->gcr[0] = CR0_INITIAL_MASK;
+       vcpu->arch.sie_block->gcr[14] = CR14_INITIAL_MASK;
+       vcpu->run->s.regs.fpc = 0;
+       vcpu->arch.sie_block->gbea = 1;
+       vcpu->arch.sie_block->pp = 0;
+       vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
+}
+
+static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
+{
+       struct kvm_sync_regs *regs = &vcpu->run->s.regs;
+
+       /* Clear reset is a superset of the initial reset */
+       kvm_arch_vcpu_ioctl_initial_reset(vcpu);
+
+       memset(&regs->gprs, 0, sizeof(regs->gprs));
+       memset(&regs->vrs, 0, sizeof(regs->vrs));
+       memset(&regs->acrs, 0, sizeof(regs->acrs));
+       memset(&regs->gscb, 0, sizeof(regs->gscb));
+
+       regs->etoken = 0;
+       regs->etoken_extension = 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
@@ -4343,7 +4358,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        switch (ioctl) {
        case KVM_S390_STORE_STATUS:
                idx = srcu_read_lock(&vcpu->kvm->srcu);
-               r = kvm_s390_vcpu_store_status(vcpu, arg);
+               r = kvm_s390_store_status_unloaded(vcpu, arg);
                srcu_read_unlock(&vcpu->kvm->srcu, idx);
                break;
        case KVM_S390_SET_INITIAL_PSW: {
@@ -4355,8 +4370,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
                break;
        }
+       case KVM_S390_CLEAR_RESET:
+               r = 0;
+               kvm_arch_vcpu_ioctl_clear_reset(vcpu);
+               break;
        case KVM_S390_INITIAL_RESET:
-               r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
+               r = 0;
+               kvm_arch_vcpu_ioctl_initial_reset(vcpu);
+               break;
+       case KVM_S390_NORMAL_RESET:
+               r = 0;
+               kvm_arch_vcpu_ioctl_normal_reset(vcpu);
                break;
        case KVM_SET_ONE_REG:
        case KVM_GET_ONE_REG: {