diff options
| author | Paul Mundt <lethal@linux-sh.org> | 2009-07-27 07:53:22 -0400 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2009-07-27 07:53:22 -0400 |
| commit | dfff0fa65ab15db45acd64b3189787d37ab163cd (patch) | |
| tree | c888641a25f83fb75a4886f6c1e63c44d889fed4 | |
| parent | 2277ab4a1df50e05bc732fe9488d4e902bb8399a (diff) | |
sh: wire up clear_user_highpage() for sh4, convert sh7705.
This wires up clear_user_highpage() on SH-4 and subsequently converts the
SH7705 32kB cache mode over to using it. Now that the SH-4 implementation
handles all of the dcache purging directly in the aliasing case, there is
no need to do this in the default clear_page() implementation.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
| -rw-r--r-- | arch/sh/include/asm/cacheflush.h | 2 | ||||
| -rw-r--r-- | arch/sh/include/asm/page.h | 12 | ||||
| -rw-r--r-- | arch/sh/include/asm/pgtable.h | 3 | ||||
| -rw-r--r-- | arch/sh/kernel/sh_ksyms_32.c | 6 | ||||
| -rw-r--r-- | arch/sh/lib/clear_page.S | 46 | ||||
| -rw-r--r-- | arch/sh/mm/Makefile_32 | 2 | ||||
| -rw-r--r-- | arch/sh/mm/pg-nommu.c | 7 | ||||
| -rw-r--r-- | arch/sh/mm/pg-sh4.c | 29 | ||||
| -rw-r--r-- | arch/sh/mm/pg-sh7705.c | 102 |
9 files changed, 27 insertions, 182 deletions
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h index 4c5462daa74c..4e360114269d 100644 --- a/arch/sh/include/asm/cacheflush.h +++ b/arch/sh/include/asm/cacheflush.h | |||
| @@ -49,7 +49,7 @@ static inline void flush_kernel_dcache_page(struct page *page) | |||
| 49 | flush_dcache_page(page); | 49 | flush_dcache_page(page); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_CACHE_OFF) | 52 | #if (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) && !defined(CONFIG_CACHE_OFF) |
| 53 | extern void copy_to_user_page(struct vm_area_struct *vma, | 53 | extern void copy_to_user_page(struct vm_area_struct *vma, |
| 54 | struct page *page, unsigned long vaddr, void *dst, const void *src, | 54 | struct page *page, unsigned long vaddr, void *dst, const void *src, |
| 55 | unsigned long len); | 55 | unsigned long len); |
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index a31ab40040f0..5208b7bfc24e 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h | |||
| @@ -56,21 +56,25 @@ pages_do_alias(unsigned long addr1, unsigned long addr2) | |||
| 56 | return (addr1 ^ addr2) & shm_align_mask; | 56 | return (addr1 ^ addr2) & shm_align_mask; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | extern void clear_page(void *to); | 59 | |
| 60 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) | ||
| 60 | extern void copy_page(void *to, void *from); | 61 | extern void copy_page(void *to, void *from); |
| 61 | 62 | ||
| 63 | struct page; | ||
| 64 | struct vm_area_struct; | ||
| 65 | |||
| 62 | #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ | 66 | #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ |
| 63 | (defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \ | 67 | (defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \ |
| 64 | defined(CONFIG_SH7705_CACHE_32KB)) | 68 | defined(CONFIG_SH7705_CACHE_32KB)) |
| 65 | struct page; | ||
| 66 | struct vm_area_struct; | ||
| 67 | extern void clear_user_page(void *to, unsigned long address, struct page *page); | 69 | extern void clear_user_page(void *to, unsigned long address, struct page *page); |
| 68 | extern void copy_user_page(void *to, void *from, unsigned long address, | 70 | extern void copy_user_page(void *to, void *from, unsigned long address, |
| 69 | struct page *page); | 71 | struct page *page); |
| 70 | #if defined(CONFIG_CPU_SH4) | 72 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) |
| 71 | extern void copy_user_highpage(struct page *to, struct page *from, | 73 | extern void copy_user_highpage(struct page *to, struct page *from, |
| 72 | unsigned long vaddr, struct vm_area_struct *vma); | 74 | unsigned long vaddr, struct vm_area_struct *vma); |
| 73 | #define __HAVE_ARCH_COPY_USER_HIGHPAGE | 75 | #define __HAVE_ARCH_COPY_USER_HIGHPAGE |
| 76 | extern void clear_user_highpage(struct page *page, unsigned long vaddr); | ||
| 77 | #define clear_user_highpage clear_user_highpage | ||
| 74 | #endif | 78 | #endif |
| 75 | #else | 79 | #else |
| 76 | #define clear_user_page(page, vaddr, pg) clear_page(page) | 80 | #define clear_user_page(page, vaddr, pg) clear_page(page) |
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index d9f68f9c3cb3..bef3ab7fc09e 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h | |||
| @@ -141,7 +141,8 @@ extern void paging_init(void); | |||
| 141 | extern void page_table_range_init(unsigned long start, unsigned long end, | 141 | extern void page_table_range_init(unsigned long start, unsigned long end, |
| 142 | pgd_t *pgd); | 142 | pgd_t *pgd); |
| 143 | 143 | ||
| 144 | #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU) | 144 | #if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ |
| 145 | defined(CONFIG_SH7705_CACHE_32KB)) && defined(CONFIG_MMU) | ||
| 145 | extern void kmap_coherent_init(void); | 146 | extern void kmap_coherent_init(void); |
| 146 | #else | 147 | #else |
| 147 | #define kmap_coherent_init() do { } while (0) | 148 | #define kmap_coherent_init() do { } while (0) |
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index cec610888e28..8dbe26b17c44 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c | |||
| @@ -101,11 +101,6 @@ EXPORT_SYMBOL(flush_cache_range); | |||
| 101 | EXPORT_SYMBOL(flush_dcache_page); | 101 | EXPORT_SYMBOL(flush_dcache_page); |
| 102 | #endif | 102 | #endif |
| 103 | 103 | ||
| 104 | #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ | ||
| 105 | (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) | ||
| 106 | EXPORT_SYMBOL(clear_user_page); | ||
| 107 | #endif | ||
| 108 | |||
| 109 | #ifdef CONFIG_MCOUNT | 104 | #ifdef CONFIG_MCOUNT |
| 110 | DECLARE_EXPORT(mcount); | 105 | DECLARE_EXPORT(mcount); |
| 111 | #endif | 106 | #endif |
| @@ -114,7 +109,6 @@ EXPORT_SYMBOL(csum_partial_copy_generic); | |||
| 114 | #ifdef CONFIG_IPV6 | 109 | #ifdef CONFIG_IPV6 |
| 115 | EXPORT_SYMBOL(csum_ipv6_magic); | 110 | EXPORT_SYMBOL(csum_ipv6_magic); |
| 116 | #endif | 111 | #endif |
| 117 | EXPORT_SYMBOL(clear_page); | ||
| 118 | EXPORT_SYMBOL(copy_page); | 112 | EXPORT_SYMBOL(copy_page); |
| 119 | EXPORT_SYMBOL(__clear_user); | 113 | EXPORT_SYMBOL(__clear_user); |
| 120 | EXPORT_SYMBOL(_ebss); | 114 | EXPORT_SYMBOL(_ebss); |
diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/clear_page.S index 8342bfbde64c..bee9817e055d 100644 --- a/arch/sh/lib/clear_page.S +++ b/arch/sh/lib/clear_page.S | |||
| @@ -8,52 +8,6 @@ | |||
| 8 | #include <linux/linkage.h> | 8 | #include <linux/linkage.h> |
| 9 | #include <asm/page.h> | 9 | #include <asm/page.h> |
| 10 | 10 | ||
| 11 | /* | ||
| 12 | * clear_page | ||
| 13 | * @to: P1 address | ||
| 14 | * | ||
| 15 | * void clear_page(void *to) | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* | ||
| 19 | * r0 --- scratch | ||
| 20 | * r4 --- to | ||
| 21 | * r5 --- to + PAGE_SIZE | ||
| 22 | */ | ||
| 23 | ENTRY(clear_page) | ||
| 24 | mov r4,r5 | ||
| 25 | mov.l .Llimit,r0 | ||
| 26 | add r0,r5 | ||
| 27 | mov #0,r0 | ||
| 28 | ! | ||
| 29 | 1: | ||
| 30 | #if defined(CONFIG_CPU_SH4) | ||
| 31 | movca.l r0,@r4 | ||
| 32 | mov r4,r1 | ||
| 33 | #else | ||
| 34 | mov.l r0,@r4 | ||
| 35 | #endif | ||
| 36 | add #32,r4 | ||
| 37 | mov.l r0,@-r4 | ||
| 38 | mov.l r0,@-r4 | ||
| 39 | mov.l r0,@-r4 | ||
| 40 | mov.l r0,@-r4 | ||
| 41 | mov.l r0,@-r4 | ||
| 42 | mov.l r0,@-r4 | ||
| 43 | mov.l r0,@-r4 | ||
| 44 | #if defined(CONFIG_CPU_SH4) | ||
| 45 | ocbwb @r1 | ||
| 46 | #endif | ||
| 47 | cmp/eq r5,r4 | ||
| 48 | bf/s 1b | ||
| 49 | add #28,r4 | ||
| 50 | ! | ||
| 51 | rts | ||
| 52 | nop | ||
| 53 | |||
| 54 | .balign 4 | ||
| 55 | .Llimit: .long (PAGE_SIZE-28) | ||
| 56 | |||
| 57 | ENTRY(__clear_user) | 11 | ENTRY(__clear_user) |
| 58 | ! | 12 | ! |
| 59 | mov #0, r0 | 13 | mov #0, r0 |
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 986a1e055834..5c04bbb08d36 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 | |||
| @@ -31,7 +31,7 @@ tlb-$(CONFIG_CPU_HAS_PTEAEX) := tlb-pteaex.o | |||
| 31 | obj-y += $(tlb-y) | 31 | obj-y += $(tlb-y) |
| 32 | ifndef CONFIG_CACHE_OFF | 32 | ifndef CONFIG_CACHE_OFF |
| 33 | obj-$(CONFIG_CPU_SH4) += pg-sh4.o | 33 | obj-$(CONFIG_CPU_SH4) += pg-sh4.o |
| 34 | obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o | 34 | obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh4.o |
| 35 | endif | 35 | endif |
| 36 | endif | 36 | endif |
| 37 | 37 | ||
diff --git a/arch/sh/mm/pg-nommu.c b/arch/sh/mm/pg-nommu.c index 91ed4e695ff7..7e33b486b7e9 100644 --- a/arch/sh/mm/pg-nommu.c +++ b/arch/sh/mm/pg-nommu.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/sh/mm/pg-nommu.c | 2 | * arch/sh/mm/pg-nommu.c |
| 3 | * | 3 | * |
| 4 | * clear_page()/copy_page() implementation for MMUless SH. | 4 | * copy_page()/__copy_user()/__clear_user() implementations for MMUless SH. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2003 Paul Mundt | 6 | * Copyright (C) 2003 Paul Mundt |
| 7 | * | 7 | * |
| @@ -20,11 +20,6 @@ void copy_page(void *to, void *from) | |||
| 20 | memcpy(to, from, PAGE_SIZE); | 20 | memcpy(to, from, PAGE_SIZE); |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | void clear_page(void *to) | ||
| 24 | { | ||
| 25 | memset(to, 0, PAGE_SIZE); | ||
| 26 | } | ||
| 27 | |||
| 28 | __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n) | 23 | __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n) |
| 29 | { | 24 | { |
| 30 | memcpy(to, from, n); | 25 | memcpy(to, from, n); |
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index f3c4b2a54fc7..4d93070b8220 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * arch/sh/mm/pg-sh4.c | 2 | * arch/sh/mm/pg-sh4.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
| 5 | * Copyright (C) 2002 - 2007 Paul Mundt | 5 | * Copyright (C) 2002 - 2009 Paul Mundt |
| 6 | * | 6 | * |
| 7 | * Released under the terms of the GNU GPL v2.0. | 7 | * Released under the terms of the GNU GPL v2.0. |
| 8 | */ | 8 | */ |
| @@ -58,20 +58,6 @@ static inline void kunmap_coherent(struct page *page) | |||
| 58 | preempt_check_resched(); | 58 | preempt_check_resched(); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | /* | ||
| 62 | * clear_user_page | ||
| 63 | * @to: P1 address | ||
| 64 | * @address: U0 address to be mapped | ||
| 65 | * @page: page (virt_to_page(to)) | ||
| 66 | */ | ||
| 67 | void clear_user_page(void *to, unsigned long address, struct page *page) | ||
| 68 | { | ||
| 69 | clear_page(to); | ||
| 70 | |||
| 71 | if (pages_do_alias((unsigned long)to, address & PAGE_MASK)) | ||
| 72 | __flush_wback_region(to, PAGE_SIZE); | ||
| 73 | } | ||
| 74 | |||
| 75 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | 61 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, |
| 76 | unsigned long vaddr, void *dst, const void *src, | 62 | unsigned long vaddr, void *dst, const void *src, |
| 77 | unsigned long len) | 63 | unsigned long len) |
| @@ -128,3 +114,16 @@ void copy_user_highpage(struct page *to, struct page *from, | |||
| 128 | smp_wmb(); | 114 | smp_wmb(); |
| 129 | } | 115 | } |
| 130 | EXPORT_SYMBOL(copy_user_highpage); | 116 | EXPORT_SYMBOL(copy_user_highpage); |
| 117 | |||
| 118 | void clear_user_highpage(struct page *page, unsigned long vaddr) | ||
| 119 | { | ||
| 120 | void *kaddr = kmap_atomic(page, KM_USER0); | ||
| 121 | |||
| 122 | clear_page(kaddr); | ||
| 123 | |||
| 124 | if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK)) | ||
| 125 | __flush_wback_region(kaddr, PAGE_SIZE); | ||
| 126 | |||
| 127 | kunmap_atomic(kaddr, KM_USER0); | ||
| 128 | } | ||
| 129 | EXPORT_SYMBOL(clear_user_highpage); | ||
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c deleted file mode 100644 index 684891b5c8c0..000000000000 --- a/arch/sh/mm/pg-sh7705.c +++ /dev/null | |||
| @@ -1,102 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/sh/mm/pg-sh7705.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1999, 2000 Niibe Yutaka | ||
| 5 | * Copyright (C) 2004 Alex Song | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 8 | * License. See the file "COPYING" in the main directory of this archive | ||
| 9 | * for more details. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/mman.h> | ||
| 15 | #include <linux/mm.h> | ||
| 16 | #include <linux/threads.h> | ||
| 17 | #include <linux/fs.h> | ||
| 18 | #include <asm/addrspace.h> | ||
| 19 | #include <asm/page.h> | ||
| 20 | #include <asm/pgtable.h> | ||
| 21 | #include <asm/processor.h> | ||
| 22 | #include <asm/cache.h> | ||
| 23 | #include <asm/io.h> | ||
| 24 | #include <asm/uaccess.h> | ||
| 25 | #include <asm/pgalloc.h> | ||
| 26 | #include <asm/mmu_context.h> | ||
| 27 | #include <asm/cacheflush.h> | ||
| 28 | |||
| 29 | static void __flush_purge_virtual_region(void *p1, void *virt, int size) | ||
| 30 | { | ||
| 31 | unsigned long v; | ||
| 32 | unsigned long begin, end; | ||
| 33 | unsigned long p1_begin; | ||
| 34 | |||
| 35 | |||
| 36 | begin = L1_CACHE_ALIGN((unsigned long)virt); | ||
| 37 | end = L1_CACHE_ALIGN((unsigned long)virt + size); | ||
| 38 | |||
| 39 | p1_begin = (unsigned long)p1 & ~(L1_CACHE_BYTES - 1); | ||
| 40 | |||
| 41 | /* do this the slow way as we may not have TLB entries | ||
| 42 | * for virt yet. */ | ||
| 43 | for (v = begin; v < end; v += L1_CACHE_BYTES) { | ||
| 44 | unsigned long p; | ||
| 45 | unsigned long ways, addr; | ||
| 46 | |||
| 47 | p = __pa(p1_begin); | ||
| 48 | |||
| 49 | ways = current_cpu_data.dcache.ways; | ||
| 50 | addr = CACHE_OC_ADDRESS_ARRAY; | ||
| 51 | |||
| 52 | do { | ||
| 53 | unsigned long data; | ||
| 54 | |||
| 55 | addr |= (v & current_cpu_data.dcache.entry_mask); | ||
| 56 | |||
| 57 | data = ctrl_inl(addr); | ||
| 58 | if ((data & CACHE_PHYSADDR_MASK) == | ||
| 59 | (p & CACHE_PHYSADDR_MASK)) { | ||
| 60 | data &= ~(SH_CACHE_UPDATED|SH_CACHE_VALID); | ||
| 61 | ctrl_outl(data, addr); | ||
| 62 | } | ||
| 63 | |||
| 64 | addr += current_cpu_data.dcache.way_incr; | ||
| 65 | } while (--ways); | ||
| 66 | |||
| 67 | p1_begin += L1_CACHE_BYTES; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | /* | ||
| 72 | * clear_user_page | ||
| 73 | * @to: P1 address | ||
| 74 | * @address: U0 address to be mapped | ||
| 75 | */ | ||
| 76 | void clear_user_page(void *to, unsigned long address, struct page *pg) | ||
| 77 | { | ||
| 78 | if (pages_do_alias(address, (unsigned long)to)) | ||
| 79 | __flush_purge_virtual_region(to, | ||
| 80 | (void *)(address & 0xfffff000), | ||
| 81 | PAGE_SIZE); | ||
| 82 | |||
| 83 | clear_page(to); | ||
| 84 | __flush_wback_region(to, PAGE_SIZE); | ||
| 85 | } | ||
| 86 | |||
| 87 | /* | ||
| 88 | * copy_user_page | ||
| 89 | * @to: P1 address | ||
| 90 | * @from: P1 address | ||
| 91 | * @address: U0 address to be mapped | ||
| 92 | */ | ||
| 93 | void copy_user_page(void *to, void *from, unsigned long address, struct page *pg) | ||
| 94 | { | ||
| 95 | if (pages_do_alias(address, (unsigned long)to)) | ||
| 96 | __flush_purge_virtual_region(to, | ||
| 97 | (void *)(address & 0xfffff000), | ||
| 98 | PAGE_SIZE); | ||
| 99 | |||
| 100 | copy_page(to, from); | ||
| 101 | __flush_wback_region(to, PAGE_SIZE); | ||
| 102 | } | ||
