diff mbox series

[v2] MIPS: Add support for CONFIG_DEBUG_VIRTUAL

Message ID 20210323222103.34225-1-f.fainelli@gmail.com (mailing list archive)
State Superseded
Headers show
Series [v2] MIPS: Add support for CONFIG_DEBUG_VIRTUAL | expand

Commit Message

Florian Fainelli March 23, 2021, 10:20 p.m. UTC
Provide hooks to intercept bad usages of virt_to_phys() and
__pa_symbol() throughout the kernel. To make this possible, we need to
rename the current implement of virt_to_phys() into
__virt_to_phys_nodebug() and wrap it around depending on
CONFIG_DEBUG_VIRTUAL.

A similar thing is needed for __pa_symbol() which is now aliased to
__phys_addr_symbol() whose implementation is either the direct return of
RELOC_HIDE or goes through the debug version.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
Changes in v2:
- fixed sparse warning in arch/mips/kernel/vdso.c

 arch/mips/Kconfig            |  1 +
 arch/mips/include/asm/io.h   | 14 ++++++++-
 arch/mips/include/asm/page.h |  9 +++++-
 arch/mips/kernel/vdso.c      |  2 +-
 arch/mips/mm/Makefile        |  2 ++
 arch/mips/mm/physaddr.c      | 55 ++++++++++++++++++++++++++++++++++++
 6 files changed, 80 insertions(+), 3 deletions(-)
 create mode 100644 arch/mips/mm/physaddr.c

Comments

Thomas Bogendoerfer March 25, 2021, 9:57 a.m. UTC | #1
On Tue, Mar 23, 2021 at 03:20:43PM -0700, Florian Fainelli wrote:
> Provide hooks to intercept bad usages of virt_to_phys() and
> __pa_symbol() throughout the kernel. To make this possible, we need to
> rename the current implement of virt_to_phys() into
> __virt_to_phys_nodebug() and wrap it around depending on
> CONFIG_DEBUG_VIRTUAL.
> 
> A similar thing is needed for __pa_symbol() which is now aliased to
> __phys_addr_symbol() whose implementation is either the direct return of
> RELOC_HIDE or goes through the debug version.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> Changes in v2:
> - fixed sparse warning in arch/mips/kernel/vdso.c

checkpatch warns about a missing SPDX license in arch/mips/mm/physaddr.c,
can you please add one ?

And as checkpatch is also unhappy about the volatiles, do we really
need them here ?

Thomas.
Florian Fainelli March 26, 2021, 5:45 p.m. UTC | #2
On 3/25/2021 2:57 AM, Thomas Bogendoerfer wrote:
> On Tue, Mar 23, 2021 at 03:20:43PM -0700, Florian Fainelli wrote:
>> Provide hooks to intercept bad usages of virt_to_phys() and
>> __pa_symbol() throughout the kernel. To make this possible, we need to
>> rename the current implement of virt_to_phys() into
>> __virt_to_phys_nodebug() and wrap it around depending on
>> CONFIG_DEBUG_VIRTUAL.
>>
>> A similar thing is needed for __pa_symbol() which is now aliased to
>> __phys_addr_symbol() whose implementation is either the direct return of
>> RELOC_HIDE or goes through the debug version.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>> Changes in v2:
>> - fixed sparse warning in arch/mips/kernel/vdso.c
> 
> checkpatch warns about a missing SPDX license in arch/mips/mm/physaddr.c,
> can you please add one ?

Yes.

> 
> And as checkpatch is also unhappy about the volatiles, do we really
> need them here ?

This is just following the existing prototypes for virt_to_phys()
declared in arch/mips/include/asm/io.h. This can be changed to unsigned
long if you prefer?
Thomas Bogendoerfer March 26, 2021, 9:44 p.m. UTC | #3
On Fri, Mar 26, 2021 at 10:45:39AM -0700, Florian Fainelli wrote:
> 
> 
> On 3/25/2021 2:57 AM, Thomas Bogendoerfer wrote:
> > On Tue, Mar 23, 2021 at 03:20:43PM -0700, Florian Fainelli wrote:
> >> Provide hooks to intercept bad usages of virt_to_phys() and
> >> __pa_symbol() throughout the kernel. To make this possible, we need to
> >> rename the current implement of virt_to_phys() into
> >> __virt_to_phys_nodebug() and wrap it around depending on
> >> CONFIG_DEBUG_VIRTUAL.
> >>
> >> A similar thing is needed for __pa_symbol() which is now aliased to
> >> __phys_addr_symbol() whose implementation is either the direct return of
> >> RELOC_HIDE or goes through the debug version.
> >>
> >> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> >> ---
> >> Changes in v2:
> >> - fixed sparse warning in arch/mips/kernel/vdso.c
> > 
> > checkpatch warns about a missing SPDX license in arch/mips/mm/physaddr.c,
> > can you please add one ?
> 
> Yes.
> 
> > 
> > And as checkpatch is also unhappy about the volatiles, do we really
> > need them here ?
> 
> This is just following the existing prototypes for virt_to_phys()
> declared in arch/mips/include/asm/io.h. This can be changed to unsigned
> long if you prefer?

I just checked other archs and they also use volatile, so nothing to
change here.

Thomas.
diff mbox series

Patch

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d89efba3d8a4..0904d6351808 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -4,6 +4,7 @@  config MIPS
 	default y
 	select ARCH_32BIT_OFF_T if !64BIT
 	select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT
+	select ARCH_HAS_DEBUG_VIRTUAL if !64BIT
 	select ARCH_HAS_FORTIFY_SOURCE
 	select ARCH_HAS_KCOV
 	select ARCH_HAS_PTE_SPECIAL if !(32BIT && CPU_HAS_RIXI)
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 78537aa23500..2c138450ad3b 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -100,11 +100,23 @@  static inline void set_io_port_base(unsigned long base)
  *     almost all conceivable cases a device driver should not be using
  *     this function
  */
-static inline unsigned long virt_to_phys(volatile const void *address)
+static inline unsigned long __virt_to_phys_nodebug(volatile const void *address)
 {
 	return __pa(address);
 }
 
+#ifdef CONFIG_DEBUG_VIRTUAL
+extern phys_addr_t __virt_to_phys(volatile const void *x);
+#else
+#define __virt_to_phys(x)	__virt_to_phys_nodebug(x)
+#endif
+
+#define virt_to_phys virt_to_phys
+static inline phys_addr_t virt_to_phys(const volatile void *x)
+{
+	return __virt_to_phys(x);
+}
+
 /*
  *     phys_to_virt    -       map physical address to virtual
  *     @address: address to remap
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index 65acab9c41f9..195ff4e9771f 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -210,9 +210,16 @@  static inline unsigned long ___pa(unsigned long x)
  * also affect MIPS so we keep this one until GCC 3.x has been retired
  * before we can apply https://patchwork.linux-mips.org/patch/1541/
  */
+#define __pa_symbol_nodebug(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
+
+#ifdef CONFIG_DEBUG_VIRTUAL
+extern phys_addr_t __phys_addr_symbol(unsigned long x);
+#else
+#define __phys_addr_symbol(x)	__pa_symbol_nodebug(x)
+#endif
 
 #ifndef __pa_symbol
-#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
+#define __pa_symbol(x)		__phys_addr_symbol((unsigned long)(x))
 #endif
 
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 7d0b91ad2581..e3fd93ca480a 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -158,7 +158,7 @@  int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
 	/* Map GIC user page. */
 	if (gic_size) {
-		gic_pfn = virt_to_phys(mips_gic_base + MIPS_GIC_USER_OFS) >> PAGE_SHIFT;
+		gic_pfn = virt_to_phys((void *)mips_gic_base + MIPS_GIC_USER_OFS) >> PAGE_SHIFT;
 
 		ret = io_remap_pfn_range(vma, base, gic_pfn, gic_size,
 					 pgprot_noncached(vma->vm_page_prot));
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 865926a37775..fa1f729e0700 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -40,3 +40,5 @@  obj-$(CONFIG_R5000_CPU_SCACHE)	+= sc-r5k.o
 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
 obj-$(CONFIG_SCACHE_DEBUGFS)	+= sc-debugfs.o
+
+obj-$(CONFIG_DEBUG_VIRTUAL)	+= physaddr.o
diff --git a/arch/mips/mm/physaddr.c b/arch/mips/mm/physaddr.c
new file mode 100644
index 000000000000..008b524a96b2
--- /dev/null
+++ b/arch/mips/mm/physaddr.c
@@ -0,0 +1,55 @@ 
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/mmdebug.h>
+#include <linux/mm.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+
+static inline bool __debug_virt_addr_valid(unsigned long x)
+{
+	/* high_memory does not get immediately defined, and there
+	 * are early callers of __pa() against PAGE_OFFSET
+	 */
+	if (!high_memory && x >= PAGE_OFFSET)
+		return true;
+
+	if (high_memory && x >= PAGE_OFFSET && x < (unsigned long)high_memory)
+		return true;
+
+	/*
+	 * MAX_DMA_ADDRESS is a virtual address that may not correspond to an
+	 * actual physical address. Enough code relies on
+	 * virt_to_phys(MAX_DMA_ADDRESS) that we just need to work around it
+	 * and always return true.
+	 */
+	if (x == MAX_DMA_ADDRESS)
+		return true;
+
+	return false;
+}
+
+phys_addr_t __virt_to_phys(volatile const void *x)
+{
+	WARN(!__debug_virt_addr_valid((unsigned long)x),
+	     "virt_to_phys used for non-linear address: %pK (%pS)\n",
+	     x, x);
+
+	return __virt_to_phys_nodebug(x);
+}
+EXPORT_SYMBOL(__virt_to_phys);
+
+phys_addr_t __phys_addr_symbol(unsigned long x)
+{
+	/* This is bounds checking against the kernel image only.
+	 * __pa_symbol should only be used on kernel symbol addresses.
+	 */
+	VIRTUAL_BUG_ON(x < (unsigned long)_text ||
+		       x > (unsigned long)_end);
+
+	return __pa_symbol_nodebug(x);
+}
+EXPORT_SYMBOL(__phys_addr_symbol);