Skip to content

Commit 8a01ec9

Browse files
aeglbp3tk0v
authored andcommitted
x86/mce: Mask out non-address bits from machine check bank
Systems that support various memory encryption schemes (MKTME, TDX, SEV) use high order physical address bits to indicate which key should be used for a specific memory location. When a memory error is reported, some systems may report those key bits in the IA32_MCi_ADDR machine check MSR. The Intel SDM has a footnote for the contents of the address register that says: "Useful bits in this field depend on the address methodology in use when the register state is saved." AMD Processor Programming Reference has a more explicit description of the MCA_ADDR register: "For physical addresses, the most significant bit is given by Core::X86::Cpuid::LongModeInfo[PhysAddrSize]." Add a new #define MCI_ADDR_PHYSADDR for the mask of valid physical address bits within the machine check bank address register. Use this mask for recoverable machine check handling and in the EDAC driver to ignore any key bits that may be present. [ Tony: Based on independent fixes proposed by Fan Du and Isaku Yamahata ] Reported-by: Isaku Yamahata <[email protected]> Reported-by: Fan Du <[email protected]> Signed-off-by: Tony Luck <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Reviewed-by: Yazen Ghannam <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent fcd343a commit 8a01ec9

File tree

3 files changed

+13
-6
lines changed

3 files changed

+13
-6
lines changed

arch/x86/include/asm/mce.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@
8888
#define MCI_MISC_ADDR_MEM 3 /* memory address */
8989
#define MCI_MISC_ADDR_GENERIC 7 /* generic */
9090

91+
/* MCi_ADDR register defines */
92+
#define MCI_ADDR_PHYSADDR GENMASK_ULL(boot_cpu_data.x86_phys_bits - 1, 0)
93+
9194
/* CTL2 register defines */
9295
#define MCI_CTL2_CMCI_EN BIT_ULL(30)
9396
#define MCI_CTL2_CMCI_THRESHOLD_MASK 0x7fffULL

arch/x86/kernel/cpu/mce/core.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ static int uc_decode_notifier(struct notifier_block *nb, unsigned long val,
573573
mce->severity != MCE_DEFERRED_SEVERITY)
574574
return NOTIFY_DONE;
575575

576-
pfn = mce->addr >> PAGE_SHIFT;
576+
pfn = (mce->addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
577577
if (!memory_failure(pfn, 0)) {
578578
set_mce_nospec(pfn);
579579
mce->kflags |= MCE_HANDLED_UC;
@@ -1294,6 +1294,7 @@ static void kill_me_maybe(struct callback_head *cb)
12941294
{
12951295
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
12961296
int flags = MF_ACTION_REQUIRED;
1297+
unsigned long pfn;
12971298
int ret;
12981299

12991300
p->mce_count = 0;
@@ -1302,9 +1303,10 @@ static void kill_me_maybe(struct callback_head *cb)
13021303
if (!p->mce_ripv)
13031304
flags |= MF_MUST_KILL;
13041305

1305-
ret = memory_failure(p->mce_addr >> PAGE_SHIFT, flags);
1306+
pfn = (p->mce_addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
1307+
ret = memory_failure(pfn, flags);
13061308
if (!ret) {
1307-
set_mce_nospec(p->mce_addr >> PAGE_SHIFT);
1309+
set_mce_nospec(pfn);
13081310
sync_core();
13091311
return;
13101312
}
@@ -1326,11 +1328,13 @@ static void kill_me_maybe(struct callback_head *cb)
13261328
static void kill_me_never(struct callback_head *cb)
13271329
{
13281330
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
1331+
unsigned long pfn;
13291332

13301333
p->mce_count = 0;
13311334
pr_err("Kernel accessed poison in user space at %llx\n", p->mce_addr);
1332-
if (!memory_failure(p->mce_addr >> PAGE_SHIFT, 0))
1333-
set_mce_nospec(p->mce_addr >> PAGE_SHIFT);
1335+
pfn = (p->mce_addr & MCI_ADDR_PHYSADDR) >> PAGE_SHIFT;
1336+
if (!memory_failure(pfn, 0))
1337+
set_mce_nospec(pfn);
13341338
}
13351339

13361340
static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *))

drivers/edac/skx_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
657657

658658
memset(&res, 0, sizeof(res));
659659
res.mce = mce;
660-
res.addr = mce->addr;
660+
res.addr = mce->addr & MCI_ADDR_PHYSADDR;
661661

662662
/* Try driver decoder first */
663663
if (!(driver_decode && driver_decode(&res))) {

0 commit comments

Comments
 (0)