aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/kernel/cpu/init.c6
-rw-r--r--arch/sh/kernel/cpu/sh3/probe.c6
-rw-r--r--arch/sh/kernel/vmlinux_32.lds.S9
-rw-r--r--arch/sh/mm/cache-debugfs.c9
-rw-r--r--arch/sh/mm/cache-sh4.c14
-rw-r--r--arch/sh/mm/cache-sh7705.c12
-rw-r--r--arch/sh/mm/init.c16
-rw-r--r--arch/sh/mm/pmb.c18
-rw-r--r--arch/sh/mm/tlb-sh4.c7
-rw-r--r--include/asm-sh/fixmap.h1
-rw-r--r--include/asm-sh/sections.h1
-rw-r--r--include/asm-sh/system.h2
-rw-r--r--include/asm-sh/system_32.h36
-rw-r--r--include/asm-sh/system_64.h7
14 files changed, 88 insertions, 56 deletions
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index fd1688e6c61c..0f0c76a842e4 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -64,11 +64,11 @@ static void __init speculative_execution_init(void)
64 * Generic first-level cache init 64 * Generic first-level cache init
65 */ 65 */
66#ifdef CONFIG_SUPERH32 66#ifdef CONFIG_SUPERH32
67static void __init cache_init(void) 67static void __uses_jump_to_uncached cache_init(void)
68{ 68{
69 unsigned long ccr, flags; 69 unsigned long ccr, flags;
70 70
71 jump_to_P2(); 71 jump_to_uncached();
72 ccr = ctrl_inl(CCR); 72 ccr = ctrl_inl(CCR);
73 73
74 /* 74 /*
@@ -145,7 +145,7 @@ static void __init cache_init(void)
145#endif 145#endif
146 146
147 ctrl_outl(flags, CCR); 147 ctrl_outl(flags, CCR);
148 back_to_P1(); 148 back_to_cached();
149} 149}
150#else 150#else
151#define cache_init() do { } while (0) 151#define cache_init() do { } while (0)
diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c
index bf579e061e09..22070e43e34d 100644
--- a/arch/sh/kernel/cpu/sh3/probe.c
+++ b/arch/sh/kernel/cpu/sh3/probe.c
@@ -16,11 +16,11 @@
16#include <asm/cache.h> 16#include <asm/cache.h>
17#include <asm/io.h> 17#include <asm/io.h>
18 18
19int __init detect_cpu_and_cache_system(void) 19int __uses_jump_to_uncached detect_cpu_and_cache_system(void)
20{ 20{
21 unsigned long addr0, addr1, data0, data1, data2, data3; 21 unsigned long addr0, addr1, data0, data1, data2, data3;
22 22
23 jump_to_P2(); 23 jump_to_uncached();
24 /* 24 /*
25 * Check if the entry shadows or not. 25 * Check if the entry shadows or not.
26 * When shadowed, it's 128-entry system. 26 * When shadowed, it's 128-entry system.
@@ -48,7 +48,7 @@ int __init detect_cpu_and_cache_system(void)
48 ctrl_outl(data0&~SH_CACHE_VALID, addr0); 48 ctrl_outl(data0&~SH_CACHE_VALID, addr0);
49 ctrl_outl(data2&~SH_CACHE_VALID, addr1); 49 ctrl_outl(data2&~SH_CACHE_VALID, addr1);
50 50
51 back_to_P1(); 51 back_to_cached();
52 52
53 boot_cpu_data.dcache.ways = 4; 53 boot_cpu_data.dcache.ways = 4;
54 boot_cpu_data.dcache.entry_shift = 4; 54 boot_cpu_data.dcache.entry_shift = 4;
diff --git a/arch/sh/kernel/vmlinux_32.lds.S b/arch/sh/kernel/vmlinux_32.lds.S
index 0956fb3681a3..50c69c18dced 100644
--- a/arch/sh/kernel/vmlinux_32.lds.S
+++ b/arch/sh/kernel/vmlinux_32.lds.S
@@ -43,6 +43,15 @@ SECTIONS
43 NOTES 43 NOTES
44 RO_DATA(PAGE_SIZE) 44 RO_DATA(PAGE_SIZE)
45 45
46 /*
47 * Code which must be executed uncached and the associated data
48 */
49 . = ALIGN(PAGE_SIZE);
50 __uncached_start = .;
51 .uncached.text : { *(.uncached.text) }
52 .uncached.data : { *(.uncached.data) }
53 __uncached_end = .;
54
46 . = ALIGN(THREAD_SIZE); 55 . = ALIGN(THREAD_SIZE);
47 .data : { /* Data */ 56 .data : { /* Data */
48 *(.data.init_task) 57 *(.data.init_task)
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
index de6d2c9aa477..db6d950b6f5e 100644
--- a/arch/sh/mm/cache-debugfs.c
+++ b/arch/sh/mm/cache-debugfs.c
@@ -22,7 +22,8 @@ enum cache_type {
22 CACHE_TYPE_UNIFIED, 22 CACHE_TYPE_UNIFIED,
23}; 23};
24 24
25static int cache_seq_show(struct seq_file *file, void *iter) 25static int __uses_jump_to_uncached cache_seq_show(struct seq_file *file,
26 void *iter)
26{ 27{
27 unsigned int cache_type = (unsigned int)file->private; 28 unsigned int cache_type = (unsigned int)file->private;
28 struct cache_info *cache; 29 struct cache_info *cache;
@@ -34,11 +35,11 @@ static int cache_seq_show(struct seq_file *file, void *iter)
34 * Go uncached immediately so we don't skew the results any 35 * Go uncached immediately so we don't skew the results any
35 * more than we already are.. 36 * more than we already are..
36 */ 37 */
37 jump_to_P2(); 38 jump_to_uncached();
38 39
39 ccr = ctrl_inl(CCR); 40 ccr = ctrl_inl(CCR);
40 if ((ccr & CCR_CACHE_ENABLE) == 0) { 41 if ((ccr & CCR_CACHE_ENABLE) == 0) {
41 back_to_P1(); 42 back_to_cached();
42 43
43 seq_printf(file, "disabled\n"); 44 seq_printf(file, "disabled\n");
44 return 0; 45 return 0;
@@ -104,7 +105,7 @@ static int cache_seq_show(struct seq_file *file, void *iter)
104 addrstart += cache->way_incr; 105 addrstart += cache->way_incr;
105 } 106 }
106 107
107 back_to_P1(); 108 back_to_cached();
108 109
109 return 0; 110 return 0;
110} 111}
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 226b190c5b9c..43d7ff6b6ec7 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -190,7 +190,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
190 * .. which happens to be the same behavior as flush_icache_range(). 190 * .. which happens to be the same behavior as flush_icache_range().
191 * So, we simply flush out a line. 191 * So, we simply flush out a line.
192 */ 192 */
193void flush_cache_sigtramp(unsigned long addr) 193void __uses_jump_to_uncached flush_cache_sigtramp(unsigned long addr)
194{ 194{
195 unsigned long v, index; 195 unsigned long v, index;
196 unsigned long flags; 196 unsigned long flags;
@@ -205,13 +205,13 @@ void flush_cache_sigtramp(unsigned long addr)
205 (v & boot_cpu_data.icache.entry_mask); 205 (v & boot_cpu_data.icache.entry_mask);
206 206
207 local_irq_save(flags); 207 local_irq_save(flags);
208 jump_to_P2(); 208 jump_to_uncached();
209 209
210 for (i = 0; i < boot_cpu_data.icache.ways; 210 for (i = 0; i < boot_cpu_data.icache.ways;
211 i++, index += boot_cpu_data.icache.way_incr) 211 i++, index += boot_cpu_data.icache.way_incr)
212 ctrl_outl(0, index); /* Clear out Valid-bit */ 212 ctrl_outl(0, index); /* Clear out Valid-bit */
213 213
214 back_to_P1(); 214 back_to_cached();
215 wmb(); 215 wmb();
216 local_irq_restore(flags); 216 local_irq_restore(flags);
217} 217}
@@ -256,12 +256,12 @@ void flush_dcache_page(struct page *page)
256} 256}
257 257
258/* TODO: Selective icache invalidation through IC address array.. */ 258/* TODO: Selective icache invalidation through IC address array.. */
259static inline void flush_icache_all(void) 259static inline void __uses_jump_to_uncached flush_icache_all(void)
260{ 260{
261 unsigned long flags, ccr; 261 unsigned long flags, ccr;
262 262
263 local_irq_save(flags); 263 local_irq_save(flags);
264 jump_to_P2(); 264 jump_to_uncached();
265 265
266 /* Flush I-cache */ 266 /* Flush I-cache */
267 ccr = ctrl_inl(CCR); 267 ccr = ctrl_inl(CCR);
@@ -269,11 +269,11 @@ static inline void flush_icache_all(void)
269 ctrl_outl(ccr, CCR); 269 ctrl_outl(ccr, CCR);
270 270
271 /* 271 /*
272 * back_to_P1() will take care of the barrier for us, don't add 272 * back_to_cached() will take care of the barrier for us, don't add
273 * another one! 273 * another one!
274 */ 274 */
275 275
276 back_to_P1(); 276 back_to_cached();
277 local_irq_restore(flags); 277 local_irq_restore(flags);
278} 278}
279 279
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index 4896d7376926..22dacc778823 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -71,7 +71,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
71/* 71/*
72 * Writeback&Invalidate the D-cache of the page 72 * Writeback&Invalidate the D-cache of the page
73 */ 73 */
74static void __flush_dcache_page(unsigned long phys) 74static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys)
75{ 75{
76 unsigned long ways, waysize, addrstart; 76 unsigned long ways, waysize, addrstart;
77 unsigned long flags; 77 unsigned long flags;
@@ -92,7 +92,7 @@ static void __flush_dcache_page(unsigned long phys)
92 * possible. 92 * possible.
93 */ 93 */
94 local_irq_save(flags); 94 local_irq_save(flags);
95 jump_to_P2(); 95 jump_to_uncached();
96 96
97 ways = current_cpu_data.dcache.ways; 97 ways = current_cpu_data.dcache.ways;
98 waysize = current_cpu_data.dcache.sets; 98 waysize = current_cpu_data.dcache.sets;
@@ -118,7 +118,7 @@ static void __flush_dcache_page(unsigned long phys)
118 addrstart += current_cpu_data.dcache.way_incr; 118 addrstart += current_cpu_data.dcache.way_incr;
119 } while (--ways); 119 } while (--ways);
120 120
121 back_to_P1(); 121 back_to_cached();
122 local_irq_restore(flags); 122 local_irq_restore(flags);
123} 123}
124 124
@@ -132,15 +132,15 @@ void flush_dcache_page(struct page *page)
132 __flush_dcache_page(PHYSADDR(page_address(page))); 132 __flush_dcache_page(PHYSADDR(page_address(page)));
133} 133}
134 134
135void flush_cache_all(void) 135void __uses_jump_to_uncached flush_cache_all(void)
136{ 136{
137 unsigned long flags; 137 unsigned long flags;
138 138
139 local_irq_save(flags); 139 local_irq_save(flags);
140 jump_to_P2(); 140 jump_to_uncached();
141 141
142 cache_wback_all(); 142 cache_wback_all();
143 back_to_P1(); 143 back_to_cached();
144 local_irq_restore(flags); 144 local_irq_restore(flags);
145} 145}
146 146
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 79c309780f95..094225e0d722 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -23,6 +23,7 @@
23 23
24DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 24DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
25pgd_t swapper_pg_dir[PTRS_PER_PGD]; 25pgd_t swapper_pg_dir[PTRS_PER_PGD];
26unsigned long cached_to_uncached = 0;
26 27
27void show_mem(void) 28void show_mem(void)
28{ 29{
@@ -99,7 +100,8 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
99 100
100 set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); 101 set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
101 102
102 flush_tlb_one(get_asid(), addr); 103 if (cached_to_uncached)
104 flush_tlb_one(get_asid(), addr);
103} 105}
104 106
105/* 107/*
@@ -164,6 +166,18 @@ void __init paging_init(void)
164 } 166 }
165 167
166 free_area_init_nodes(max_zone_pfns); 168 free_area_init_nodes(max_zone_pfns);
169
170 /* Set up the uncached fixmap */
171 set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start));
172
173#ifdef CONFIG_29BIT
174 /*
175 * Handle trivial transitions between cached and uncached
176 * segments, making use of the 1:1 mapping relationship in
177 * 512MB lowmem.
178 */
179 cached_to_uncached = P2SEG - P1SEG;
180#endif
167} 181}
168 182
169static struct kcore_list kcore_mem, kcore_vmalloc; 183static struct kcore_list kcore_mem, kcore_vmalloc;
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index ef6ab39eaf65..ab81c602295f 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -163,18 +163,18 @@ repeat:
163 return 0; 163 return 0;
164} 164}
165 165
166int set_pmb_entry(struct pmb_entry *pmbe) 166int __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe)
167{ 167{
168 int ret; 168 int ret;
169 169
170 jump_to_P2(); 170 jump_to_uncached();
171 ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry); 171 ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry);
172 back_to_P1(); 172 back_to_cached();
173 173
174 return ret; 174 return ret;
175} 175}
176 176
177void clear_pmb_entry(struct pmb_entry *pmbe) 177void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe)
178{ 178{
179 unsigned int entry = pmbe->entry; 179 unsigned int entry = pmbe->entry;
180 unsigned long addr; 180 unsigned long addr;
@@ -188,7 +188,7 @@ void clear_pmb_entry(struct pmb_entry *pmbe)
188 entry >= NR_PMB_ENTRIES)) 188 entry >= NR_PMB_ENTRIES))
189 return; 189 return;
190 190
191 jump_to_P2(); 191 jump_to_uncached();
192 192
193 /* Clear V-bit */ 193 /* Clear V-bit */
194 addr = mk_pmb_addr(entry); 194 addr = mk_pmb_addr(entry);
@@ -197,7 +197,7 @@ void clear_pmb_entry(struct pmb_entry *pmbe)
197 addr = mk_pmb_data(entry); 197 addr = mk_pmb_data(entry);
198 ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr); 198 ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
199 199
200 back_to_P1(); 200 back_to_cached();
201 201
202 clear_bit(entry, &pmb_map); 202 clear_bit(entry, &pmb_map);
203} 203}
@@ -302,7 +302,7 @@ static void pmb_cache_ctor(struct kmem_cache *cachep, void *pmb)
302 pmbe->entry = PMB_NO_ENTRY; 302 pmbe->entry = PMB_NO_ENTRY;
303} 303}
304 304
305static int __init pmb_init(void) 305static int __uses_jump_to_uncached pmb_init(void)
306{ 306{
307 unsigned int nr_entries = ARRAY_SIZE(pmb_init_map); 307 unsigned int nr_entries = ARRAY_SIZE(pmb_init_map);
308 unsigned int entry, i; 308 unsigned int entry, i;
@@ -312,7 +312,7 @@ static int __init pmb_init(void)
312 pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry), 0, 312 pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry), 0,
313 SLAB_PANIC, pmb_cache_ctor); 313 SLAB_PANIC, pmb_cache_ctor);
314 314
315 jump_to_P2(); 315 jump_to_uncached();
316 316
317 /* 317 /*
318 * Ordering is important, P2 must be mapped in the PMB before we 318 * Ordering is important, P2 must be mapped in the PMB before we
@@ -335,7 +335,7 @@ static int __init pmb_init(void)
335 i |= MMUCR_TI; 335 i |= MMUCR_TI;
336 ctrl_outl(i, MMUCR); 336 ctrl_outl(i, MMUCR);
337 337
338 back_to_P1(); 338 back_to_cached();
339 339
340 return 0; 340 return 0;
341} 341}
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
index 2d1dd6044307..f0c7b7397fa6 100644
--- a/arch/sh/mm/tlb-sh4.c
+++ b/arch/sh/mm/tlb-sh4.c
@@ -79,7 +79,8 @@ void update_mmu_cache(struct vm_area_struct * vma,
79 local_irq_restore(flags); 79 local_irq_restore(flags);
80} 80}
81 81
82void local_flush_tlb_one(unsigned long asid, unsigned long page) 82void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid,
83 unsigned long page)
83{ 84{
84 unsigned long addr, data; 85 unsigned long addr, data;
85 86
@@ -91,7 +92,7 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
91 */ 92 */
92 addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; 93 addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
93 data = page | asid; /* VALID bit is off */ 94 data = page | asid; /* VALID bit is off */
94 jump_to_P2(); 95 jump_to_uncached();
95 ctrl_outl(data, addr); 96 ctrl_outl(data, addr);
96 back_to_P1(); 97 back_to_cached();
97} 98}
diff --git a/include/asm-sh/fixmap.h b/include/asm-sh/fixmap.h
index 09463cd9bbb9..721fcc4d5e98 100644
--- a/include/asm-sh/fixmap.h
+++ b/include/asm-sh/fixmap.h
@@ -49,6 +49,7 @@ enum fixed_addresses {
49#define FIX_N_COLOURS 16 49#define FIX_N_COLOURS 16
50 FIX_CMAP_BEGIN, 50 FIX_CMAP_BEGIN,
51 FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS, 51 FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS,
52 FIX_UNCACHED,
52#ifdef CONFIG_HIGHMEM 53#ifdef CONFIG_HIGHMEM
53 FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ 54 FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
54 FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, 55 FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
diff --git a/include/asm-sh/sections.h b/include/asm-sh/sections.h
index bd9cbc967c2a..8f8f4ad400df 100644
--- a/include/asm-sh/sections.h
+++ b/include/asm-sh/sections.h
@@ -4,6 +4,7 @@
4#include <asm-generic/sections.h> 4#include <asm-generic/sections.h>
5 5
6extern long __machvec_start, __machvec_end; 6extern long __machvec_start, __machvec_end;
7extern char __uncached_start, __uncached_end;
7extern char _ebss[]; 8extern char _ebss[];
8 9
9#endif /* __ASM_SH_SECTIONS_H */ 10#endif /* __ASM_SH_SECTIONS_H */
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 969f3d4afe2a..9bda8d063ecf 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -144,6 +144,8 @@ extern unsigned int instruction_size(unsigned int insn);
144#define instruction_size(insn) (4) 144#define instruction_size(insn) (4)
145#endif 145#endif
146 146
147extern unsigned long cached_to_uncached;
148
147/* XXX 149/* XXX
148 * disable hlt during certain critical i/o operations 150 * disable hlt during certain critical i/o operations
149 */ 151 */
diff --git a/include/asm-sh/system_32.h b/include/asm-sh/system_32.h
index ad37e8d5f31e..e918bacd5ecf 100644
--- a/include/asm-sh/system_32.h
+++ b/include/asm-sh/system_32.h
@@ -58,29 +58,31 @@ do { \
58 last = __last; \ 58 last = __last; \
59} while (0) 59} while (0)
60 60
61#define __uses_jump_to_uncached __attribute__ ((__section__ (".uncached.text")))
62
61/* 63/*
62 * Jump to P2 area. 64 * Jump to uncached area.
63 * When handling TLB or caches, we need to do it from P2 area. 65 * When handling TLB or caches, we need to do it from an uncached area.
64 */ 66 */
65#define jump_to_P2() \ 67#define jump_to_uncached() \
66do { \ 68do { \
67 unsigned long __dummy; \ 69 unsigned long __dummy; \
68 __asm__ __volatile__( \ 70 \
69 "mov.l 1f, %0\n\t" \ 71 __asm__ __volatile__( \
70 "or %1, %0\n\t" \ 72 "mova 1f, %0\n\t" \
71 "jmp @%0\n\t" \ 73 "add %1, %0\n\t" \
72 " nop\n\t" \ 74 "jmp @%0\n\t" \
73 ".balign 4\n" \ 75 " nop\n\t" \
74 "1: .long 2f\n" \ 76 ".balign 4\n" \
75 "2:" \ 77 "1:" \
76 : "=&r" (__dummy) \ 78 : "=&z" (__dummy) \
77 : "r" (0x20000000)); \ 79 : "r" (cached_to_uncached)); \
78} while (0) 80} while (0)
79 81
80/* 82/*
81 * Back to P1 area. 83 * Back to cached area.
82 */ 84 */
83#define back_to_P1() \ 85#define back_to_cached() \
84do { \ 86do { \
85 unsigned long __dummy; \ 87 unsigned long __dummy; \
86 ctrl_barrier(); \ 88 ctrl_barrier(); \
diff --git a/include/asm-sh/system_64.h b/include/asm-sh/system_64.h
index 0e466e991f7d..943acf5ea07c 100644
--- a/include/asm-sh/system_64.h
+++ b/include/asm-sh/system_64.h
@@ -32,8 +32,9 @@ do { \
32 &next->thread); \ 32 &next->thread); \
33} while (0) 33} while (0)
34 34
35/* No segmentation.. */ 35#define __uses_jump_to_uncached
36#define jump_to_P2() do { } while (0) 36
37#define back_to_P1() do { } while (0) 37#define jump_to_uncached() do { } while (0)
38#define back_to_cached() do { } while (0)
38 39
39#endif /* __ASM_SH_SYSTEM_64_H */ 40#endif /* __ASM_SH_SYSTEM_64_H */