Commit 5f6e3b72 authored by Yazen Ghannam's avatar Yazen Ghannam Committed by Borislav Petkov (AMD)
Browse files

x86/mce/amd: Fix threshold limit reset



The MCA threshold limit must be reset after servicing the interrupt.

Currently, the restart function doesn't have an explicit check for this.  It
makes some assumptions based on the current limit and what's in the registers.
These assumptions don't always hold, so the limit won't be reset in some
cases.

Make the reset condition explicit. Either an interrupt/overflow has occurred
or the bank is being initialized.

Signed-off-by: default avatarYazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/20250624-wip-mca-updates-v4-4-236dd74f645f@amd.com
parent d66e1e90
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -350,7 +350,6 @@ static void smca_configure(unsigned int bank, unsigned int cpu)

struct thresh_restart {
	struct threshold_block	*b;
	int			reset;
	int			set_lvt_off;
	int			lvt_off;
	u16			old_limit;
@@ -432,13 +431,13 @@ static void threshold_restart_bank(void *_tr)

	rdmsr(tr->b->address, lo, hi);

	if (tr->b->threshold_limit < (hi & THRESHOLD_MAX))
		tr->reset = 1;	/* limit cannot be lower than err count */

	if (tr->reset) {		/* reset err count and overflow bit */
		hi =
		    (hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
		    (THRESHOLD_MAX - tr->b->threshold_limit);
	/*
	 * Reset error count and overflow bit.
	 * This is done during init or after handling an interrupt.
	 */
	if (hi & MASK_OVERFLOW_HI || tr->set_lvt_off) {
		hi &= ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI);
		hi |= THRESHOLD_MAX - tr->b->threshold_limit;
	} else if (tr->old_limit) {	/* change limit w/o reset */
		int new_count = (hi & THRESHOLD_MAX) +
		    (tr->old_limit - tr->b->threshold_limit);