aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/mm/cache-sh2a.c6
-rw-r--r--arch/sh/mm/cache-sh4.c61
-rw-r--r--arch/sh/mm/cache-sh5.c29
-rw-r--r--arch/sh/mm/cache-sh7705.c8
4 files changed, 33 insertions, 71 deletions
diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c
index 975899d83564..d783361e3f0a 100644
--- a/arch/sh/mm/cache-sh2a.c
+++ b/arch/sh/mm/cache-sh2a.c
@@ -102,12 +102,10 @@ static void sh2a_flush_icache_range(void *args)
102 struct flusher_data *data = args; 102 struct flusher_data *data = args;
103 unsigned long start, end; 103 unsigned long start, end;
104 unsigned long v; 104 unsigned long v;
105 unsigned long flags;
106 105
107 start = data->addr1 & ~(L1_CACHE_BYTES-1); 106 start = data->addr1 & ~(L1_CACHE_BYTES-1);
108 end = (data->addr2 + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1); 107 end = (data->addr2 + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
109 108
110 local_irq_save(flags);
111 jump_to_uncached(); 109 jump_to_uncached();
112 110
113 for (v = start; v < end; v+=L1_CACHE_BYTES) { 111 for (v = start; v < end; v+=L1_CACHE_BYTES) {
@@ -122,12 +120,10 @@ static void sh2a_flush_icache_range(void *args)
122 } 120 }
123 } 121 }
124 /* I-Cache invalidate */ 122 /* I-Cache invalidate */
125 ctrl_outl(addr, 123 ctrl_outl(addr, CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
126 CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
127 } 124 }
128 125
129 back_to_cached(); 126 back_to_cached();
130 local_irq_restore(flags);
131} 127}
132 128
133void __init sh2a_cache_init(void) 129void __init sh2a_cache_init(void)
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 9201b37c7cca..e3b77f0fa470 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -48,48 +48,44 @@ static void sh4_flush_icache_range(void *args)
48 struct flusher_data *data = args; 48 struct flusher_data *data = args;
49 int icacheaddr; 49 int icacheaddr;
50 unsigned long start, end; 50 unsigned long start, end;
51 unsigned long flags, v; 51 unsigned long v;
52 int i; 52 int i;
53 53
54 start = data->addr1; 54 start = data->addr1;
55 end = data->addr2; 55 end = data->addr2;
56 56
57 /* If there are too many pages then just blow the caches */ 57 /* If there are too many pages then just blow the caches */
58 if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) { 58 if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
59 local_flush_cache_all(args); 59 local_flush_cache_all(args);
60 } else { 60 } else {
61 /* selectively flush d-cache then invalidate the i-cache */ 61 /* selectively flush d-cache then invalidate the i-cache */
62 /* this is inefficient, so only use for small ranges */ 62 /* this is inefficient, so only use for small ranges */
63 start &= ~(L1_CACHE_BYTES-1); 63 start &= ~(L1_CACHE_BYTES-1);
64 end += L1_CACHE_BYTES-1; 64 end += L1_CACHE_BYTES-1;
65 end &= ~(L1_CACHE_BYTES-1); 65 end &= ~(L1_CACHE_BYTES-1);
66 66
67 local_irq_save(flags); 67 jump_to_uncached();
68 jump_to_uncached(); 68
69 69 for (v = start; v < end; v+=L1_CACHE_BYTES) {
70 for (v = start; v < end; v+=L1_CACHE_BYTES) { 70 __ocbwb(v);
71 asm volatile("ocbwb %0" 71
72 : /* no output */ 72 icacheaddr = CACHE_IC_ADDRESS_ARRAY |
73 : "m" (__m(v))); 73 (v & cpu_data->icache.entry_mask);
74 74
75 icacheaddr = CACHE_IC_ADDRESS_ARRAY | ( 75 for (i = 0; i < cpu_data->icache.ways;
76 v & cpu_data->icache.entry_mask); 76 i++, icacheaddr += cpu_data->icache.way_incr)
77 77 /* Clear i-cache line valid-bit */
78 for (i = 0; i < cpu_data->icache.ways; 78 ctrl_outl(0, icacheaddr);
79 i++, icacheaddr += cpu_data->icache.way_incr) 79 }
80 /* Clear i-cache line valid-bit */
81 ctrl_outl(0, icacheaddr);
82 }
83 80
84 back_to_cached(); 81 back_to_cached();
85 local_irq_restore(flags);
86 } 82 }
87} 83}
88 84
89static inline void flush_cache_4096(unsigned long start, 85static inline void flush_cache_4096(unsigned long start,
90 unsigned long phys) 86 unsigned long phys)
91{ 87{
92 unsigned long flags, exec_offset = 0; 88 unsigned long exec_offset = 0;
93 89
94 /* 90 /*
95 * All types of SH-4 require PC to be in P2 to operate on the I-cache. 91 * All types of SH-4 require PC to be in P2 to operate on the I-cache.
@@ -99,10 +95,8 @@ static inline void flush_cache_4096(unsigned long start,
99 (start < CACHE_OC_ADDRESS_ARRAY)) 95 (start < CACHE_OC_ADDRESS_ARRAY))
100 exec_offset = 0x20000000; 96 exec_offset = 0x20000000;
101 97
102 local_irq_save(flags);
103 __flush_cache_4096(start | SH_CACHE_ASSOC, 98 __flush_cache_4096(start | SH_CACHE_ASSOC,
104 P1SEGADDR(phys), exec_offset); 99 P1SEGADDR(phys), exec_offset);
105 local_irq_restore(flags);
106} 100}
107 101
108/* 102/*
@@ -135,9 +129,8 @@ static void sh4_flush_dcache_page(void *page)
135/* TODO: Selective icache invalidation through IC address array.. */ 129/* TODO: Selective icache invalidation through IC address array.. */
136static void __uses_jump_to_uncached flush_icache_all(void) 130static void __uses_jump_to_uncached flush_icache_all(void)
137{ 131{
138 unsigned long flags, ccr; 132 unsigned long ccr;
139 133
140 local_irq_save(flags);
141 jump_to_uncached(); 134 jump_to_uncached();
142 135
143 /* Flush I-cache */ 136 /* Flush I-cache */
@@ -149,9 +142,7 @@ static void __uses_jump_to_uncached flush_icache_all(void)
149 * back_to_cached() will take care of the barrier for us, don't add 142 * back_to_cached() will take care of the barrier for us, don't add
150 * another one! 143 * another one!
151 */ 144 */
152
153 back_to_cached(); 145 back_to_cached();
154 local_irq_restore(flags);
155} 146}
156 147
157static inline void flush_dcache_all(void) 148static inline void flush_dcache_all(void)
diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c
index 467ff8e260f7..2f9dd6df00a6 100644
--- a/arch/sh/mm/cache-sh5.c
+++ b/arch/sh/mm/cache-sh5.c
@@ -34,28 +34,22 @@ static inline void
34sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid, 34sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid,
35 unsigned long paddr) 35 unsigned long paddr)
36{ 36{
37 local_irq_disable();
38 sh64_setup_tlb_slot(dtlb_cache_slot, eaddr, asid, paddr); 37 sh64_setup_tlb_slot(dtlb_cache_slot, eaddr, asid, paddr);
39} 38}
40 39
41static inline void sh64_teardown_dtlb_cache_slot(void) 40static inline void sh64_teardown_dtlb_cache_slot(void)
42{ 41{
43 sh64_teardown_tlb_slot(dtlb_cache_slot); 42 sh64_teardown_tlb_slot(dtlb_cache_slot);
44 local_irq_enable();
45} 43}
46 44
47static inline void sh64_icache_inv_all(void) 45static inline void sh64_icache_inv_all(void)
48{ 46{
49 unsigned long long addr, flag, data; 47 unsigned long long addr, flag, data;
50 unsigned long flags;
51 48
52 addr = ICCR0; 49 addr = ICCR0;
53 flag = ICCR0_ICI; 50 flag = ICCR0_ICI;
54 data = 0; 51 data = 0;
55 52
56 /* Make this a critical section for safety (probably not strictly necessary.) */
57 local_irq_save(flags);
58
59 /* Without %1 it gets unexplicably wrong */ 53 /* Without %1 it gets unexplicably wrong */
60 __asm__ __volatile__ ( 54 __asm__ __volatile__ (
61 "getcfg %3, 0, %0\n\t" 55 "getcfg %3, 0, %0\n\t"
@@ -64,8 +58,6 @@ static inline void sh64_icache_inv_all(void)
64 "synci" 58 "synci"
65 : "=&r" (data) 59 : "=&r" (data)
66 : "0" (data), "r" (flag), "r" (addr)); 60 : "0" (data), "r" (flag), "r" (addr));
67
68 local_irq_restore(flags);
69} 61}
70 62
71static void sh64_icache_inv_kernel_range(unsigned long start, unsigned long end) 63static void sh64_icache_inv_kernel_range(unsigned long start, unsigned long end)
@@ -90,7 +82,6 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long
90 Also, eaddr is page-aligned. */ 82 Also, eaddr is page-aligned. */
91 unsigned int cpu = smp_processor_id(); 83 unsigned int cpu = smp_processor_id();
92 unsigned long long addr, end_addr; 84 unsigned long long addr, end_addr;
93 unsigned long flags = 0;
94 unsigned long running_asid, vma_asid; 85 unsigned long running_asid, vma_asid;
95 addr = eaddr; 86 addr = eaddr;
96 end_addr = addr + PAGE_SIZE; 87 end_addr = addr + PAGE_SIZE;
@@ -111,10 +102,9 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long
111 102
112 running_asid = get_asid(); 103 running_asid = get_asid();
113 vma_asid = cpu_asid(cpu, vma->vm_mm); 104 vma_asid = cpu_asid(cpu, vma->vm_mm);
114 if (running_asid != vma_asid) { 105 if (running_asid != vma_asid)
115 local_irq_save(flags);
116 switch_and_save_asid(vma_asid); 106 switch_and_save_asid(vma_asid);
117 } 107
118 while (addr < end_addr) { 108 while (addr < end_addr) {
119 /* Worth unrolling a little */ 109 /* Worth unrolling a little */
120 __asm__ __volatile__("icbi %0, 0" : : "r" (addr)); 110 __asm__ __volatile__("icbi %0, 0" : : "r" (addr));
@@ -123,10 +113,9 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long
123 __asm__ __volatile__("icbi %0, 96" : : "r" (addr)); 113 __asm__ __volatile__("icbi %0, 96" : : "r" (addr));
124 addr += 128; 114 addr += 128;
125 } 115 }
126 if (running_asid != vma_asid) { 116
117 if (running_asid != vma_asid)
127 switch_and_save_asid(running_asid); 118 switch_and_save_asid(running_asid);
128 local_irq_restore(flags);
129 }
130} 119}
131 120
132static void sh64_icache_inv_user_page_range(struct mm_struct *mm, 121static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
@@ -159,16 +148,12 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
159 unsigned long eaddr; 148 unsigned long eaddr;
160 unsigned long after_last_page_start; 149 unsigned long after_last_page_start;
161 unsigned long mm_asid, current_asid; 150 unsigned long mm_asid, current_asid;
162 unsigned long flags = 0;
163 151
164 mm_asid = cpu_asid(smp_processor_id(), mm); 152 mm_asid = cpu_asid(smp_processor_id(), mm);
165 current_asid = get_asid(); 153 current_asid = get_asid();
166 154
167 if (mm_asid != current_asid) { 155 if (mm_asid != current_asid)
168 /* Switch ASID and run the invalidate loop under cli */
169 local_irq_save(flags);
170 switch_and_save_asid(mm_asid); 156 switch_and_save_asid(mm_asid);
171 }
172 157
173 aligned_start = start & PAGE_MASK; 158 aligned_start = start & PAGE_MASK;
174 after_last_page_start = PAGE_SIZE + ((end - 1) & PAGE_MASK); 159 after_last_page_start = PAGE_SIZE + ((end - 1) & PAGE_MASK);
@@ -194,10 +179,8 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
194 aligned_start = vma->vm_end; /* Skip to start of next region */ 179 aligned_start = vma->vm_end; /* Skip to start of next region */
195 } 180 }
196 181
197 if (mm_asid != current_asid) { 182 if (mm_asid != current_asid)
198 switch_and_save_asid(current_asid); 183 switch_and_save_asid(current_asid);
199 local_irq_restore(flags);
200 }
201 } 184 }
202} 185}
203 186
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index 6293f57fa888..9dc38660e3de 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -81,7 +81,6 @@ static void sh7705_flush_icache_range(void *args)
81static void __flush_dcache_page(unsigned long phys) 81static void __flush_dcache_page(unsigned long phys)
82{ 82{
83 unsigned long ways, waysize, addrstart; 83 unsigned long ways, waysize, addrstart;
84 unsigned long flags;
85 84
86 phys |= SH_CACHE_VALID; 85 phys |= SH_CACHE_VALID;
87 86
@@ -98,7 +97,6 @@ static void __flush_dcache_page(unsigned long phys)
98 * potential cache aliasing, therefore the optimisation is probably not 97 * potential cache aliasing, therefore the optimisation is probably not
99 * possible. 98 * possible.
100 */ 99 */
101 local_irq_save(flags);
102 jump_to_uncached(); 100 jump_to_uncached();
103 101
104 ways = current_cpu_data.dcache.ways; 102 ways = current_cpu_data.dcache.ways;
@@ -126,7 +124,6 @@ static void __flush_dcache_page(unsigned long phys)
126 } while (--ways); 124 } while (--ways);
127 125
128 back_to_cached(); 126 back_to_cached();
129 local_irq_restore(flags);
130} 127}
131 128
132/* 129/*
@@ -145,14 +142,9 @@ static void sh7705_flush_dcache_page(void *page)
145 142
146static void sh7705_flush_cache_all(void *args) 143static void sh7705_flush_cache_all(void *args)
147{ 144{
148 unsigned long flags;
149
150 local_irq_save(flags);
151 jump_to_uncached(); 145 jump_to_uncached();
152
153 cache_wback_all(); 146 cache_wback_all();
154 back_to_cached(); 147 back_to_cached();
155 local_irq_restore(flags);
156} 148}
157 149
158/* 150/*