diff options
author | Paul Mundt <lethal@linux-sh.org> | 2008-11-12 12:53:48 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-11-12 12:53:48 +0900 |
commit | 185aed75570fb4f78ef283dfa26cd9da5fa06a91 (patch) | |
tree | a98cb3f46bf9426f8d4a660d63b8a3ac7d9f369d /arch | |
parent | ade7a9b4ccd20ab8159c77a0abd20552f2d6b06c (diff) |
sh: Provide a sane valid_phys_addr_range() to prevent TLB reset with PMB.
With the PMB enabled, only P1SEG and up are covered by the PMB mappings,
meaning that situations where out-of-bounds physical addresses are read
from will lead to TLB reset after the PMB miss, allowing for use cases
like dd if=/dev/mem to reset the TLB.
Fix this up to make sure the reference is between __MEMORY_START (phys)
and __pa(high_memory). This is coherent across all variants of sh/sh64
with and without MMU, though the PMB bug itself is only applicable to
SH-4A parts.
Reported-by: Hideo Saito <saito@densan.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/include/asm/io.h | 4 | ||||
-rw-r--r-- | arch/sh/mm/Makefile_32 | 2 | ||||
-rw-r--r-- | arch/sh/mm/Makefile_64 | 2 | ||||
-rw-r--r-- | arch/sh/mm/mmap.c | 31 |
4 files changed, 37 insertions, 2 deletions
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 436c28539577..65eaae34e753 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -293,6 +293,10 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) */ #define xlate_dev_kmem_ptr(p) p +#define ARCH_HAS_VALID_PHYS_ADDR_RANGE +int valid_phys_addr_range(unsigned long addr, size_t size); +int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); + #endif /* __KERNEL__ */ #endif /* __ASM_SH_IO_H */ diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 70e0906023cc..f066e76da204 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 @@ -2,7 +2,7 @@ # Makefile for the Linux SuperH-specific parts of the memory manager. # -obj-y := init.o extable_32.o consistent.o +obj-y := init.o extable_32.o consistent.o mmap.o ifndef CONFIG_CACHE_OFF cache-$(CONFIG_CPU_SH2) := cache-sh2.o diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64 index 0d92a8a3ac9a..9481d0f54efd 100644 --- a/arch/sh/mm/Makefile_64 +++ b/arch/sh/mm/Makefile_64 @@ -2,7 +2,7 @@ # Makefile for the Linux SuperH-specific parts of the memory manager. # -obj-y := init.o consistent.o +obj-y := init.o consistent.o mmap.o mmu-y := tlb-nommu.o pg-nommu.o extable_32.o mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \ diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c new file mode 100644 index 000000000000..1f3cc3d92d3d --- /dev/null +++ b/arch/sh/mm/mmap.c @@ -0,0 +1,31 @@ +/* + * arch/sh/mm/mmap.c + * + * Copyright (C) 2008 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/io.h> +#include <linux/mm.h> +#include <asm/page.h> + +/* + * You really shouldn't be using read() or write() on /dev/mem. This + * might go away in the future. + */ +int valid_phys_addr_range(unsigned long addr, size_t count) +{ + if (addr < (PAGE_OFFSET + (PFN_START << PAGE_SHIFT))) + return 0; + if (addr + count > __pa(high_memory)) + return 0; + + return 1; +} + +int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) +{ + return 1; +} |