sh: Migrate SH-4 cacheflush ops to function pointers.
[linux-2.6.git] / arch / sh / mm / cache-sh4.c
1 /*
2  * arch/sh/mm/cache-sh4.c
3  *
4  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
5  * Copyright (C) 2001 - 2007  Paul Mundt
6  * Copyright (C) 2003  Richard Curnow
7  * Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
8  *
9  * This file is subject to the terms and conditions of the GNU General Public
10  * License.  See the file "COPYING" in the main directory of this archive
11  * for more details.
12  */
13 #include <linux/init.h>
14 #include <linux/mm.h>
15 #include <linux/io.h>
16 #include <linux/mutex.h>
17 #include <linux/fs.h>
18 #include <asm/mmu_context.h>
19 #include <asm/cacheflush.h>
20
21 /*
22  * The maximum number of pages we support up to when doing ranged dcache
23  * flushing. Anything exceeding this will simply flush the dcache in its
24  * entirety.
25  */
26 #define MAX_DCACHE_PAGES        64      /* XXX: Tune for ways */
27 #define MAX_ICACHE_PAGES        32
28
29 static void __flush_cache_4096(unsigned long addr, unsigned long phys,
30                                unsigned long exec_offset);
31
32 /*
33  * This is initialised here to ensure that it is not placed in the BSS.  If
34  * that were to happen, note that cache_init gets called before the BSS is
35  * cleared, so this would get nulled out which would be hopeless.
36  */
37 static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
38         (void (*)(unsigned long, unsigned long))0xdeadbeef;
39
40 /*
41  * Write back the range of D-cache, and purge the I-cache.
42  *
43  * Called from kernel/module.c:sys_init_module and routine for a.out format,
44  * signal handler code and kprobes code
45  */
46 static void sh4_flush_icache_range(unsigned long start, unsigned long end)
47 {
48         int icacheaddr;
49         unsigned long flags, v;
50         int i;
51
52        /* If there are too many pages then just blow the caches */
53         if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
54                 flush_cache_all();
55        } else {
56                /* selectively flush d-cache then invalidate the i-cache */
57                /* this is inefficient, so only use for small ranges */
58                start &= ~(L1_CACHE_BYTES-1);
59                end += L1_CACHE_BYTES-1;
60                end &= ~(L1_CACHE_BYTES-1);
61
62                local_irq_save(flags);
63                jump_to_uncached();
64
65                for (v = start; v < end; v+=L1_CACHE_BYTES) {
66                        asm volatile("ocbwb     %0"
67                                     : /* no output */
68                                     : "m" (__m(v)));
69
70                        icacheaddr = CACHE_IC_ADDRESS_ARRAY | (
71                                        v & cpu_data->icache.entry_mask);
72
73                        for (i = 0; i < cpu_data->icache.ways;
74                                i++, icacheaddr += cpu_data->icache.way_incr)
75                                        /* Clear i-cache line valid-bit */
76                                        ctrl_outl(0, icacheaddr);
77                }
78
79                 back_to_cached();
80                 local_irq_restore(flags);
81         }
82 }
83
84 static inline void flush_cache_4096(unsigned long start,
85                                     unsigned long phys)
86 {
87         unsigned long flags, exec_offset = 0;
88
89         /*
90          * All types of SH-4 require PC to be in P2 to operate on the I-cache.
91          * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
92          */
93         if ((boot_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) ||
94             (start < CACHE_OC_ADDRESS_ARRAY))
95                 exec_offset = 0x20000000;
96
97         local_irq_save(flags);
98         __flush_cache_4096(start | SH_CACHE_ASSOC,
99                            P1SEGADDR(phys), exec_offset);
100         local_irq_restore(flags);
101 }
102
103 /*
104  * Write back & invalidate the D-cache of the page.
105  * (To avoid "alias" issues)
106  */
107 static void sh4_flush_dcache_page(struct page *page)
108 {
109         struct address_space *mapping = page_mapping(page);
110
111 #ifndef CONFIG_SMP
112         if (mapping && !mapping_mapped(mapping))
113                 set_bit(PG_dcache_dirty, &page->flags);
114         else
115 #endif
116         {
117                 unsigned long phys = PHYSADDR(page_address(page));
118                 unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
119                 int i, n;
120
121                 /* Loop all the D-cache */
122                 n = boot_cpu_data.dcache.n_aliases;
123                 for (i = 0; i < n; i++, addr += 4096)
124                         flush_cache_4096(addr, phys);
125         }
126
127         wmb();
128 }
129
130 /* TODO: Selective icache invalidation through IC address array.. */
131 static void __uses_jump_to_uncached flush_icache_all(void)
132 {
133         unsigned long flags, ccr;
134
135         local_irq_save(flags);
136         jump_to_uncached();
137
138         /* Flush I-cache */
139         ccr = ctrl_inl(CCR);
140         ccr |= CCR_CACHE_ICI;
141         ctrl_outl(ccr, CCR);
142
143         /*
144          * back_to_cached() will take care of the barrier for us, don't add
145          * another one!
146          */
147
148         back_to_cached();
149         local_irq_restore(flags);
150 }
151
152 static inline void flush_dcache_all(void)
153 {
154         (*__flush_dcache_segment_fn)(0UL, boot_cpu_data.dcache.way_size);
155         wmb();
156 }
157
158 static void sh4_flush_cache_all(void)
159 {
160         flush_dcache_all();
161         flush_icache_all();
162 }
163
164 static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
165                              unsigned long end)
166 {
167         unsigned long d = 0, p = start & PAGE_MASK;
168         unsigned long alias_mask = boot_cpu_data.dcache.alias_mask;
169         unsigned long n_aliases = boot_cpu_data.dcache.n_aliases;
170         unsigned long select_bit;
171         unsigned long all_aliases_mask;
172         unsigned long addr_offset;
173         pgd_t *dir;
174         pmd_t *pmd;
175         pud_t *pud;
176         pte_t *pte;
177         int i;
178
179         dir = pgd_offset(mm, p);
180         pud = pud_offset(dir, p);
181         pmd = pmd_offset(pud, p);
182         end = PAGE_ALIGN(end);
183
184         all_aliases_mask = (1 << n_aliases) - 1;
185
186         do {
187                 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
188                         p &= PMD_MASK;
189                         p += PMD_SIZE;
190                         pmd++;
191
192                         continue;
193                 }
194
195                 pte = pte_offset_kernel(pmd, p);
196
197                 do {
198                         unsigned long phys;
199                         pte_t entry = *pte;
200
201                         if (!(pte_val(entry) & _PAGE_PRESENT)) {
202                                 pte++;
203                                 p += PAGE_SIZE;
204                                 continue;
205                         }
206
207                         phys = pte_val(entry) & PTE_PHYS_MASK;
208
209                         if ((p ^ phys) & alias_mask) {
210                                 d |= 1 << ((p & alias_mask) >> PAGE_SHIFT);
211                                 d |= 1 << ((phys & alias_mask) >> PAGE_SHIFT);
212
213                                 if (d == all_aliases_mask)
214                                         goto loop_exit;
215                         }
216
217                         pte++;
218                         p += PAGE_SIZE;
219                 } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
220                 pmd++;
221         } while (p < end);
222
223 loop_exit:
224         addr_offset = 0;
225         select_bit = 1;
226
227         for (i = 0; i < n_aliases; i++) {
228                 if (d & select_bit) {
229                         (*__flush_dcache_segment_fn)(addr_offset, PAGE_SIZE);
230                         wmb();
231                 }
232
233                 select_bit <<= 1;
234                 addr_offset += PAGE_SIZE;
235         }
236 }
237
238 /*
239  * Note : (RPC) since the caches are physically tagged, the only point
240  * of flush_cache_mm for SH-4 is to get rid of aliases from the
241  * D-cache.  The assumption elsewhere, e.g. flush_cache_range, is that
242  * lines can stay resident so long as the virtual address they were
243  * accessed with (hence cache set) is in accord with the physical
244  * address (i.e. tag).  It's no different here.  So I reckon we don't
245  * need to flush the I-cache, since aliases don't matter for that.  We
246  * should try that.
247  *
248  * Caller takes mm->mmap_sem.
249  */
250 static void sh4_flush_cache_mm(struct mm_struct *mm)
251 {
252         if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT)
253                 return;
254
255         /*
256          * If cache is only 4k-per-way, there are never any 'aliases'.  Since
257          * the cache is physically tagged, the data can just be left in there.
258          */
259         if (boot_cpu_data.dcache.n_aliases == 0)
260                 return;
261
262         /*
263          * Don't bother groveling around the dcache for the VMA ranges
264          * if there are too many PTEs to make it worthwhile.
265          */
266         if (mm->nr_ptes >= MAX_DCACHE_PAGES)
267                 flush_dcache_all();
268         else {
269                 struct vm_area_struct *vma;
270
271                 /*
272                  * In this case there are reasonably sized ranges to flush,
273                  * iterate through the VMA list and take care of any aliases.
274                  */
275                 for (vma = mm->mmap; vma; vma = vma->vm_next)
276                         __flush_cache_mm(mm, vma->vm_start, vma->vm_end);
277         }
278
279         /* Only touch the icache if one of the VMAs has VM_EXEC set. */
280         if (mm->exec_vm)
281                 flush_icache_all();
282 }
283
284 /*
285  * Write back and invalidate I/D-caches for the page.
286  *
287  * ADDR: Virtual Address (U0 address)
288  * PFN: Physical page number
289  */
290 static void sh4_flush_cache_page(struct vm_area_struct *vma,
291                 unsigned long address, unsigned long pfn)
292 {
293         unsigned long phys = pfn << PAGE_SHIFT;
294         unsigned int alias_mask;
295
296         if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
297                 return;
298
299         alias_mask = boot_cpu_data.dcache.alias_mask;
300
301         /* We only need to flush D-cache when we have alias */
302         if ((address^phys) & alias_mask) {
303                 /* Loop 4K of the D-cache */
304                 flush_cache_4096(
305                         CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
306                         phys);
307                 /* Loop another 4K of the D-cache */
308                 flush_cache_4096(
309                         CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
310                         phys);
311         }
312
313         alias_mask = boot_cpu_data.icache.alias_mask;
314         if (vma->vm_flags & VM_EXEC) {
315                 /*
316                  * Evict entries from the portion of the cache from which code
317                  * may have been executed at this address (virtual).  There's
318                  * no need to evict from the portion corresponding to the
319                  * physical address as for the D-cache, because we know the
320                  * kernel has never executed the code through its identity
321                  * translation.
322                  */
323                 flush_cache_4096(
324                         CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
325                         phys);
326         }
327 }
328
329 /*
330  * Write back and invalidate D-caches.
331  *
332  * START, END: Virtual Address (U0 address)
333  *
334  * NOTE: We need to flush the _physical_ page entry.
335  * Flushing the cache lines for U0 only isn't enough.
336  * We need to flush for P1 too, which may contain aliases.
337  */
338 static void sh4_flush_cache_range(struct vm_area_struct *vma,
339                 unsigned long start, unsigned long end)
340 {
341         if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
342                 return;
343
344         /*
345          * If cache is only 4k-per-way, there are never any 'aliases'.  Since
346          * the cache is physically tagged, the data can just be left in there.
347          */
348         if (boot_cpu_data.dcache.n_aliases == 0)
349                 return;
350
351         /*
352          * Don't bother with the lookup and alias check if we have a
353          * wide range to cover, just blow away the dcache in its
354          * entirety instead. -- PFM.
355          */
356         if (((end - start) >> PAGE_SHIFT) >= MAX_DCACHE_PAGES)
357                 flush_dcache_all();
358         else
359                 __flush_cache_mm(vma->vm_mm, start, end);
360
361         if (vma->vm_flags & VM_EXEC) {
362                 /*
363                  * TODO: Is this required???  Need to look at how I-cache
364                  * coherency is assured when new programs are loaded to see if
365                  * this matters.
366                  */
367                 flush_icache_all();
368         }
369 }
370
371 /**
372  * __flush_cache_4096
373  *
374  * @addr:  address in memory mapped cache array
375  * @phys:  P1 address to flush (has to match tags if addr has 'A' bit
376  *         set i.e. associative write)
377  * @exec_offset: set to 0x20000000 if flush has to be executed from P2
378  *               region else 0x0
379  *
380  * The offset into the cache array implied by 'addr' selects the
381  * 'colour' of the virtual address range that will be flushed.  The
382  * operation (purge/write-back) is selected by the lower 2 bits of
383  * 'phys'.
384  */
385 static void __flush_cache_4096(unsigned long addr, unsigned long phys,
386                                unsigned long exec_offset)
387 {
388         int way_count;
389         unsigned long base_addr = addr;
390         struct cache_info *dcache;
391         unsigned long way_incr;
392         unsigned long a, ea, p;
393         unsigned long temp_pc;
394
395         dcache = &boot_cpu_data.dcache;
396         /* Write this way for better assembly. */
397         way_count = dcache->ways;
398         way_incr = dcache->way_incr;
399
400         /*
401          * Apply exec_offset (i.e. branch to P2 if required.).
402          *
403          * FIXME:
404          *
405          *      If I write "=r" for the (temp_pc), it puts this in r6 hence
406          *      trashing exec_offset before it's been added on - why?  Hence
407          *      "=&r" as a 'workaround'
408          */
409         asm volatile("mov.l 1f, %0\n\t"
410                      "add   %1, %0\n\t"
411                      "jmp   @%0\n\t"
412                      "nop\n\t"
413                      ".balign 4\n\t"
414                      "1:  .long 2f\n\t"
415                      "2:\n" : "=&r" (temp_pc) : "r" (exec_offset));
416
417         /*
418          * We know there will be >=1 iteration, so write as do-while to avoid
419          * pointless nead-of-loop check for 0 iterations.
420          */
421         do {
422                 ea = base_addr + PAGE_SIZE;
423                 a = base_addr;
424                 p = phys;
425
426                 do {
427                         *(volatile unsigned long *)a = p;
428                         /*
429                          * Next line: intentionally not p+32, saves an add, p
430                          * will do since only the cache tag bits need to
431                          * match.
432                          */
433                         *(volatile unsigned long *)(a+32) = p;
434                         a += 64;
435                         p += 64;
436                 } while (a < ea);
437
438                 base_addr += way_incr;
439         } while (--way_count != 0);
440 }
441
442 /*
443  * Break the 1, 2 and 4 way variants of this out into separate functions to
444  * avoid nearly all the overhead of having the conditional stuff in the function
445  * bodies (+ the 1 and 2 way cases avoid saving any registers too).
446  */
447 static void __flush_dcache_segment_1way(unsigned long start,
448                                         unsigned long extent_per_way)
449 {
450         unsigned long orig_sr, sr_with_bl;
451         unsigned long base_addr;
452         unsigned long way_incr, linesz, way_size;
453         struct cache_info *dcache;
454         register unsigned long a0, a0e;
455
456         asm volatile("stc sr, %0" : "=r" (orig_sr));
457         sr_with_bl = orig_sr | (1<<28);
458         base_addr = ((unsigned long)&empty_zero_page[0]);
459
460         /*
461          * The previous code aligned base_addr to 16k, i.e. the way_size of all
462          * existing SH-4 D-caches.  Whilst I don't see a need to have this
463          * aligned to any better than the cache line size (which it will be
464          * anyway by construction), let's align it to at least the way_size of
465          * any existing or conceivable SH-4 D-cache.  -- RPC
466          */
467         base_addr = ((base_addr >> 16) << 16);
468         base_addr |= start;
469
470         dcache = &boot_cpu_data.dcache;
471         linesz = dcache->linesz;
472         way_incr = dcache->way_incr;
473         way_size = dcache->way_size;
474
475         a0 = base_addr;
476         a0e = base_addr + extent_per_way;
477         do {
478                 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
479                 asm volatile("movca.l r0, @%0\n\t"
480                              "ocbi @%0" : : "r" (a0));
481                 a0 += linesz;
482                 asm volatile("movca.l r0, @%0\n\t"
483                              "ocbi @%0" : : "r" (a0));
484                 a0 += linesz;
485                 asm volatile("movca.l r0, @%0\n\t"
486                              "ocbi @%0" : : "r" (a0));
487                 a0 += linesz;
488                 asm volatile("movca.l r0, @%0\n\t"
489                              "ocbi @%0" : : "r" (a0));
490                 asm volatile("ldc %0, sr" : : "r" (orig_sr));
491                 a0 += linesz;
492         } while (a0 < a0e);
493 }
494
495 static void __flush_dcache_segment_2way(unsigned long start,
496                                         unsigned long extent_per_way)
497 {
498         unsigned long orig_sr, sr_with_bl;
499         unsigned long base_addr;
500         unsigned long way_incr, linesz, way_size;
501         struct cache_info *dcache;
502         register unsigned long a0, a1, a0e;
503
504         asm volatile("stc sr, %0" : "=r" (orig_sr));
505         sr_with_bl = orig_sr | (1<<28);
506         base_addr = ((unsigned long)&empty_zero_page[0]);
507
508         /* See comment under 1-way above */
509         base_addr = ((base_addr >> 16) << 16);
510         base_addr |= start;
511
512         dcache = &boot_cpu_data.dcache;
513         linesz = dcache->linesz;
514         way_incr = dcache->way_incr;
515         way_size = dcache->way_size;
516
517         a0 = base_addr;
518         a1 = a0 + way_incr;
519         a0e = base_addr + extent_per_way;
520         do {
521                 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
522                 asm volatile("movca.l r0, @%0\n\t"
523                              "movca.l r0, @%1\n\t"
524                              "ocbi @%0\n\t"
525                              "ocbi @%1" : :
526                              "r" (a0), "r" (a1));
527                 a0 += linesz;
528                 a1 += linesz;
529                 asm volatile("movca.l r0, @%0\n\t"
530                              "movca.l r0, @%1\n\t"
531                              "ocbi @%0\n\t"
532                              "ocbi @%1" : :
533                              "r" (a0), "r" (a1));
534                 a0 += linesz;
535                 a1 += linesz;
536                 asm volatile("movca.l r0, @%0\n\t"
537                              "movca.l r0, @%1\n\t"
538                              "ocbi @%0\n\t"
539                              "ocbi @%1" : :
540                              "r" (a0), "r" (a1));
541                 a0 += linesz;
542                 a1 += linesz;
543                 asm volatile("movca.l r0, @%0\n\t"
544                              "movca.l r0, @%1\n\t"
545                              "ocbi @%0\n\t"
546                              "ocbi @%1" : :
547                              "r" (a0), "r" (a1));
548                 asm volatile("ldc %0, sr" : : "r" (orig_sr));
549                 a0 += linesz;
550                 a1 += linesz;
551         } while (a0 < a0e);
552 }
553
554 static void __flush_dcache_segment_4way(unsigned long start,
555                                         unsigned long extent_per_way)
556 {
557         unsigned long orig_sr, sr_with_bl;
558         unsigned long base_addr;
559         unsigned long way_incr, linesz, way_size;
560         struct cache_info *dcache;
561         register unsigned long a0, a1, a2, a3, a0e;
562
563         asm volatile("stc sr, %0" : "=r" (orig_sr));
564         sr_with_bl = orig_sr | (1<<28);
565         base_addr = ((unsigned long)&empty_zero_page[0]);
566
567         /* See comment under 1-way above */
568         base_addr = ((base_addr >> 16) << 16);
569         base_addr |= start;
570
571         dcache = &boot_cpu_data.dcache;
572         linesz = dcache->linesz;
573         way_incr = dcache->way_incr;
574         way_size = dcache->way_size;
575
576         a0 = base_addr;
577         a1 = a0 + way_incr;
578         a2 = a1 + way_incr;
579         a3 = a2 + way_incr;
580         a0e = base_addr + extent_per_way;
581         do {
582                 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
583                 asm volatile("movca.l r0, @%0\n\t"
584                              "movca.l r0, @%1\n\t"
585                              "movca.l r0, @%2\n\t"
586                              "movca.l r0, @%3\n\t"
587                              "ocbi @%0\n\t"
588                              "ocbi @%1\n\t"
589                              "ocbi @%2\n\t"
590                              "ocbi @%3\n\t" : :
591                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
592                 a0 += linesz;
593                 a1 += linesz;
594                 a2 += linesz;
595                 a3 += linesz;
596                 asm volatile("movca.l r0, @%0\n\t"
597                              "movca.l r0, @%1\n\t"
598                              "movca.l r0, @%2\n\t"
599                              "movca.l r0, @%3\n\t"
600                              "ocbi @%0\n\t"
601                              "ocbi @%1\n\t"
602                              "ocbi @%2\n\t"
603                              "ocbi @%3\n\t" : :
604                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
605                 a0 += linesz;
606                 a1 += linesz;
607                 a2 += linesz;
608                 a3 += linesz;
609                 asm volatile("movca.l r0, @%0\n\t"
610                              "movca.l r0, @%1\n\t"
611                              "movca.l r0, @%2\n\t"
612                              "movca.l r0, @%3\n\t"
613                              "ocbi @%0\n\t"
614                              "ocbi @%1\n\t"
615                              "ocbi @%2\n\t"
616                              "ocbi @%3\n\t" : :
617                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
618                 a0 += linesz;
619                 a1 += linesz;
620                 a2 += linesz;
621                 a3 += linesz;
622                 asm volatile("movca.l r0, @%0\n\t"
623                              "movca.l r0, @%1\n\t"
624                              "movca.l r0, @%2\n\t"
625                              "movca.l r0, @%3\n\t"
626                              "ocbi @%0\n\t"
627                              "ocbi @%1\n\t"
628                              "ocbi @%2\n\t"
629                              "ocbi @%3\n\t" : :
630                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
631                 asm volatile("ldc %0, sr" : : "r" (orig_sr));
632                 a0 += linesz;
633                 a1 += linesz;
634                 a2 += linesz;
635                 a3 += linesz;
636         } while (a0 < a0e);
637 }
638
639 extern void __weak sh4__flush_region_init(void);
640
641 /*
642  * SH-4 has virtually indexed and physically tagged cache.
643  */
644 void __init sh4_cache_init(void)
645 {
646         printk("PVR=%08x CVR=%08x PRR=%08x\n",
647                 ctrl_inl(CCN_PVR),
648                 ctrl_inl(CCN_CVR),
649                 ctrl_inl(CCN_PRR));
650
651         switch (boot_cpu_data.dcache.ways) {
652         case 1:
653                 __flush_dcache_segment_fn = __flush_dcache_segment_1way;
654                 break;
655         case 2:
656                 __flush_dcache_segment_fn = __flush_dcache_segment_2way;
657                 break;
658         case 4:
659                 __flush_dcache_segment_fn = __flush_dcache_segment_4way;
660                 break;
661         default:
662                 panic("unknown number of cache ways\n");
663                 break;
664         }
665
666         flush_icache_range      = sh4_flush_icache_range;
667         flush_dcache_page       = sh4_flush_dcache_page;
668         flush_cache_all         = sh4_flush_cache_all;
669         flush_cache_mm          = sh4_flush_cache_mm;
670         flush_cache_dup_mm      = sh4_flush_cache_mm;
671         flush_cache_page        = sh4_flush_cache_page;
672         flush_cache_range       = sh4_flush_cache_range;
673
674         sh4__flush_region_init();
675 }