forked from mirrors/linux
		
	MIPS: Add support for CONFIG_DEBUG_VIRTUAL
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> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
This commit is contained in:
		
							parent
							
								
									666c1fc90c
								
							
						
					
					
						commit
						dfad83cb71
					
				
					 6 changed files with 83 additions and 4 deletions
				
			
		| 
						 | 
					@ -4,6 +4,7 @@ config MIPS
 | 
				
			||||||
	default y
 | 
						default y
 | 
				
			||||||
	select ARCH_32BIT_OFF_T if !64BIT
 | 
						select ARCH_32BIT_OFF_T if !64BIT
 | 
				
			||||||
	select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT
 | 
						select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT
 | 
				
			||||||
 | 
						select ARCH_HAS_DEBUG_VIRTUAL if !64BIT
 | 
				
			||||||
	select ARCH_HAS_FORTIFY_SOURCE
 | 
						select ARCH_HAS_FORTIFY_SOURCE
 | 
				
			||||||
	select ARCH_HAS_KCOV
 | 
						select ARCH_HAS_KCOV
 | 
				
			||||||
	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if !EVA
 | 
						select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if !EVA
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					 *     almost all conceivable cases a device driver should not be using
 | 
				
			||||||
 *     this function
 | 
					 *     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);
 | 
						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
 | 
					 *     phys_to_virt    -       map physical address to virtual
 | 
				
			||||||
 *     @address: address to remap
 | 
					 *     @address: address to remap
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					 * 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/
 | 
					 * 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
 | 
					#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
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 | 
					#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mips_vdso_image *image = current->thread.abi->vdso;
 | 
						struct mips_vdso_image *image = current->thread.abi->vdso;
 | 
				
			||||||
	struct mm_struct *mm = current->mm;
 | 
						struct mm_struct *mm = current->mm;
 | 
				
			||||||
	unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr, gic_pfn;
 | 
						unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr, gic_pfn, gic_base;
 | 
				
			||||||
	struct vm_area_struct *vma;
 | 
						struct vm_area_struct *vma;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,7 +158,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Map GIC user page. */
 | 
						/* Map GIC user page. */
 | 
				
			||||||
	if (gic_size) {
 | 
						if (gic_size) {
 | 
				
			||||||
		gic_pfn = virt_to_phys(mips_gic_base + MIPS_GIC_USER_OFS) >> PAGE_SHIFT;
 | 
							gic_base = (unsigned long)mips_gic_base + MIPS_GIC_USER_OFS;
 | 
				
			||||||
 | 
							gic_pfn = virt_to_phys((void *)gic_base) >> PAGE_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = io_remap_pfn_range(vma, base, gic_pfn, gic_size,
 | 
							ret = io_remap_pfn_range(vma, base, gic_pfn, gic_size,
 | 
				
			||||||
					 pgprot_noncached(vma->vm_page_prot));
 | 
										 pgprot_noncached(vma->vm_page_prot));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,3 +40,5 @@ obj-$(CONFIG_R5000_CPU_SCACHE)	+= sc-r5k.o
 | 
				
			||||||
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
 | 
					obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
 | 
				
			||||||
obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
 | 
					obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
 | 
				
			||||||
obj-$(CONFIG_SCACHE_DEBUGFS)	+= sc-debugfs.o
 | 
					obj-$(CONFIG_SCACHE_DEBUGFS)	+= sc-debugfs.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					obj-$(CONFIG_DEBUG_VIRTUAL)	+= physaddr.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										56
									
								
								arch/mips/mm/physaddr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								arch/mips/mm/physaddr.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,56 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					#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);
 | 
				
			||||||
		Loading…
	
		Reference in a new issue