aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/cache-sh4.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm/cache-sh4.c')
-rw-r--r--arch/sh/mm/cache-sh4.c124
1 files changed, 4 insertions, 120 deletions
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index b2453bbef4cd..a5c339bca8aa 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -170,89 +170,13 @@ static void sh4_flush_cache_all(void *unused)
170 flush_icache_all(); 170 flush_icache_all();
171} 171}
172 172
173static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
174 unsigned long end)
175{
176 unsigned long d = 0, p = start & PAGE_MASK;
177 unsigned long alias_mask = boot_cpu_data.dcache.alias_mask;
178 unsigned long n_aliases = boot_cpu_data.dcache.n_aliases;
179 unsigned long select_bit;
180 unsigned long all_aliases_mask;
181 unsigned long addr_offset;
182 pgd_t *dir;
183 pmd_t *pmd;
184 pud_t *pud;
185 pte_t *pte;
186 int i;
187
188 dir = pgd_offset(mm, p);
189 pud = pud_offset(dir, p);
190 pmd = pmd_offset(pud, p);
191 end = PAGE_ALIGN(end);
192
193 all_aliases_mask = (1 << n_aliases) - 1;
194
195 do {
196 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
197 p &= PMD_MASK;
198 p += PMD_SIZE;
199 pmd++;
200
201 continue;
202 }
203
204 pte = pte_offset_kernel(pmd, p);
205
206 do {
207 unsigned long phys;
208 pte_t entry = *pte;
209
210 if (!(pte_val(entry) & _PAGE_PRESENT)) {
211 pte++;
212 p += PAGE_SIZE;
213 continue;
214 }
215
216 phys = pte_val(entry) & PTE_PHYS_MASK;
217
218 if ((p ^ phys) & alias_mask) {
219 d |= 1 << ((p & alias_mask) >> PAGE_SHIFT);
220 d |= 1 << ((phys & alias_mask) >> PAGE_SHIFT);
221
222 if (d == all_aliases_mask)
223 goto loop_exit;
224 }
225
226 pte++;
227 p += PAGE_SIZE;
228 } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
229 pmd++;
230 } while (p < end);
231
232loop_exit:
233 addr_offset = 0;
234 select_bit = 1;
235
236 for (i = 0; i < n_aliases; i++) {
237 if (d & select_bit) {
238 (*__flush_dcache_segment_fn)(addr_offset, PAGE_SIZE);
239 wmb();
240 }
241
242 select_bit <<= 1;
243 addr_offset += PAGE_SIZE;
244 }
245}
246
247/* 173/*
248 * Note : (RPC) since the caches are physically tagged, the only point 174 * Note : (RPC) since the caches are physically tagged, the only point
249 * of flush_cache_mm for SH-4 is to get rid of aliases from the 175 * of flush_cache_mm for SH-4 is to get rid of aliases from the
250 * D-cache. The assumption elsewhere, e.g. flush_cache_range, is that 176 * D-cache. The assumption elsewhere, e.g. flush_cache_range, is that
251 * lines can stay resident so long as the virtual address they were 177 * lines can stay resident so long as the virtual address they were
252 * accessed with (hence cache set) is in accord with the physical 178 * accessed with (hence cache set) is in accord with the physical
253 * address (i.e. tag). It's no different here. So I reckon we don't 179 * address (i.e. tag). It's no different here.
254 * need to flush the I-cache, since aliases don't matter for that. We
255 * should try that.
256 * 180 *
257 * Caller takes mm->mmap_sem. 181 * Caller takes mm->mmap_sem.
258 */ 182 */
@@ -263,33 +187,7 @@ static void sh4_flush_cache_mm(void *arg)
263 if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT) 187 if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT)
264 return; 188 return;
265 189
266 /* 190 flush_dcache_all();
267 * If cache is only 4k-per-way, there are never any 'aliases'. Since
268 * the cache is physically tagged, the data can just be left in there.
269 */
270 if (boot_cpu_data.dcache.n_aliases == 0)
271 return;
272
273 /*
274 * Don't bother groveling around the dcache for the VMA ranges
275 * if there are too many PTEs to make it worthwhile.
276 */
277 if (mm->nr_ptes >= MAX_DCACHE_PAGES)
278 flush_dcache_all();
279 else {
280 struct vm_area_struct *vma;
281
282 /*
283 * In this case there are reasonably sized ranges to flush,
284 * iterate through the VMA list and take care of any aliases.
285 */
286 for (vma = mm->mmap; vma; vma = vma->vm_next)
287 __flush_cache_mm(mm, vma->vm_start, vma->vm_end);
288 }
289
290 /* Only touch the icache if one of the VMAs has VM_EXEC set. */
291 if (mm->exec_vm)
292 flush_icache_all();
293} 191}
294 192
295/* 193/*
@@ -372,24 +270,10 @@ static void sh4_flush_cache_range(void *args)
372 if (boot_cpu_data.dcache.n_aliases == 0) 270 if (boot_cpu_data.dcache.n_aliases == 0)
373 return; 271 return;
374 272
375 /* 273 flush_dcache_all();
376 * Don't bother with the lookup and alias check if we have a
377 * wide range to cover, just blow away the dcache in its
378 * entirety instead. -- PFM.
379 */
380 if (((end - start) >> PAGE_SHIFT) >= MAX_DCACHE_PAGES)
381 flush_dcache_all();
382 else
383 __flush_cache_mm(vma->vm_mm, start, end);
384 274
385 if (vma->vm_flags & VM_EXEC) { 275 if (vma->vm_flags & VM_EXEC)
386 /*
387 * TODO: Is this required??? Need to look at how I-cache
388 * coherency is assured when new programs are loaded to see if
389 * this matters.
390 */
391 flush_icache_all(); 276 flush_icache_all();
392 }
393} 277}
394 278
395/** 279/**