Thread (37 messages) 37 messages, 6 authors, 2015-10-19

[PATCH 01/20] x86: introduce arch_memremap()

flat view
STALE4023d

From: Dan Williams <hidden>
Date: 2015-10-09 22:21:30
Also in: linux-arm-kernel, lkml
Subsystem: documentation, libnvdimm: non-volatile memory device subsystem, library code, the rest, x86 architecture (32-bit and 64-bit), x86 mm · Maintainers: Jonathan Corbet, Dan Williams, Vishal Verma, Dave Jiang, Alison Schofield, Andrew Morton, Linus Torvalds, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, Andy Lutomirski, Peter Zijlstra

In preparation for removing ioremap_cache() introduce arch_memremap()
for x86.  For now, arch_memremap(..., MEMREMAP_WB) and
arch_memremap(..., MEMREMAP_WT) are aliases for ioremap_cache() and
ioremap_wt() respectively.  While the memremap() conversion patches are
filtering through the other sub-systems further development of the
memremap interface may proceed.

This also initiates the guarantee that a successful call to
memremap(..., MEMREMAP_WB) has indeed established a cached mapping and
has not silently fallen back to uncached.

Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Thomas Gleixner <redacted>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Ross Zwisler <redacted>
Signed-off-by: Dan Williams <redacted>
---
 Documentation/x86/pat.txt |    2 ++
 arch/x86/Kconfig          |    1 +
 arch/x86/mm/ioremap.c     |   17 +++++++++++++++++
 drivers/nvdimm/Kconfig    |    2 +-
 include/linux/io.h        |    1 +
 kernel/memremap.c         |   25 +++++++++++++------------
 lib/Kconfig               |    5 ++++-
 7 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt
index 54944c71b819..8c908fa5ea26 100644
--- a/Documentation/x86/pat.txt
+++ b/Documentation/x86/pat.txt
@@ -40,6 +40,8 @@ ioremap_nocache        |    --    |    UC-     |       UC-        |
                        |          |            |                  |
 ioremap_wc             |    --    |    --      |       WC         |
                        |          |            |                  |
+memremap(MEMREMAP_WB)  |    WB    |    WB      |       WB         |
+                       |          |            |                  |
 ioremap_wt             |    --    |    --      |       WT         |
                        |          |            |                  |
 set_memory_uc          |    UC-   |    --      |       --         |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 328c8352480c..488cb210d055 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -27,6 +27,7 @@ config X86
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_FAST_MULTIPLIER
 	select ARCH_HAS_GCOV_PROFILE_ALL
+	select ARCH_HAS_MEMREMAP
 	select ARCH_HAS_PMEM_API		if X86_64
 	select ARCH_HAS_MMIO_FLUSH
 	select ARCH_HAS_SG_CHAIN
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index b9c78f3bcd67..123431ae702f 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -317,6 +317,23 @@ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
 }
 EXPORT_SYMBOL(ioremap_cache);
 
+void *arch_memremap(resource_size_t phys_addr, size_t size,
+		unsigned long flags)
+{
+	int prot;
+
+	if (flags & MEMREMAP_WB)
+		prot = _PAGE_CACHE_MODE_WB;
+	else if (flags & MEMREMAP_WT)
+		prot = _PAGE_CACHE_MODE_WT;
+	else
+		return NULL;
+
+	return (void __force *) __ioremap_caller(phys_addr, size, prot,
+			__builtin_return_address(0));
+}
+EXPORT_SYMBOL(arch_memremap);
+
 void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
 				unsigned long prot_val)
 {
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index 53c11621d5b1..b8e9d8b46f33 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -1,5 +1,6 @@
 menuconfig LIBNVDIMM
 	tristate "NVDIMM (Non-Volatile Memory Device) Support"
+	depends on ARCH_HAS_MEMREMAP
 	depends on PHYS_ADDR_T_64BIT
 	depends on BLK_DEV
 	help
@@ -19,7 +20,6 @@ if LIBNVDIMM
 config BLK_DEV_PMEM
 	tristate "PMEM: Persistent memory block device support"
 	default LIBNVDIMM
-	depends on HAS_IOMEM
 	select ND_BTT if BTT
 	select ND_PFN if NVDIMM_PFN
 	help
diff --git a/include/linux/io.h b/include/linux/io.h
index de64c1e53612..4f150781735d 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -153,5 +153,6 @@ enum {
 
 void *memremap(resource_size_t offset, size_t size, unsigned long flags);
 void memunmap(void *addr);
+void *arch_memremap(resource_size_t offset, size_t size, unsigned long flags);
 
 #endif /* _LINUX_IO_H */
diff --git a/kernel/memremap.c b/kernel/memremap.c
index 72b0c66628b6..8bd5fe05d4a4 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -24,6 +24,16 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
 }
 #endif
 
+/* temporary while we convert arch implementations to arch_memremap */
+__weak void *arch_memremap(resource_size_t offset, size_t size,
+		unsigned long flags)
+{
+	if (flags & MEMREMAP_WB)
+		return (void __force *) ioremap_cache(offset, size);
+	else if (flags & MEMREMAP_WT)
+		return (void __force *) ioremap_wt(offset, size);
+}
+
 /**
  * memremap() - remap an iomem_resource as cacheable memory
  * @offset: iomem resource start address
@@ -48,7 +58,6 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
 void *memremap(resource_size_t offset, size_t size, unsigned long flags)
 {
 	int is_ram = region_intersects(offset, size, "System RAM");
-	void *addr = NULL;
 
 	if (is_ram == REGION_MIXED) {
 		WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n",
@@ -58,7 +67,6 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
 
 	/* Try all mapping types requested until one returns non-NULL */
 	if (flags & MEMREMAP_WB) {
-		flags &= ~MEMREMAP_WB;
 		/*
 		 * MEMREMAP_WB is special in that it can be satisifed
 		 * from the direct map.  Some archs depend on the
@@ -66,9 +74,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
 		 * the requested range is potentially in "System RAM"
 		 */
 		if (is_ram == REGION_INTERSECTS)
-			addr = __va(offset);
-		else
-			addr = ioremap_cache(offset, size);
+			return __va(offset);
 	}
 
 	/*
@@ -77,18 +83,13 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
 	 * address mapping.  Enforce that this mapping is not aliasing
 	 * "System RAM"
 	 */
-	if (!addr && is_ram == REGION_INTERSECTS && flags) {
+	if (is_ram == REGION_INTERSECTS) {
 		WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
 				&offset, (unsigned long) size);
 		return NULL;
 	}
 
-	if (!addr && (flags & MEMREMAP_WT)) {
-		flags &= ~MEMREMAP_WT;
-		addr = ioremap_wt(offset, size);
-	}
-
-	return addr;
+	return arch_memremap(offset, size, flags);
 }
 EXPORT_SYMBOL(memremap);
 
diff --git a/lib/Kconfig b/lib/Kconfig
index 2e491ac15622..8d99b4e6a45b 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -520,7 +520,10 @@ config SG_SPLIT
 #
 
 config ARCH_HAS_SG_CHAIN
-	def_bool n
+	bool
+
+config ARCH_HAS_MEMREMAP
+	bool
 
 config ARCH_HAS_PMEM_API
 	bool
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help