aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-07-27 07:53:22 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-07-27 07:53:22 -0400
commitdfff0fa65ab15db45acd64b3189787d37ab163cd (patch)
treec888641a25f83fb75a4886f6c1e63c44d889fed4 /arch/sh
parent2277ab4a1df50e05bc732fe9488d4e902bb8399a (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>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/include/asm/cacheflush.h2
-rw-r--r--arch/sh/include/asm/page.h12
-rw-r--r--arch/sh/include/asm/pgtable.h3
-rw-r--r--arch/sh/kernel/sh_ksyms_32.c6
-rw-r--r--arch/sh/lib/clear_page.S46
-rw-r--r--arch/sh/mm/Makefile_322
-rw-r--r--arch/sh/mm/pg-nommu.c7
-rw-r--r--arch/sh/mm/pg-sh4.c29
-rw-r--r--arch/sh/mm/pg-sh7705.c102
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)
53extern void copy_to_user_page(struct vm_area_struct *vma, 53extern 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
59extern void clear_page(void *to); 59
60#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
60extern void copy_page(void *to, void *from); 61extern void copy_page(void *to, void *from);
61 62
63struct page;
64struct 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))
65struct page;
66struct vm_area_struct;
67extern void clear_user_page(void *to, unsigned long address, struct page *page); 69extern void clear_user_page(void *to, unsigned long address, struct page *page);
68extern void copy_user_page(void *to, void *from, unsigned long address, 70extern 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)
71extern void copy_user_highpage(struct page *to, struct page *from, 73extern 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
76extern 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);
141extern void page_table_range_init(unsigned long start, unsigned long end, 141extern 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)
145extern void kmap_coherent_init(void); 146extern 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);
101EXPORT_SYMBOL(flush_dcache_page); 101EXPORT_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))
106EXPORT_SYMBOL(clear_user_page);
107#endif
108
109#ifdef CONFIG_MCOUNT 104#ifdef CONFIG_MCOUNT
110DECLARE_EXPORT(mcount); 105DECLARE_EXPORT(mcount);
111#endif 106#endif
@@ -114,7 +109,6 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
114#ifdef CONFIG_IPV6 109#ifdef CONFIG_IPV6
115EXPORT_SYMBOL(csum_ipv6_magic); 110EXPORT_SYMBOL(csum_ipv6_magic);
116#endif 111#endif
117EXPORT_SYMBOL(clear_page);
118EXPORT_SYMBOL(copy_page); 112EXPORT_SYMBOL(copy_page);
119EXPORT_SYMBOL(__clear_user); 113EXPORT_SYMBOL(__clear_user);
120EXPORT_SYMBOL(_ebss); 114EXPORT_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 */
23ENTRY(clear_page)
24 mov r4,r5
25 mov.l .Llimit,r0
26 add r0,r5
27 mov #0,r0
28 !
291:
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
57ENTRY(__clear_user) 11ENTRY(__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
31obj-y += $(tlb-y) 31obj-y += $(tlb-y)
32ifndef CONFIG_CACHE_OFF 32ifndef CONFIG_CACHE_OFF
33obj-$(CONFIG_CPU_SH4) += pg-sh4.o 33obj-$(CONFIG_CPU_SH4) += pg-sh4.o
34obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o 34obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh4.o
35endif 35endif
36endif 36endif
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
23void 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 */
67void 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
75void copy_to_user_page(struct vm_area_struct *vma, struct page *page, 61void 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}
130EXPORT_SYMBOL(copy_user_highpage); 116EXPORT_SYMBOL(copy_user_highpage);
117
118void 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}
129EXPORT_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
29static 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 */
76void 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 */
93void 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}