Skip to content

Commit

Permalink
x86/MCE: Always save CS register on AMD Zen IF Poison errors
Browse files Browse the repository at this point in the history
commit 4240e2e upstream.

The Instruction Fetch (IF) units on current AMD Zen-based systems do not
guarantee a synchronous #MC is delivered for poison consumption errors.
Therefore, MCG_STATUS[EIPV|RIPV] will not be set. However, the
microarchitecture does guarantee that the exception is delivered within
the same context. In other words, the exact rIP is not known, but the
context is known to not have changed.

There is no architecturally-defined method to determine this behavior.

The Code Segment (CS) register is always valid on such IF unit poison
errors regardless of the value of MCG_STATUS[EIPV|RIPV].

Add a quirk to save the CS register for poison consumption from the IF
unit banks.

This is needed to properly determine the context of the error.
Otherwise, the severity grading function will assume the context is
IN_KERNEL due to the m->cs value being 0 (the initialized value). This
leads to unnecessary kernel panics on data poison errors due to the
kernel believing the poison consumption occurred in kernel context.

Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20230814200853.29258-1-yazen.ghannam@amd.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
yghannam authored and gregkh committed Sep 13, 2023
1 parent d08b39b commit e6e6a5f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
26 changes: 26 additions & 0 deletions arch/x86/kernel/cpu/mce/core.c
Expand Up @@ -856,6 +856,26 @@ static noinstr bool quirk_skylake_repmov(void)
return false;
}

/*
* Some Zen-based Instruction Fetch Units set EIPV=RIPV=0 on poison consumption
* errors. This means mce_gather_info() will not save the "ip" and "cs" registers.
*
* However, the context is still valid, so save the "cs" register for later use.
*
* The "ip" register is truly unknown, so don't save it or fixup EIPV/RIPV.
*
* The Instruction Fetch Unit is at MCA bank 1 for all affected systems.
*/
static __always_inline void quirk_zen_ifu(int bank, struct mce *m, struct pt_regs *regs)
{
if (bank != 1)
return;
if (!(m->status & MCI_STATUS_POISON))
return;

m->cs = regs->cs;
}

/*
* Do a quick check if any of the events requires a panic.
* This decides if we keep the events around or clear them.
Expand All @@ -875,6 +895,9 @@ static __always_inline int mce_no_way_out(struct mce *m, char **msg, unsigned lo
if (mce_flags.snb_ifu_quirk)
quirk_sandybridge_ifu(i, m, regs);

if (mce_flags.zen_ifu_quirk)
quirk_zen_ifu(i, m, regs);

m->bank = i;
if (mce_severity(m, regs, &tmp, true) >= MCE_PANIC_SEVERITY) {
mce_read_aux(m, i);
Expand Down Expand Up @@ -1852,6 +1875,9 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
if (c->x86 == 0x15 && c->x86_model <= 0xf)
mce_flags.overflow_recov = 1;

if (c->x86 >= 0x17 && c->x86 <= 0x1A)
mce_flags.zen_ifu_quirk = 1;

}

if (c->x86_vendor == X86_VENDOR_INTEL) {
Expand Down
5 changes: 4 additions & 1 deletion arch/x86/kernel/cpu/mce/internal.h
Expand Up @@ -157,6 +157,9 @@ struct mce_vendor_flags {
*/
smca : 1,

/* Zen IFU quirk */
zen_ifu_quirk : 1,

/* AMD-style error thresholding banks present. */
amd_threshold : 1,

Expand All @@ -172,7 +175,7 @@ struct mce_vendor_flags {
/* Skylake, Cascade Lake, Cooper Lake REP;MOVS* quirk */
skx_repmov_quirk : 1,

__reserved_0 : 56;
__reserved_0 : 55;
};

extern struct mce_vendor_flags mce_flags;
Expand Down

0 comments on commit e6e6a5f

Please sign in to comment.