Skip to contentSkip to conversation

x86/mm changes for v4.6

GIT PULL Ingo Molnar 1 participant 1 message Mar 14, 2016

Subsystems (5)
Documentation x86 x86 MM KASAN +1 more subsystems
lore
Share & tools
lore
#0 lore raw

Linus,

Please pull the latest x86-mm-for-linus git tree from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-mm-for-linus

# HEAD: 8b8addf891de8a00e4d39fc32f93f7c5eb8feceb x86/mm/32: Enable full randomization on i386 and X86_32

The main changes in this cycle were:

- Enable full ASLR randomization for 32-bit programs (Hector Marco-Gisbert)

- Add initial minimal INVPCI support, to flush global mappings (Andy Lutomirski)

- Add KASAN enhancements (Andrey Ryabinin)

- Fix mmiotrace for huge pages (Karol Herbst)

- ... misc cleanups and small enhancements.

Thanks,

Ingo

------------------>
Andrey Ryabinin (2):
x86/kasan: Clear kasan_zero_page after TLB flush x86/kasan: Write protect kasan zero shadow

Andy Lutomirski (6):
x86/mm/32: Set NX in __supported_pte_mask before enabling paging x86/mm: Make kmap_prot into a #define
x86/mm: Add INVPCID helpers
x86/mm: Add a 'noinvpcid' boot option to turn off INVPCID x86/mm: If INVPCID is available, use it to flush global mappings x86/dmi: Switch dmi_remap() from ioremap() [uncached] to ioremap_cache()

Borislav Petkov (2):
x86/mm: Fix INVPCID asm constraint
x86/mm/ptdump: Remove paravirt_enabled()

Hector Marco-Gisbert (1):

      x86/mm/32: Enable full randomization on i386 and X86_32

Ingo Molnar (2):
x86/mm/numa: Clean up numa_clear_kernel_node_hotplug() x86/mm/numa: Check for failures in numa_clear_kernel_node_hotplug()

Jan Beulich (1):
x86/mm: Avoid premature success when changing page attributes

Karol Herbst (1):
x86/mm/kmmio: Fix mmiotrace for hugepages

Seth Jennings (1):
x86/mm: Streamline and restore probe_memory_block_size()

 Documentation/kernel-parameters.txt |  2 +
 arch/x86/include/asm/dmi.h          |  2 +-
 arch/x86/include/asm/fixmap.h       |  2 +-
 arch/x86/include/asm/tlbflush.h     | 57 ++++++++++++++++++++++++
 arch/x86/kernel/cpu/common.c        | 16 +++++++
 arch/x86/kernel/head_32.S           |  6 +++
 arch/x86/mm/dump_pagetables.c       | 11 +++--
 arch/x86/mm/init_32.c               |  3 --
 arch/x86/mm/init_64.c               | 24 +++-------
 arch/x86/mm/kasan_init_64.c         | 17 +++++--
 arch/x86/mm/kmmio.c                 | 88 +++++++++++++++++++++++++------------
 arch/x86/mm/mmap.c                  | 14 +-----
 arch/x86/mm/numa.c                  | 67 ++++++++++++++++++----------
 arch/x86/mm/pageattr.c              |  4 +-
 arch/x86/mm/setup_nx.c              |  5 +--
 15 files changed, 217 insertions(+), 101 deletions(-)
Documentation/kernel-parameters.txt +2 -0
index 551ecf09c8dd..e4c4d2a5a28d 100644
@@ -2566,6 +2566,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
 	nointroute	[IA-64]
 
+	noinvpcid	[X86] Disable the INVPCID cpu feature.
+
 	nojitter	[IA-64] Disables jitter checking for ITC timers.
 
 	no-kvmclock	[X86,KVM] Disable paravirtualized KVM clock driver
arch/x86/include/asm/dmi.h +1 -1
index 535192f6bfad..3c69fed215c5 100644
@@ -15,7 +15,7 @@ static __always_inline __init void *dmi_alloc(unsigned len)
 /* Use early IO mappings for DMI because it's initialized early */
 #define dmi_early_remap		early_ioremap
 #define dmi_early_unmap		early_iounmap
-#define dmi_remap		ioremap
+#define dmi_remap		ioremap_cache
 #define dmi_unmap		iounmap
 
 #endif /* _ASM_X86_DMI_H */
arch/x86/include/asm/fixmap.h +1 -1
index 6d7d0e52ed5a..8554f960e21b 100644
@@ -138,7 +138,7 @@ extern void reserve_top_address(unsigned long reserve);
 extern int fixmaps_set;
 
 extern pte_t *kmap_pte;
-extern pgprot_t kmap_prot;
+#define kmap_prot PAGE_KERNEL
 extern pte_t *pkmap_page_table;
 
 void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
arch/x86/include/asm/tlbflush.h +57 -0

69 lines not on this page · raw message

arch/x86/kernel/cpu/common.c +16 -0
index 37830de8f60a..f4d0aa64d934 100644
@@ -162,6 +162,22 @@ static int __init x86_mpx_setup(char *s)
 }
 __setup("nompx", x86_mpx_setup);
 
+static int __init x86_noinvpcid_setup(char *s)
+{
+	/* noinvpcid doesn't accept parameters */
+	if (s)
+		return -EINVAL;
+
+	/* do not emit a message if the feature is not present */
+	if (!boot_cpu_has(X86_FEATURE_INVPCID))
+		return 0;
+
+	setup_clear_cpu_cap(X86_FEATURE_INVPCID);
+	pr_info("noinvpcid: INVPCID feature disabled\n");
+	return 0;
+}
+early_param("noinvpcid", x86_noinvpcid_setup);
+
 #ifdef CONFIG_X86_32
 static int cachesize_override = -1;
 static int disable_x86_serial_nr = 1;
arch/x86/kernel/head_32.S +6 -0
index 6bc9ae24b6d2..57fc3f8c85fd 100644
@@ -389,6 +389,12 @@ ENTRY(startup_32_smp)
 	/* Make changes effective */
 	wrmsr
 
+	/*
+	 * And make sure that all the mappings we set up have NX set from
+	 * the beginning.
+	 */
+	orl $(1 << (_PAGE_BIT_NX - 32)), pa(__supported_pte_mask + 4)
+
 enable_paging:
 
 /*
arch/x86/mm/dump_pagetables.c +5 -6
index 4a6f1d9b5106..99bfb192803f 100644
@@ -358,20 +358,19 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
 #define pgd_none(a)  pud_none(__pud(pgd_val(a)))
 #endif
 
-#ifdef CONFIG_X86_64
 static inline bool is_hypervisor_range(int idx)
 {
+#ifdef CONFIG_X86_64
 	/*
 	 * ffff800000000000 - ffff87ffffffffff is reserved for
 	 * the hypervisor.
 	 */
-	return paravirt_enabled() &&
-		(idx >= pgd_index(__PAGE_OFFSET) - 16) &&
-		(idx < pgd_index(__PAGE_OFFSET));
-}
+	return	(idx >= pgd_index(__PAGE_OFFSET) - 16) &&
+		(idx <  pgd_index(__PAGE_OFFSET));
 #else
-static inline bool is_hypervisor_range(int idx) { return false; }
+	return false;
 #endif
+}
 
 static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
 				       bool checkwx)
arch/x86/mm/init_32.c +0 -3
index cb4ef3de61f9..a4bb1c7ab65e 100644
@@ -388,7 +388,6 @@ kernel_physical_mapping_init(unsigned long start,
 }
 
 pte_t *kmap_pte;
-pgprot_t kmap_prot;
 
 static inline pte_t *kmap_get_fixmap_pte(unsigned long vaddr)
 {
@@ -405,8 +404,6 @@ static void __init kmap_init(void)
 	 */
 	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
 	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-	kmap_prot = PAGE_KERNEL;
 }
 
 #ifdef CONFIG_HIGHMEM
arch/x86/mm/init_64.c +6 -18
index 5488d21123bd..9686535edfb5 100644
@@ -53,6 +53,7 @@
 #include <asm/numa.h>
 #include <asm/cacheflush.h>
 #include <asm/init.h>
+#include <asm/uv/uv.h>
 #include <asm/setup.h>
 
 #include "mm_internal.h"
@@ -1206,26 +1207,13 @@ int kern_addr_valid(unsigned long addr)
 
 static unsigned long probe_memory_block_size(void)
 {
-	/* start from 2g */
-	unsigned long bz = 1UL<<31;
+	unsigned long bz = MIN_MEMORY_BLOCK_SIZE;
 
-	if (totalram_pages >= (64ULL << (30 - PAGE_SHIFT))) {
-		pr_info("Using 2GB memory block size for large-memory system\n");
-		return 2UL * 1024 * 1024 * 1024;
-	}
-
-	/* less than 64g installed */
-	if ((max_pfn << PAGE_SHIFT) < (16UL << 32))
-		return MIN_MEMORY_BLOCK_SIZE;
-
-	/* get the tail size */
-	while (bz > MIN_MEMORY_BLOCK_SIZE) {
-		if (!((max_pfn << PAGE_SHIFT) & (bz - 1)))
-			break;
-		bz >>= 1;
-	}
+	/* if system is UV or has 64GB of RAM or more, use large blocks */
+	if (is_uv_system() || ((max_pfn << PAGE_SHIFT) >= (64UL << 30)))
+		bz = 2UL << 30; /* 2GB */
 
-	printk(KERN_DEBUG "memory block size : %ldMB\n", bz >> 20);
+	pr_info("x86/mm: Memory block size: %ldMB\n", bz >> 20);
 
 	return bz;
 }
arch/x86/mm/kasan_init_64.c +14 -3
index d470cf219a2d..1b1110fa0057 100644
@@ -120,11 +120,22 @@ void __init kasan_init(void)
 	kasan_populate_zero_shadow(kasan_mem_to_shadow((void *)MODULES_END),
 			(void *)KASAN_SHADOW_END);
 
-	memset(kasan_zero_page, 0, PAGE_SIZE);
-
 	load_cr3(init_level4_pgt);
 	__flush_tlb_all();
-	init_task.kasan_depth = 0;
 
+	/*
+	 * kasan_zero_page has been used as early shadow memory, thus it may
+	 * contain some garbage. Now we can clear and write protect it, since
+	 * after the TLB flush no one should write to it.
+	 */
+	memset(kasan_zero_page, 0, PAGE_SIZE);
+	for (i = 0; i < PTRS_PER_PTE; i++) {
+		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO);
+		set_pte(&kasan_zero_pte[i], pte);
+	}
+	/* Flush TLBs again to be sure that write protection applied. */
+	__flush_tlb_all();
+
+	init_task.kasan_depth = 0;
 	pr_info("KernelAddressSanitizer initialized\n");
 }
arch/x86/mm/kmmio.c +59 -29

222 lines not on this page · raw message

arch/x86/mm/mmap.c +1 -13
index 96bd1e2bffaf..389939f74dd5 100644
@@ -94,18 +94,6 @@ static unsigned long mmap_base(unsigned long rnd)
 }
 
 /*
- * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
- * does, but not when emulating X86_32
- */
-static unsigned long mmap_legacy_base(unsigned long rnd)
-{
-	if (mmap_is_ia32())
-		return TASK_UNMAPPED_BASE;
-	else
-		return TASK_UNMAPPED_BASE + rnd;
-}
-
-/*
  * This function, called very early during the creation of a new
  * process VM image, sets up which VM layout function to use:
  */
@@ -116,7 +104,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	if (current->flags & PF_RANDOMIZE)
 		random_factor = arch_mmap_rnd();
 
-	mm->mmap_legacy_base = mmap_legacy_base(random_factor);
+	mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor;
 
 	if (mmap_is_legacy()) {
 		mm->mmap_base = mm->mmap_legacy_base;
arch/x86/mm/numa.c +44 -23

90 lines not on this page · raw message

arch/x86/mm/pageattr.c +3 -1
index 2440814b0069..3dd6afd2c0e5 100644
@@ -1122,8 +1122,10 @@ static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
 	/*
 	 * Ignore all non primary paths.
 	 */
-	if (!primary)
+	if (!primary) {
+		cpa->numpages = 1;
 		return 0;
+	}
 
 	/*
 	 * Ignore the NULL PTE for kernel identity mapping, as it is expected
arch/x86/mm/setup_nx.c +2 -3
index 92e2eacb3321..78f5d5907f98 100644
@@ -31,9 +31,8 @@ early_param("noexec", noexec_setup);
 
 void x86_configure_nx(void)
 {
-	if (boot_cpu_has(X86_FEATURE_NX) && !disable_nx)
-		__supported_pte_mask |= _PAGE_NX;
-	else
+	/* If disable_nx is set, clear NX on all new mappings going forward. */
+	if (disable_nx)
 		__supported_pte_mask &= ~_PAGE_NX;
 }