Commit 23ba710a authored by Tony Luck's avatar Tony Luck Committed by Borislav Petkov
Browse files

x86/mce: Fix all mce notifiers to update the mce->kflags bitmask



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: default avatarTony Luck <tony.luck@intel.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Tested-by: default avatarTony Luck <tony.luck@intel.com>
Link: https://lkml.kernel.org/r/20200214222720.13168-5-tony.luck@intel.com
parent 1de08dcc
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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;
}
+5 −0
Original line number Diff line number Diff line
@@ -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;
}

+3 −2
Original line number Diff line number Diff line
@@ -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)
+1 −0
Original line number Diff line number Diff line
@@ -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;
	}

+3 −2
Original line number Diff line number Diff line
@@ -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 = {
Loading