All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] MIPS: Support auto-detecting ARCH_PFN_OFFSET / PHYS_OFFSET
@ 2018-07-28  1:23 Paul Burton
  2018-07-28  1:23 ` [PATCH 1/4] MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic Paul Burton
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Paul Burton @ 2018-07-28  1:23 UTC (permalink / raw)
  To: linux-mips; +Cc: Vladimir Kondratiev, Paul Burton

This series fixes a couple of issues we currently have with use of
PHYS_OFFSET, introduces the ability to auto-detect a suitable value for
it from the boot memory map & enables that for the generic platform.
This allows generic kernels to run on systems where the base address of
physical memory is higher than zero without wasting memory on
book-keeping for the unused region between zero & that base address.

Applies cleanly atop mips-next as of commit a999933db9ed ("MIPS: remove
mips_swiotlb_ops").

Thanks,
    Paul

Paul Burton (4):
  MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic
  MIPS: Fix ISA virt/bus conversion for non-zero PHYS_OFFSET
  MIPS: Allow auto-dection of ARCH_PFN_OFFSET & PHYS_OFFSET
  MIPS: generic: Select MIPS_AUTO_PFN_OFFSET

 arch/mips/Kconfig                           |  4 ++++
 arch/mips/include/asm/io.h                  |  8 ++++----
 arch/mips/include/asm/mach-ar7/spaces.h     |  3 ---
 arch/mips/include/asm/mach-generic/spaces.h | 10 +++++++---
 arch/mips/include/asm/mach-pic32/spaces.h   |  1 -
 arch/mips/include/asm/page.h                | 11 ++++++++---
 arch/mips/jazz/jazzdma.c                    |  2 +-
 arch/mips/kernel/setup.c                    | 14 ++++++++++++--
 arch/mips/mm/dma-noncoherent.c              |  2 +-
 9 files changed, 37 insertions(+), 18 deletions(-)

-- 
2.18.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic
  2018-07-28  1:23 [PATCH 0/4] MIPS: Support auto-detecting ARCH_PFN_OFFSET / PHYS_OFFSET Paul Burton
@ 2018-07-28  1:23 ` Paul Burton
  2018-07-28  1:23 ` [PATCH 2/4] MIPS: Fix ISA virt/bus conversion for non-zero PHYS_OFFSET Paul Burton
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Burton @ 2018-07-28  1:23 UTC (permalink / raw)
  To: linux-mips
  Cc: Vladimir Kondratiev, Paul Burton, Florian Fainelli, James Hogan,
	Ralf Baechle

Converting an address between cached & uncached (typically addresses in
(c)kseg0 & (c)kseg1 or 2 xkphys regions) should not depend upon
PHYS_OFFSET in any way - we're converting from a virtual address in one
unmapped region to a virtual address in another unmapped region.

For some reason our CAC_ADDR() & UNCAC_ADDR() macros make use of
PAGE_OFFSET, which typically includes PHYS_OFFSET. This means that
platforms with a non-zero PHYS_OFFSET typically have to workaround
miscalculation by these 2 macros by also defining UNCAC_BASE to a value
that isn't really correct.

It appears that an attempt has previously been made to address this with
commit 3f4579252aa1 ("MIPS: make CAC_ADDR and UNCAC_ADDR account for
PHYS_OFFSET") which was later undone by commit ed3ce16c3d2b ("Revert
"MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET"") which
also introduced the ar7 workaround. That attempt at a fix was roughly
equivalent, but essentially caused the CAC_ADDR() & UNCAC_ADDR() macros
to cancel out PHYS_OFFSET by adding & then subtracting it again. In his
revert Leonid is correct that using PHYS_OFFSET makes no sense in the
context of these macros, but appears to have missed its inclusion via
PAGE_OFFSET which means PHYS_OFFSET actually had an effect after the
revert rather than before it.

Here we fix this by modifying CAC_ADDR() & UNCAC_ADDR() to stop using
PAGE_OFFSET (& thus PHYS_OFFSET), instead using __pa() & __va() along
with UNCAC_BASE.

For UNCAC_ADDR(), __pa() will convert a cached address to a physical
address which we can simply use as an offset from UNCAC_BASE to obtain
an address in the uncached region.

For CAC_ADDR() we can undo the effect of UNCAC_ADDR() by subtracting
UNCAC_BASE and using __va() on the result.

With this change made, remove definitions of UNCAC_BASE from the ar7 &
pic32 platforms which appear to have defined them only to workaround
this problem.

Signed-off-by: Paul Burton <paul.burton@mips.com>
References: 3f4579252aa1 ("MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET")
References: ed3ce16c3d2b ("Revert "MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET"")
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: James Hogan <jhogan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---

 arch/mips/include/asm/mach-ar7/spaces.h   | 3 ---
 arch/mips/include/asm/mach-pic32/spaces.h | 1 -
 arch/mips/include/asm/page.h              | 4 ++--
 arch/mips/jazz/jazzdma.c                  | 2 +-
 arch/mips/mm/dma-noncoherent.c            | 2 +-
 5 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
index 660ab64c0fc9..a004d94dfbdd 100644
--- a/arch/mips/include/asm/mach-ar7/spaces.h
+++ b/arch/mips/include/asm/mach-ar7/spaces.h
@@ -17,9 +17,6 @@
 #define PAGE_OFFSET	_AC(0x94000000, UL)
 #define PHYS_OFFSET	_AC(0x14000000, UL)
 
-#define UNCAC_BASE	_AC(0xb4000000, UL)	/* 0xa0000000 + PHYS_OFFSET */
-#define IO_BASE		UNCAC_BASE
-
 #include <asm/mach-generic/spaces.h>
 
 #endif /* __ASM_AR7_SPACES_H */
diff --git a/arch/mips/include/asm/mach-pic32/spaces.h b/arch/mips/include/asm/mach-pic32/spaces.h
index 046a0a9aa8b3..a1b9783b76ea 100644
--- a/arch/mips/include/asm/mach-pic32/spaces.h
+++ b/arch/mips/include/asm/mach-pic32/spaces.h
@@ -16,7 +16,6 @@
 
 #ifdef CONFIG_PIC32MZDA
 #define PHYS_OFFSET	_AC(0x08000000, UL)
-#define UNCAC_BASE	_AC(0xa8000000, UL)
 #endif
 
 #include <asm/mach-generic/spaces.h>
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index ad461216b5a1..a051b82f8009 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -252,8 +252,8 @@ extern int __virt_addr_valid(const volatile void *kaddr);
 	 ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
 	 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE)
-#define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
+#define UNCAC_ADDR(addr)	(UNCAC_BASE + __pa(addr))
+#define CAC_ADDR(addr)		((unsigned long)__va((addr) - UNCAC_BASE))
 
 #include <asm-generic/memory_model.h>
 #include <asm-generic/getorder.h>
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
index 446fc8c92e1e..d31bc2f01208 100644
--- a/arch/mips/jazz/jazzdma.c
+++ b/arch/mips/jazz/jazzdma.c
@@ -576,7 +576,7 @@ static void *jazz_dma_alloc(struct device *dev, size_t size,
 
 	if (!(attrs & DMA_ATTR_NON_CONSISTENT)) {
 		dma_cache_wback_inv((unsigned long)ret, size);
-		ret = UNCAC_ADDR(ret);
+		ret = (void *)UNCAC_ADDR(ret);
 	}
 	return ret;
 }
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c
index 25edf6d6b686..2aca1236af36 100644
--- a/arch/mips/mm/dma-noncoherent.c
+++ b/arch/mips/mm/dma-noncoherent.c
@@ -78,7 +78,7 @@ void *arch_dma_alloc(struct device *dev, size_t size,
 
 	if (!dev_is_coherent(dev) && !(attrs & DMA_ATTR_NON_CONSISTENT)) {
 		dma_cache_wback_inv((unsigned long) ret, size);
-		ret = UNCAC_ADDR(ret);
+		ret = (void *)UNCAC_ADDR(ret);
 	}
 
 	return ret;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] MIPS: Fix ISA virt/bus conversion for non-zero PHYS_OFFSET
  2018-07-28  1:23 [PATCH 0/4] MIPS: Support auto-detecting ARCH_PFN_OFFSET / PHYS_OFFSET Paul Burton
  2018-07-28  1:23 ` [PATCH 1/4] MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic Paul Burton
@ 2018-07-28  1:23 ` Paul Burton
  2018-07-28  1:23 ` [PATCH 3/4] MIPS: Allow auto-dection of ARCH_PFN_OFFSET & PHYS_OFFSET Paul Burton
  2018-07-28  1:23 ` [PATCH 4/4] MIPS: generic: Select MIPS_AUTO_PFN_OFFSET Paul Burton
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Burton @ 2018-07-28  1:23 UTC (permalink / raw)
  To: linux-mips; +Cc: Vladimir Kondratiev, Paul Burton, James Hogan, Ralf Baechle

isa_virt_to_bus() & isa_bus_to_virt() claim to treat ISA bus addresses
as being identical to physical addresses, but they fail to do so in the
presence of a non-zero PHYS_OFFSET.

Correct this by having them use virt_to_phys() & phys_to_virt(), which
consolidates the calculations to one place & ensures that ISA bus
addresses do indeed match physical addresses.

Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: James Hogan <jhogan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---

 arch/mips/include/asm/io.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index cd170d920d55..54c730aed327 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -143,14 +143,14 @@ static inline void * phys_to_virt(unsigned long address)
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
  */
-static inline unsigned long isa_virt_to_bus(volatile void * address)
+static inline unsigned long isa_virt_to_bus(volatile void *address)
 {
-	return (unsigned long)address - PAGE_OFFSET;
+	return virt_to_phys(address);
 }
 
-static inline void * isa_bus_to_virt(unsigned long address)
+static inline void *isa_bus_to_virt(unsigned long address)
 {
-	return (void *)(address + PAGE_OFFSET);
+	return phys_to_virt(address);
 }
 
 #define isa_page_to_bus page_to_phys
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] MIPS: Allow auto-dection of ARCH_PFN_OFFSET & PHYS_OFFSET
  2018-07-28  1:23 [PATCH 0/4] MIPS: Support auto-detecting ARCH_PFN_OFFSET / PHYS_OFFSET Paul Burton
  2018-07-28  1:23 ` [PATCH 1/4] MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic Paul Burton
  2018-07-28  1:23 ` [PATCH 2/4] MIPS: Fix ISA virt/bus conversion for non-zero PHYS_OFFSET Paul Burton
@ 2018-07-28  1:23 ` Paul Burton
  2018-07-28  1:23 ` [PATCH 4/4] MIPS: generic: Select MIPS_AUTO_PFN_OFFSET Paul Burton
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Burton @ 2018-07-28  1:23 UTC (permalink / raw)
  To: linux-mips; +Cc: Vladimir Kondratiev, Paul Burton, James Hogan, Ralf Baechle

On systems where physical memory begins at a non-zero address, defining
PHYS_OFFSET (which influences ARCH_PFN_OFFSET) can save us time & memory
by avoiding book-keeping for pages from address zero to the start of
memory.

Some MIPS platforms already make use of this, but with the definition of
PHYS_OFFSET being compile-time constant it hasn't been possible to
enable this optimization for a kernel which may run on systems with
varying physical memory base addresses.

Introduce a new Kconfig option CONFIG_MIPS_AUTO_PFN_OFFSET which, when
enabled, makes ARCH_PFN_OFFSET a variable & detects it from the boot
memory map (which for example may have been populated from DT). The
relationship with PHYS_OFFSET is reversed, with PHYS_OFFSET now being
based on ARCH_PFN_OFFSET. This is because ARCH_PFN_OFFSET is used far
more often, so avoiding the need for runtime calculation gives us a
smaller impact on kernel text size (0.1% rather than 0.15% for
64r6el_defconfig).

Signed-off-by: Paul Burton <paul.burton@mips.com>
Suggested-by: Vladimir Kondratiev <vladimir.kondratiev@intel.com>
Cc: James Hogan <jhogan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---

 arch/mips/Kconfig                           |  3 +++
 arch/mips/include/asm/mach-generic/spaces.h | 10 +++++++---
 arch/mips/include/asm/page.h                |  7 ++++++-
 arch/mips/kernel/setup.c                    | 14 ++++++++++++--
 4 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 10256056647c..fbf7f678e856 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2985,6 +2985,9 @@ config PGTABLE_LEVELS
 	default 3 if 64BIT && !PAGE_SIZE_64KB
 	default 2
 
+config MIPS_AUTO_PFN_OFFSET
+	bool
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h
index 952b0fdfda0e..ee5ebe98f6cf 100644
--- a/arch/mips/include/asm/mach-generic/spaces.h
+++ b/arch/mips/include/asm/mach-generic/spaces.h
@@ -17,9 +17,13 @@
 /*
  * This gives the physical RAM offset.
  */
-#ifndef PHYS_OFFSET
-#define PHYS_OFFSET		_AC(0, UL)
-#endif
+#ifndef __ASSEMBLY__
+# if defined(CONFIG_MIPS_AUTO_PFN_OFFSET)
+#  define PHYS_OFFSET		((unsigned long)PFN_PHYS(ARCH_PFN_OFFSET))
+# elif !defined(PHYS_OFFSET)
+#  define PHYS_OFFSET		_AC(0, UL)
+# endif
+#endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_32BIT
 #ifdef CONFIG_KVM_GUEST
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index a051b82f8009..e8cc328fce2d 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -80,7 +80,12 @@ extern void build_copy_page(void);
  * used in our early mem init code for all memory models.
  * So always define it.
  */
-#define ARCH_PFN_OFFSET		PFN_UP(PHYS_OFFSET)
+#ifdef CONFIG_MIPS_AUTO_PFN_OFFSET
+extern unsigned long ARCH_PFN_OFFSET;
+# define ARCH_PFN_OFFSET	ARCH_PFN_OFFSET
+#else
+# define ARCH_PFN_OFFSET	PFN_UP(PHYS_OFFSET)
+#endif
 
 extern void clear_page(void * page);
 extern void copy_page(void * to, void * from);
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 3d4524309b5c..c71d1eb7da59 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -85,6 +85,11 @@ static struct resource bss_resource = { .name = "Kernel bss", };
 
 static void *detect_magic __initdata = detect_memory_region;
 
+#ifdef CONFIG_MIPS_AUTO_PFN_OFFSET
+unsigned long ARCH_PFN_OFFSET;
+EXPORT_SYMBOL(ARCH_PFN_OFFSET);
+#endif
+
 void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type)
 {
 	int x = boot_mem_map.nr_map;
@@ -442,6 +447,12 @@ static void __init bootmem_init(void)
 		mapstart = max(reserved_end, start);
 	}
 
+	if (min_low_pfn >= max_low_pfn)
+		panic("Incorrect memory mapping !!!");
+
+#ifdef CONFIG_MIPS_AUTO_PFN_OFFSET
+	ARCH_PFN_OFFSET = PFN_UP(ramstart);
+#else
 	/*
 	 * Reserve any memory between the start of RAM and PHYS_OFFSET
 	 */
@@ -449,8 +460,6 @@ static void __init bootmem_init(void)
 		add_memory_region(PHYS_OFFSET, ramstart - PHYS_OFFSET,
 				  BOOT_MEM_RESERVED);
 
-	if (min_low_pfn >= max_low_pfn)
-		panic("Incorrect memory mapping !!!");
 	if (min_low_pfn > ARCH_PFN_OFFSET) {
 		pr_info("Wasting %lu bytes for tracking %lu unused pages\n",
 			(min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page),
@@ -460,6 +469,7 @@ static void __init bootmem_init(void)
 			ARCH_PFN_OFFSET - min_low_pfn);
 	}
 	min_low_pfn = ARCH_PFN_OFFSET;
+#endif
 
 	/*
 	 * Determine low and high memory ranges
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] MIPS: generic: Select MIPS_AUTO_PFN_OFFSET
  2018-07-28  1:23 [PATCH 0/4] MIPS: Support auto-detecting ARCH_PFN_OFFSET / PHYS_OFFSET Paul Burton
                   ` (2 preceding siblings ...)
  2018-07-28  1:23 ` [PATCH 3/4] MIPS: Allow auto-dection of ARCH_PFN_OFFSET & PHYS_OFFSET Paul Burton
@ 2018-07-28  1:23 ` Paul Burton
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Burton @ 2018-07-28  1:23 UTC (permalink / raw)
  To: linux-mips; +Cc: Vladimir Kondratiev, Paul Burton, James Hogan, Ralf Baechle

Enable CONFIG_MIPS_AUTO_PFN_OFFSET for the generic platform, allowing
it to avoid wasted book-keeping for pages with addresses lower than the
physical base address of memory.

This has a minimal impact on kernel text size, with 64r6el_defconfig
gaining 0.1% in size as reported by bloat-o-meter:

  add/remove: 4/1 grow/shrink: 345/13 up/down: 9017/-392 (8625)
  Function                                     old     new   delta
  pcpu_setup_first_chunk                      1444    1780    +336
  pcpu_alloc_first_chunk                       864    1136    +272
  start_kernel                                1064    1288    +224
  initcall_blacklist                           224     372    +148
  try_fill_recv                               2088    2184     +96
  ...
  Total: Before=8457273, After=8465898, chg +0.10%

The gain for systems with large offsets to physical memory & the ability
to continue using generic kernels on such systems seems well worth this
small cost.

Signed-off-by: Paul Burton <paul.burton@mips.com>
Suggested-by: Vladimir Kondratiev <vladimir.kondratiev@intel.com>
Cc: James Hogan <jhogan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org

---

 arch/mips/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fbf7f678e856..c95eb5ad0d96 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -98,6 +98,7 @@ config MIPS_GENERIC
 	select HW_HAS_PCI
 	select IRQ_MIPS_CPU
 	select LIBFDT
+	select MIPS_AUTO_PFN_OFFSET
 	select MIPS_CPU_SCACHE
 	select MIPS_GIC
 	select MIPS_L1_CACHE_SHIFT_7
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-07-28  1:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-28  1:23 [PATCH 0/4] MIPS: Support auto-detecting ARCH_PFN_OFFSET / PHYS_OFFSET Paul Burton
2018-07-28  1:23 ` [PATCH 1/4] MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic Paul Burton
2018-07-28  1:23 ` [PATCH 2/4] MIPS: Fix ISA virt/bus conversion for non-zero PHYS_OFFSET Paul Burton
2018-07-28  1:23 ` [PATCH 3/4] MIPS: Allow auto-dection of ARCH_PFN_OFFSET & PHYS_OFFSET Paul Burton
2018-07-28  1:23 ` [PATCH 4/4] MIPS: generic: Select MIPS_AUTO_PFN_OFFSET Paul Burton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.