Skip to contentSkip to conversation

x86/mm changes for v4.5

GIT PULL Ingo Molnar 1 participant 1 message Jan 11, 2016

Subsystems (5)
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: 1f1a89ac05f6e88aa341e86e57435fdbb1177c0c x86/mm: Micro-optimise clflush_cache_range()

The main changes in this cycle were:

- make the debugfs 'kernel_page_tables' file read-only, as it only has read ops. (Borislav Petkov)

- micro-optimize clflush_cache_range() (Chris Wilson)

- swiotlb enhancements, which fixes certain KVM emulated devices (Igor Mammedov)

- fix an LDT related debug message (Jan Beulich)

- modularize CONFIG_X86_PTDUMP (Kees Cook)

- tone down an overly alarming warning (Laura Abbott)

- Mark variable __initdata (Rasmus Villemoes)

- PAT additions (Toshi Kani)

out-of-topic modifications in x86-mm-for-linus:
-------------------------------------------------

  include/asm-generic/pgtable.h      # d9fe4fab1197: x86/mm/pat: Add untrack_pfn_
  include/linux/bootmem.h            # 8dd330300197: x86/mm: Introduce max_possib
  mm/bootmem.c                       # 8dd330300197: x86/mm: Introduce max_possib
  mm/mremap.c                        # d9fe4fab1197: x86/mm/pat: Add untrack_pfn_
  mm/nobootmem.c                     # 8dd330300197: x86/mm: Introduce max_possib

Thanks,

Ingo

------------------>
Borislav Petkov (1):
x86/mm/ptdump: Make (debugfs)/kernel_page_tables read-only

Chris Wilson (1):
x86/mm: Micro-optimise clflush_cache_range()

Igor Mammedov (2):
x86/mm: Introduce max_possible_pfn
x86/mm/64: Enable SWIOTLB if system has SRAT memory regions above MAX_DMA32_PFN

Jan Beulich (1):
x86/LDT: Print the real LDT base address

Kees Cook (1):
x86/mm: Turn CONFIG_X86_PTDUMP into a module

Laura Abbott (1):
x86/mm: Drop WARN from multi-BAR check

Rasmus Villemoes (1):
x86/mm/mtrr: Mark the 'range_new' static variable in mtrr_calc_range_state() as __initdata

Toshi Kani (2):
x86/mm/pat: Add untrack_pfn_moved for mremap x86/mm/pat: Change free_memtype() to support shrinking case

 arch/x86/Kconfig.debug             |  2 +-
 arch/x86/kernel/cpu/mtrr/cleanup.c | 11 ++++++--
 arch/x86/kernel/pci-swiotlb.c      |  2 +-
 arch/x86/kernel/process_64.c       |  2 +-
 arch/x86/kernel/setup.c            |  2 ++
 arch/x86/mm/Makefile               |  1 +
 arch/x86/mm/debug_pagetables.c     | 46 +++++++++++++++++++++++++++++++++
 arch/x86/mm/dump_pagetables.c      | 34 ++-----------------------
 arch/x86/mm/ioremap.c              |  4 +--
 arch/x86/mm/pageattr.c             | 10 +++++---
 arch/x86/mm/pat.c                  | 12 ++++++++-
 arch/x86/mm/pat_rbtree.c           | 52 +++++++++++++++++++++++++++++++-------
 arch/x86/mm/srat.c                 |  2 ++
 include/asm-generic/pgtable.h      | 10 +++++++-
 include/linux/bootmem.h            |  4 +++
 mm/bootmem.c                       |  1 +
 mm/mremap.c                        |  4 +++
 mm/nobootmem.c                     |  1 +
 18 files changed, 146 insertions(+), 54 deletions(-)
 create mode 100644 arch/x86/mm/debug_pagetables.c
arch/x86/Kconfig.debug +1 -1
index 137dfa96aa14..110253ce83af 100644
@@ -69,7 +69,7 @@ config X86_PTDUMP_CORE
 	def_bool n
 
 config X86_PTDUMP
-	bool "Export kernel pagetable layout to userspace via debugfs"
+	tristate "Export kernel pagetable layout to userspace via debugfs"
 	depends on DEBUG_KERNEL
 	select DEBUG_FS
 	select X86_PTDUMP_CORE
arch/x86/kernel/cpu/mtrr/cleanup.c +9 -2
index 70d7c93f4550..0d98503c2245 100644
@@ -593,9 +593,16 @@ mtrr_calc_range_state(u64 chunk_size, u64 gran_size,
 		      unsigned long x_remove_base,
 		      unsigned long x_remove_size, int i)
 {
-	static struct range range_new[RANGE_NUM];
+	/*
+	 * range_new should really be an automatic variable, but
+	 * putting 4096 bytes on the stack is frowned upon, to put it
+	 * mildly. It is safe to make it a static __initdata variable,
+	 * since mtrr_calc_range_state is only called during init and
+	 * there's no way it will call itself recursively.
+	 */
+	static struct range range_new[RANGE_NUM] __initdata;
 	unsigned long range_sums_new;
-	static int nr_range_new;
+	int nr_range_new;
 	int num_reg;
 
 	/* Convert ranges to var ranges state: */
arch/x86/kernel/pci-swiotlb.c +1 -1
index adf0392d549a..7c577a178859 100644
@@ -88,7 +88,7 @@ int __init pci_swiotlb_detect_4gb(void)
 {
 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
 #ifdef CONFIG_X86_64
-	if (!no_iommu && max_pfn > MAX_DMA32_PFN)
+	if (!no_iommu && max_possible_pfn > MAX_DMA32_PFN)
 		swiotlb = 1;
 #endif
 	return swiotlb;
arch/x86/kernel/process_64.c +1 -1
index e835d263a33b..b9d99e0f82c4 100644
@@ -125,7 +125,7 @@ void release_thread(struct task_struct *dead_task)
 		if (dead_task->mm->context.ldt) {
 			pr_warn("WARNING: dead process %s still has LDT? <%p/%d>\n",
 				dead_task->comm,
-				dead_task->mm->context.ldt,
+				dead_task->mm->context.ldt->entries,
 				dead_task->mm->context.ldt->size);
 			BUG();
 		}
arch/x86/kernel/setup.c +2 -0
index 29db25f9a745..16a846548ece 100644
@@ -1048,6 +1048,8 @@ void __init setup_arch(char **cmdline_p)
 	if (mtrr_trim_uncached_memory(max_pfn))
 		max_pfn = e820_end_of_ram_pfn();
 
+	max_possible_pfn = max_pfn;
+
 #ifdef CONFIG_X86_32
 	/* max_low_pfn get updated here */
 	find_low_pfn_range();
arch/x86/mm/Makefile +1 -0
index 65c47fda26fc..f9d38a48e3c8 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_X86_32)		+= pgtable_32.o iomap_32.o
 
 obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 obj-$(CONFIG_X86_PTDUMP_CORE)	+= dump_pagetables.o
+obj-$(CONFIG_X86_PTDUMP)	+= debug_pagetables.o
 
 obj-$(CONFIG_HIGHMEM)		+= highmem_32.o
 
arch/x86/mm/debug_pagetables.c new file +46 -0

46 lines not on this page · raw message

arch/x86/mm/dump_pagetables.c +2 -32
index a035c2aa7801..90a1dc054873 100644
@@ -426,38 +426,15 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
 {
 	ptdump_walk_pgd_level_core(m, pgd, false);
 }
+EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level);
 
 void ptdump_walk_pgd_level_checkwx(void)
 {
 	ptdump_walk_pgd_level_core(NULL, NULL, true);
 }
 
-#ifdef CONFIG_X86_PTDUMP
-static int ptdump_show(struct seq_file *m, void *v)
+static int __init pt_dump_init(void)
 {
-	ptdump_walk_pgd_level(m, NULL);
-	return 0;
-}
-
-static int ptdump_open(struct inode *inode, struct file *filp)
-{
-	return single_open(filp, ptdump_show, NULL);
-}
-
-static const struct file_operations ptdump_fops = {
-	.open		= ptdump_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-#endif
-
-static int pt_dump_init(void)
-{
-#ifdef CONFIG_X86_PTDUMP
-	struct dentry *pe;
-#endif
-
 #ifdef CONFIG_X86_32
 	/* Not a compile-time constant on x86-32 */
 	address_markers[VMALLOC_START_NR].start_address = VMALLOC_START;
@@ -468,13 +445,6 @@ static int pt_dump_init(void)
 	address_markers[FIXADDR_START_NR].start_address = FIXADDR_START;
 #endif
 
-#ifdef CONFIG_X86_PTDUMP
-	pe = debugfs_create_file("kernel_page_tables", 0600, NULL, NULL,
-				 &ptdump_fops);
-	if (!pe)
-		return -ENOMEM;
-#endif
-
 	return 0;
 }
 
arch/x86/mm/ioremap.c +2 -2
index b9c78f3bcd67..0d8d53d1f5cc 100644
@@ -194,8 +194,8 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
 	 * Check if the request spans more than any BAR in the iomem resource
 	 * tree.
 	 */
-	WARN_ONCE(iomem_map_sanity_check(unaligned_phys_addr, unaligned_size),
-		  KERN_INFO "Info: mapping multiple BARs. Your kernel is fine.");
+	if (iomem_map_sanity_check(unaligned_phys_addr, unaligned_size))
+		pr_warn("caller %pS mapping multiple BARs\n", caller);
 
 	return ret_addr;
 err_free_area:
arch/x86/mm/pageattr.c +6 -4
index a3137a4feed1..6000ad7f560c 100644
@@ -129,14 +129,16 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  */
 void clflush_cache_range(void *vaddr, unsigned int size)
 {
-	unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+	const unsigned long clflush_size = boot_cpu_data.x86_clflush_size;
+	void *p = (void *)((unsigned long)vaddr & ~(clflush_size - 1));
 	void *vend = vaddr + size;
-	void *p;
+
+	if (p >= vend)
+		return;
 
 	mb();
 
-	for (p = (void *)((unsigned long)vaddr & ~clflush_mask);
-	     p < vend; p += boot_cpu_data.x86_clflush_size)
+	for (; p < vend; p += clflush_size)
 		clflushopt(p);
 
 	mb();
arch/x86/mm/pat.c +11 -1
index 188e3e07eeeb..031782e74231 100644
@@ -586,7 +586,7 @@ int free_memtype(u64 start, u64 end)
 	entry = rbt_memtype_erase(start, end);
 	spin_unlock(&memtype_lock);
 
-	if (!entry) {
+	if (IS_ERR(entry)) {
 		pr_info("x86/PAT: %s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
 			current->comm, current->pid, start, end - 1);
 		return -EINVAL;
@@ -992,6 +992,16 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
 	vma->vm_flags &= ~VM_PAT;
 }
 
+/*
+ * untrack_pfn_moved is called, while mremapping a pfnmap for a new region,
+ * with the old vma after its pfnmap page table has been removed.  The new
+ * vma has a new pfnmap to the same pfn & cache type with VM_PAT set.
+ */
+void untrack_pfn_moved(struct vm_area_struct *vma)
+{
+	vma->vm_flags &= ~VM_PAT;
+}
+
 pgprot_t pgprot_writecombine(pgprot_t prot)
 {
 	return __pgprot(pgprot_val(prot) |
arch/x86/mm/pat_rbtree.c +43 -9

77 lines not on this page · raw message

arch/x86/mm/srat.c +2 -0
index c2aea63bee20..b5f821881465 100644
@@ -203,6 +203,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 		pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
 			(unsigned long long)start, (unsigned long long)end - 1);
 
+	max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
+
 	return 0;
 out_err_bad_srat:
 	bad_srat();
include/asm-generic/pgtable.h +9 -1
index 14b0ff32fb9f..3a6803cb0ec9 100644
@@ -569,7 +569,7 @@ static inline int track_pfn_copy(struct vm_area_struct *vma)
 }
 
 /*
- * untrack_pfn_vma is called while unmapping a pfnmap for a region.
+ * untrack_pfn is called while unmapping a pfnmap for a region.
  * untrack can be called for a specific region indicated by pfn and size or
  * can be for the entire vma (in which case pfn, size are zero).
  */
@@ -577,6 +577,13 @@ static inline void untrack_pfn(struct vm_area_struct *vma,
 			       unsigned long pfn, unsigned long size)
 {
 }
+
+/*
+ * untrack_pfn_moved is called while mremapping a pfnmap for a new region.
+ */
+static inline void untrack_pfn_moved(struct vm_area_struct *vma)
+{
+}
 #else
 extern int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
 			   unsigned long pfn, unsigned long addr,
@@ -586,6 +593,7 @@ extern int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
 extern int track_pfn_copy(struct vm_area_struct *vma);
 extern void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
 			unsigned long size);
+extern void untrack_pfn_moved(struct vm_area_struct *vma);
 #endif
 
 #ifdef __HAVE_COLOR_ZERO_PAGE
include/linux/bootmem.h +4 -0
index f589222bfa87..35b22f94d2d2 100644
@@ -19,6 +19,10 @@ extern unsigned long min_low_pfn;
  * highest page
  */
 extern unsigned long max_pfn;
+/*
+ * highest possible page
+ */
+extern unsigned long long max_possible_pfn;
 
 #ifndef CONFIG_NO_BOOTMEM
 /*
mm/bootmem.c +1 -0
index 3b6380784c28..91e32bc8517f 100644
@@ -33,6 +33,7 @@ EXPORT_SYMBOL(contig_page_data);
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
 unsigned long max_pfn;
+unsigned long long max_possible_pfn;
 
 bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;
 
mm/mremap.c +4 -0
index c25bc6268e46..de824e72c3e8 100644
@@ -319,6 +319,10 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 	hiwater_vm = mm->hiwater_vm;
 	vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
 
+	/* Tell pfnmap has moved from this vma */
+	if (unlikely(vma->vm_flags & VM_PFNMAP))
+		untrack_pfn_moved(vma);
+
 	if (do_munmap(mm, old_addr, old_len) < 0) {
 		/* OOM: unable to split vma, just get accounts right */
 		vm_unacct_memory(excess >> PAGE_SHIFT);
mm/nobootmem.c +1 -0
index e57cf24babd6..99feb2b07fc5 100644
@@ -31,6 +31,7 @@ EXPORT_SYMBOL(contig_page_data);
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
 unsigned long max_pfn;
+unsigned long long max_possible_pfn;
 
 static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
 					u64 goal, u64 limit)