x86/{mce,mm}: Unmap the entire page if the whole page is affected and poisoned
[sfrench/cifs-2.6.git] / arch / x86 / include / asm / set_memory.h
index ec2c0a094b5da354c4a1dc4ac7c4e19bf2f9e65d..5948218f35c584e00d605a4b76115c2bd9897cda 100644 (file)
@@ -86,28 +86,35 @@ int set_direct_map_default_noflush(struct page *page);
 extern int kernel_set_to_readonly;
 
 #ifdef CONFIG_X86_64
-static inline int set_mce_nospec(unsigned long pfn)
+/*
+ * Prevent speculative access to the page by either unmapping
+ * it (if we do not require access to any part of the page) or
+ * marking it uncacheable (if we want to try to retrieve data
+ * from non-poisoned lines in the page).
+ */
+static inline int set_mce_nospec(unsigned long pfn, bool unmap)
 {
        unsigned long decoy_addr;
        int rc;
 
        /*
-        * Mark the linear address as UC to make sure we don't log more
-        * errors because of speculative access to the page.
         * We would like to just call:
-        *      set_memory_uc((unsigned long)pfn_to_kaddr(pfn), 1);
+        *      set_memory_XX((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_uc() properly sanitizing any __pa()
+        * This relies on set_memory_XX() properly sanitizing any __pa()
         * results with __PHYSICAL_MASK or PTE_PFN_MASK.
         */
        decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
 
-       rc = set_memory_uc(decoy_addr, 1);
+       if (unmap)
+               rc = set_memory_np(decoy_addr, 1);
+       else
+               rc = set_memory_uc(decoy_addr, 1);
        if (rc)
                pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
        return rc;