KVM: s390: vsie: cleanup mcck reinjection
[sfrench/cifs-2.6.git] / arch / s390 / kvm / vsie.c
index 4719ecb9ab423b7a3c0cc246c0baa856cdd10544..fbe46dd0e55d4231e9935f46e0c6e5618b28fa16 100644 (file)
 
 struct vsie_page {
        struct kvm_s390_sie_block scb_s;        /* 0x0000 */
+       /*
+        * the backup info for machine check. ensure it's at
+        * the same offset as that in struct sie_page!
+        */
+       struct mcck_volatile_info mcck_info;    /* 0x0200 */
        /* the pinned originial scb */
-       struct kvm_s390_sie_block *scb_o;       /* 0x0200 */
+       struct kvm_s390_sie_block *scb_o;       /* 0x0218 */
        /* the shadow gmap in use by the vsie_page */
-       struct gmap *gmap;                      /* 0x0208 */
+       struct gmap *gmap;                      /* 0x0220 */
        /* address of the last reported fault to guest2 */
-       unsigned long fault_addr;               /* 0x0210 */
-       __u8 reserved[0x0700 - 0x0218];         /* 0x0218 */
+       unsigned long fault_addr;               /* 0x0228 */
+       __u8 reserved[0x0700 - 0x0230];         /* 0x0230 */
        struct kvm_s390_crypto_cb crycb;        /* 0x0700 */
        __u8 fac[S390_ARCH_FAC_LIST_SIZE_BYTE]; /* 0x0800 */
-} __packed;
+};
 
 /* trigger a validity icpt for the given scb */
 static int set_validity_icpt(struct kvm_s390_sie_block *scb,
@@ -344,6 +349,9 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                scb_s->eca |= scb_o->eca & ECA_IB;
        if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_CEI))
                scb_s->eca |= scb_o->eca & ECA_CEI;
+       /* Epoch Extension */
+       if (test_kvm_facility(vcpu->kvm, 139))
+               scb_s->ecd |= scb_o->ecd & ECD_MEF;
 
        prepare_ibc(vcpu, vsie_page);
        rc = shadow_crycb(vcpu, vsie_page);
@@ -822,6 +830,12 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
        local_irq_enable();
        vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 
+       if (rc == -EINTR) {
+               VCPU_EVENT(vcpu, 3, "%s", "machine check");
+               kvm_s390_reinject_machine_check(vcpu, &vsie_page->mcck_info);
+               return 0;
+       }
+
        if (rc > 0)
                rc = 0; /* we could still have an icpt */
        else if (rc == -EFAULT)
@@ -904,6 +918,13 @@ static void register_shadow_scb(struct kvm_vcpu *vcpu,
         */
        preempt_disable();
        scb_s->epoch += vcpu->kvm->arch.epoch;
+
+       if (scb_s->ecd & ECD_MEF) {
+               scb_s->epdx += vcpu->kvm->arch.epdx;
+               if (scb_s->epoch < vcpu->kvm->arch.epoch)
+                       scb_s->epdx += 1;
+       }
+
        preempt_enable();
 }