x86/mce: Fix all mce notifiers to update the mce->kflags bitmask
authorTony Luck <tony.luck@intel.com>
Fri, 14 Feb 2020 22:27:17 +0000 (14:27 -0800)
committerBorislav Petkov <bp@suse.de>
Tue, 14 Apr 2020 13:59:26 +0000 (15:59 +0200)
If the handler took any action to log or deal with the error, set a bit
in mce->kflags so that the default handler on the end of the machine
check chain can see what has been done.

Get rid of NOTIFY_STOP returns. Make the EDAC and dev-mcelog handlers
skip over errors already processed by CEC.

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Tested-by: Tony Luck <tony.luck@intel.com>
Link: https://lkml.kernel.org/r/20200214222720.13168-5-tony.luck@intel.com
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/mce/dev-mcelog.c
drivers/acpi/acpi_extlog.c
drivers/acpi/nfit/mce.c
drivers/edac/i7core_edac.c
drivers/edac/mce_amd.c
drivers/edac/pnd2_edac.c
drivers/edac/sb_edac.c
drivers/edac/skx_common.c
drivers/ras/cec.c

index b033b35896300b253fbe296c4c714592b0d4733c..5666a48a4bc9a07bb47a2d9df0828669ed13f17d 100644 (file)
@@ -581,8 +581,10 @@ static int uc_decode_notifier(struct notifier_block *nb, unsigned long val,
                return NOTIFY_DONE;
 
        pfn = mce->addr >> PAGE_SHIFT;
-       if (!memory_failure(pfn, 0))
+       if (!memory_failure(pfn, 0)) {
                set_mce_nospec(pfn);
+               mce->kflags |= MCE_HANDLED_UC;
+       }
 
        return NOTIFY_OK;
 }
index d089567a9ce82228cff67cb9ea151460651a31a9..c033e7ea9e3c3704805eebf3b7981164ce00e7e4 100644 (file)
@@ -39,6 +39,9 @@ static int dev_mce_log(struct notifier_block *nb, unsigned long val,
        struct mce *mce = (struct mce *)data;
        unsigned int entry;
 
+       if (mce->kflags & MCE_HANDLED_CEC)
+               return NOTIFY_DONE;
+
        mutex_lock(&mce_chrdev_read_mutex);
 
        entry = mcelog->next;
@@ -56,6 +59,7 @@ static int dev_mce_log(struct notifier_block *nb, unsigned long val,
 
        memcpy(mcelog->entry + entry, mce, sizeof(struct mce));
        mcelog->entry[entry].finished = 1;
+       mcelog->entry[entry].kflags = 0;
 
        /* wake processes polling /dev/mcelog */
        wake_up_interruptible(&mce_chrdev_wait);
@@ -63,6 +67,7 @@ static int dev_mce_log(struct notifier_block *nb, unsigned long val,
 unlock:
        mutex_unlock(&mce_chrdev_read_mutex);
 
+       mce->kflags |= MCE_HANDLED_MCELOG;
        return NOTIFY_OK;
 }
 
index 8596a106a933c146a65430e607913f2276b7781d..9cc3c1f92db561ca2fc37af4d9faccc31525a69b 100644 (file)
@@ -146,7 +146,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
        static u32 err_seq;
 
        estatus = extlog_elog_entry_check(cpu, bank);
-       if (estatus == NULL)
+       if (estatus == NULL || (mce->kflags & MCE_HANDLED_CEC))
                return NOTIFY_DONE;
 
        memcpy(elog_buf, (void *)estatus, ELOG_ENTRY_LEN);
@@ -176,7 +176,8 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
        }
 
 out:
-       return NOTIFY_STOP;
+       mce->kflags |= MCE_HANDLED_EXTLOG;
+       return NOTIFY_OK;
 }
 
 static bool __init extlog_get_l1addr(void)
index f0ae48515b48fc83528650534cd11bfca97b1d35..ee8d9973f60b885de1efce97d0b31fc68fec1091 100644 (file)
@@ -76,6 +76,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
                         */
                        acpi_nfit_ars_rescan(acpi_desc, 0);
                }
+               mce->kflags |= MCE_HANDLED_NFIT;
                break;
        }
 
index b3135b208f9a0e0ed1bded6bf94e06838953515a..5860ca41185cf1830d3aa2408f6fb36b5f7a29bc 100644 (file)
@@ -1815,7 +1815,7 @@ static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
        struct mem_ctl_info *mci;
 
        i7_dev = get_i7core_dev(mce->socketid);
-       if (!i7_dev)
+       if (!i7_dev || (mce->kflags & MCE_HANDLED_CEC))
                return NOTIFY_DONE;
 
        mci = i7_dev->mci;
@@ -1834,7 +1834,8 @@ static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
        i7core_check_error(mci, mce);
 
        /* Advise mcelog that the errors were handled */
-       return NOTIFY_STOP;
+       mce->kflags |= MCE_HANDLED_EDAC;
+       return NOTIFY_OK;
 }
 
 static struct notifier_block i7_mce_dec = {
index e58644d9c92b7f92f38e308cccc7359bf9f917c2..2b5401db56ad9d6648b7c75ecdfc5a0fb853d4c6 100644 (file)
@@ -1046,6 +1046,9 @@ amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
        unsigned int fam = x86_family(m->cpuid);
        int ecc;
 
+       if (m->kflags & MCE_HANDLED_CEC)
+               return NOTIFY_DONE;
+
        pr_emerg(HW_ERR "%s\n", decode_error_status(m));
 
        pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
@@ -1146,7 +1149,8 @@ amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
  err_code:
        amd_decode_err_code(m->status & 0xffff);
 
-       return NOTIFY_STOP;
+       m->kflags |= MCE_HANDLED_EDAC;
+       return NOTIFY_OK;
 }
 
 static struct notifier_block amd_mce_dec_nb = {
index bc47328eb48588314a257a499e71d2d88f2ff412..1929a5dc8f94d44ef96abdb829e82550e8646256 100644 (file)
@@ -1400,7 +1400,7 @@ static int pnd2_mce_check_error(struct notifier_block *nb, unsigned long val, vo
                return NOTIFY_DONE;
 
        mci = pnd2_mci;
-       if (!mci)
+       if (!mci || (mce->kflags & MCE_HANDLED_CEC))
                return NOTIFY_DONE;
 
        /*
@@ -1429,7 +1429,8 @@ static int pnd2_mce_check_error(struct notifier_block *nb, unsigned long val, vo
        pnd2_mce_output_error(mci, mce, &daddr);
 
        /* Advice mcelog that the error were handled */
-       return NOTIFY_STOP;
+       mce->kflags |= MCE_HANDLED_EDAC;
+       return NOTIFY_OK;
 }
 
 static struct notifier_block pnd2_mce_dec = {
index 7d51c82be62ba3cf9d379c53c67ee7b4caa53f08..f790f7d086880e887e02781a5fea2a7545b6b16d 100644 (file)
@@ -3136,6 +3136,8 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
 
        if (edac_get_report_status() == EDAC_REPORTING_DISABLED)
                return NOTIFY_DONE;
+       if (mce->kflags & MCE_HANDLED_CEC)
+               return NOTIFY_DONE;
 
        /*
         * Just let mcelog handle it if the error is
@@ -3183,7 +3185,8 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
        sbridge_mce_output_error(mci, mce);
 
        /* Advice mcelog that the error were handled */
-       return NOTIFY_STOP;
+       mce->kflags |= MCE_HANDLED_EDAC;
+       return NOTIFY_OK;
 }
 
 static struct notifier_block sbridge_mce_dec = {
index 99bbaf629b8d90ee18a321b68bac0edd55f62049..6f08a12f6b1103a8bc3b06c4f04db739bb363b14 100644 (file)
@@ -577,6 +577,9 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
        if (edac_get_report_status() == EDAC_REPORTING_DISABLED)
                return NOTIFY_DONE;
 
+       if (mce->kflags & MCE_HANDLED_CEC)
+               return NOTIFY_DONE;
+
        /* ignore unless this is memory related with an address */
        if ((mce->status & 0xefff) >> 7 != 1 || !(mce->status & MCI_STATUS_ADDRV))
                return NOTIFY_DONE;
@@ -616,6 +619,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
 
        skx_mce_output_error(mci, mce, &res);
 
+       mce->kflags |= MCE_HANDLED_EDAC;
        return NOTIFY_DONE;
 }
 
index 6b42040bf956e90e9f13a21a9475908b6a57ff23..569d9ad2c594289e899911f3a309295b6139a881 100644 (file)
@@ -538,9 +538,12 @@ static int cec_notifier(struct notifier_block *nb, unsigned long val,
        /* We eat only correctable DRAM errors with usable addresses. */
        if (mce_is_memory_error(m) &&
            mce_is_correctable(m)  &&
-           mce_usable_address(m))
-               if (!cec_add_elem(m->addr >> PAGE_SHIFT))
-                       return NOTIFY_STOP;
+           mce_usable_address(m)) {
+               if (!cec_add_elem(m->addr >> PAGE_SHIFT)) {
+                       m->kflags |= MCE_HANDLED_CEC;
+                       return NOTIFY_OK;
+               }
+       }
 
        return NOTIFY_DONE;
 }