struct esca_entry cpu[KVM_S390_ESCA_CPU_SLOTS];
 } __packed;
 
+/*
+ * This struct is used to store some machine check info from lowcore
+ * for machine checks that happen while the guest is running.
+ * This info in host's lowcore might be overwritten by a second machine
+ * check from host when host is in the machine check's high-level handling.
+ * The size is 24 bytes.
+ */
+struct mcck_volatile_info {
+       __u64 mcic;
+       __u64 failing_storage_address;
+       __u32 ext_damage_code;
+       __u32 reserved;
+};
+
 #define CPUSTAT_STOPPED    0x80000000
 #define CPUSTAT_WAIT       0x10000000
 #define CPUSTAT_ECALL_PEND 0x08000000
 
 struct sie_page {
        struct kvm_s390_sie_block sie_block;
-       __u8 reserved200[1024];         /* 0x0200 */
+       struct mcck_volatile_info mcck_info;    /* 0x0200 */
+       __u8 reserved218[1000];         /* 0x0218 */
        struct kvm_s390_itdb itdb;      /* 0x0600 */
        __u8 reserved700[2304];         /* 0x0700 */
 } __packed;
 
 #include <asm/switch_to.h>
 #include <asm/ctl_reg.h>
 #include <asm/asm-offsets.h>
+#include <linux/kvm_host.h>
 
 struct mcck_struct {
        unsigned int kill_task : 1;
        return kill_task;
 }
 
+/*
+ * Backup the guest's machine check info to its description block
+ */
+static void notrace s390_backup_mcck_info(struct pt_regs *regs)
+{
+       struct mcck_volatile_info *mcck_backup;
+       struct sie_page *sie_page;
+
+       /* r14 contains the sie block, which was set in sie64a */
+       struct kvm_s390_sie_block *sie_block =
+                       (struct kvm_s390_sie_block *) regs->gprs[14];
+
+       if (sie_block == NULL)
+               /* Something's seriously wrong, stop system. */
+               s390_handle_damage();
+
+       sie_page = container_of(sie_block, struct sie_page, sie_block);
+       mcck_backup = &sie_page->mcck_info;
+       mcck_backup->mcic = S390_lowcore.mcck_interruption_code &
+                               ~(MCCK_CODE_CP | MCCK_CODE_EXT_DAMAGE);
+       mcck_backup->ext_damage_code = S390_lowcore.external_damage_code;
+       mcck_backup->failing_storage_address
+                       = S390_lowcore.failing_storage_address;
+}
+
 #define MAX_IPD_COUNT  29
 #define MAX_IPD_TIME   (5 * 60 * USEC_PER_SEC) /* 5 minutes */
 
                mcck->mcck_code = mci.val;
                set_cpu_flag(CIF_MCCK_PENDING);
        }
+
+       /*
+        * Backup the machine check's info if it happens when the guest
+        * is running.
+        */
+       if (test_cpu_flag(CIF_MCCK_GUEST))
+               s390_backup_mcck_info(regs);
+
        if (mci.cd) {
                /* Timing facility damage */
                s390_handle_damage();