|
|
@@ -42,6 +42,7 @@
|
|
|
#include <linux/irq_work.h>
|
|
|
#include <linux/export.h>
|
|
|
#include <linux/jump_label.h>
|
|
|
+#include <linux/set_memory.h>
|
|
|
|
|
|
#include <asm/intel-family.h>
|
|
|
#include <asm/processor.h>
|
|
|
@@ -50,7 +51,6 @@
|
|
|
#include <asm/mce.h>
|
|
|
#include <asm/msr.h>
|
|
|
#include <asm/reboot.h>
|
|
|
-#include <asm/set_memory.h>
|
|
|
|
|
|
#include "mce-internal.h"
|
|
|
|
|
|
@@ -108,10 +108,6 @@ static struct irq_work mce_irq_work;
|
|
|
|
|
|
static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs);
|
|
|
|
|
|
-#ifndef mce_unmap_kpfn
|
|
|
-static void mce_unmap_kpfn(unsigned long pfn);
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* CPU/chipset specific EDAC code can register a notifier call here to print
|
|
|
* MCE errors in a human-readable form.
|
|
|
@@ -602,7 +598,7 @@ static int srao_decode_notifier(struct notifier_block *nb, unsigned long val,
|
|
|
if (mce_usable_address(mce) && (mce->severity == MCE_AO_SEVERITY)) {
|
|
|
pfn = mce->addr >> PAGE_SHIFT;
|
|
|
if (!memory_failure(pfn, 0))
|
|
|
- mce_unmap_kpfn(pfn);
|
|
|
+ set_mce_nospec(pfn);
|
|
|
}
|
|
|
|
|
|
return NOTIFY_OK;
|
|
|
@@ -1072,38 +1068,10 @@ static int do_memory_failure(struct mce *m)
|
|
|
if (ret)
|
|
|
pr_err("Memory error not recovered");
|
|
|
else
|
|
|
- mce_unmap_kpfn(m->addr >> PAGE_SHIFT);
|
|
|
+ set_mce_nospec(m->addr >> PAGE_SHIFT);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-#ifndef mce_unmap_kpfn
|
|
|
-static void mce_unmap_kpfn(unsigned long pfn)
|
|
|
-{
|
|
|
- unsigned long decoy_addr;
|
|
|
-
|
|
|
- /*
|
|
|
- * Unmap this page from the kernel 1:1 mappings to make sure
|
|
|
- * we don't log more errors because of speculative access to
|
|
|
- * the page.
|
|
|
- * We would like to just call:
|
|
|
- * set_memory_np((unsigned long)pfn_to_kaddr(pfn), 1);
|
|
|
- * but doing that would radically increase the odds of a
|
|
|
- * speculative access to the poison page because we'd have
|
|
|
- * the virtual address of the kernel 1:1 mapping sitting
|
|
|
- * around in registers.
|
|
|
- * Instead we get tricky. We create a non-canonical address
|
|
|
- * that looks just like the one we want, but has bit 63 flipped.
|
|
|
- * This relies on set_memory_np() not checking whether we passed
|
|
|
- * a legal address.
|
|
|
- */
|
|
|
-
|
|
|
- decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
|
|
|
-
|
|
|
- if (set_memory_np(decoy_addr, 1))
|
|
|
- pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* The actual machine check handler. This only handles real
|
|
|
* exceptions when something got corrupted coming in through int 18.
|