Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: Migrate SH-4 cacheflush ops to function pointers.

This paves the way for allowing individual CPUs to overload the
individual flushing routines that they care about without having to
depend on weak aliases. SH-4 is converted over initially, as it wires
up pretty much everything. The majority of the other CPUs will simply use
the default no-op implementation with their own region flushers wired up.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

+159 -135
+1 -36
arch/sh/include/asm/cacheflush.h
··· 1 1 #ifndef __ASM_SH_CACHEFLUSH_H 2 2 #define __ASM_SH_CACHEFLUSH_H 3 3 4 - #include <linux/mm.h> 5 - 6 4 #ifdef __KERNEL__ 7 5 8 - #ifdef CONFIG_CACHE_OFF 9 - /* 10 - * Nothing to do when the cache is disabled, initial flush and explicit 11 - * disabling is handled at CPU init time. 12 - * 13 - * See arch/sh/kernel/cpu/init.c:cache_init(). 14 - */ 15 - #define flush_cache_all() do { } while (0) 16 - #define flush_cache_mm(mm) do { } while (0) 17 - #define flush_cache_dup_mm(mm) do { } while (0) 18 - #define flush_cache_range(vma, start, end) do { } while (0) 19 - #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) 20 - #define flush_dcache_page(page) do { } while (0) 21 - #define flush_icache_range(start, end) do { } while (0) 22 - #define flush_icache_page(vma,pg) do { } while (0) 23 - #define flush_cache_sigtramp(vaddr) do { } while (0) 24 - #define __flush_wback_region(start, size) do { (void)(start); } while (0) 25 - #define __flush_purge_region(start, size) do { (void)(start); } while (0) 26 - #define __flush_invalidate_region(start, size) do { (void)(start); } while (0) 27 - #else 6 + #include <linux/mm.h> 28 7 #include <cpu/cacheflush.h> 29 - 30 - /* 31 - * Consistent DMA requires that the __flush_xxx() primitives must be set 32 - * for any of the enabled non-coherent caches (most of the UP CPUs), 33 - * regardless of PIPT or VIPT cache configurations. 34 - */ 35 - 36 - /* Flush (write-back only) a region (smaller than a page) */ 37 - extern void __flush_wback_region(void *start, int size); 38 - /* Flush (write-back & invalidate) a region (smaller than a page) */ 39 - extern void __flush_purge_region(void *start, int size); 40 - /* Flush (invalidate only) a region (smaller than a page) */ 41 - extern void __flush_invalidate_region(void *start, int size); 42 - #endif 43 8 44 9 #define ARCH_HAS_FLUSH_ANON_PAGE 45 10 extern void __flush_anon_page(struct page *page, unsigned long);
+20 -17
arch/sh/include/cpu-common/cpu/cacheflush.h
··· 1 1 /* 2 - * include/asm-sh/cpu-sh2/cacheflush.h 3 - * 4 2 * Copyright (C) 2003 Paul Mundt 5 3 * 6 4 * This file is subject to the terms and conditions of the GNU General Public 7 5 * License. See the file "COPYING" in the main directory of this archive 8 6 * for more details. 9 7 */ 10 - #ifndef __ASM_CPU_SH2_CACHEFLUSH_H 11 - #define __ASM_CPU_SH2_CACHEFLUSH_H 8 + #ifndef __ASM_CPU_SH_CACHEFLUSH_H 9 + #define __ASM_CPU_SH_CACHEFLUSH_H 12 10 13 11 /* 14 12 * Cache flushing: ··· 20 22 * - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache 21 23 * - flush_icache_range(start, end) flushes(invalidates) a range for icache 22 24 * - flush_icache_page(vma, pg) flushes(invalidates) a page for icache 23 - * 24 - * Caches are indexed (effectively) by physical address on SH-2, so 25 - * we don't need them. 25 + * - flush_cache_sigtramp(vaddr) flushes the signal trampoline 26 26 */ 27 - #define flush_cache_all() do { } while (0) 28 - #define flush_cache_mm(mm) do { } while (0) 29 - #define flush_cache_dup_mm(mm) do { } while (0) 30 - #define flush_cache_range(vma, start, end) do { } while (0) 31 - #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) 32 - #define flush_dcache_page(page) do { } while (0) 33 - #define flush_icache_range(start, end) do { } while (0) 34 - #define flush_icache_page(vma,pg) do { } while (0) 35 - #define flush_cache_sigtramp(vaddr) do { } while (0) 27 + extern void (*flush_cache_all)(void); 28 + extern void (*flush_cache_mm)(struct mm_struct *mm); 29 + extern void (*flush_cache_dup_mm)(struct mm_struct *mm); 30 + extern void (*flush_cache_page)(struct vm_area_struct *vma, 31 + unsigned long addr, unsigned long pfn); 32 + extern void (*flush_cache_range)(struct vm_area_struct *vma, 33 + unsigned long start, unsigned long end); 34 + extern void (*flush_dcache_page)(struct page *page); 35 + extern void (*flush_icache_range)(unsigned long start, unsigned long end); 36 + extern void (*flush_icache_page)(struct vm_area_struct *vma, 37 + struct page *page); 38 + extern void (*flush_cache_sigtramp)(unsigned long address); 36 39 37 - #endif /* __ASM_CPU_SH2_CACHEFLUSH_H */ 40 + extern void (*__flush_wback_region)(void *start, int size); 41 + extern void (*__flush_purge_region)(void *start, int size); 42 + extern void (*__flush_invalidate_region)(void *start, int size); 43 + 44 + #endif /* __ASM_CPU_SH_CACHEFLUSH_H */
-31
arch/sh/include/cpu-sh4/cpu/cacheflush.h
··· 1 - /* 2 - * include/asm-sh/cpu-sh4/cacheflush.h 3 - * 4 - * Copyright (C) 1999 Niibe Yutaka 5 - * Copyright (C) 2003 Paul Mundt 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 - #ifndef __ASM_CPU_SH4_CACHEFLUSH_H 12 - #define __ASM_CPU_SH4_CACHEFLUSH_H 13 - 14 - /* 15 - * Caches are broken on SH-4 (unless we use write-through 16 - * caching; in which case they're only semi-broken), 17 - * so we need them. 18 - */ 19 - void flush_cache_all(void); 20 - void flush_cache_mm(struct mm_struct *mm); 21 - #define flush_cache_dup_mm(mm) flush_cache_mm(mm) 22 - void flush_cache_range(struct vm_area_struct *vma, unsigned long start, 23 - unsigned long end); 24 - void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, 25 - unsigned long pfn); 26 - void flush_dcache_page(struct page *pg); 27 - void flush_icache_range(unsigned long start, unsigned long end); 28 - 29 - #define flush_icache_page(vma,pg) do { } while (0) 30 - 31 - #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
+5 -5
arch/sh/include/cpu-sh5/cpu/cacheflush.h
··· 3 3 4 4 #ifndef __ASSEMBLY__ 5 5 6 - struct vm_area_struct; 7 - struct page; 8 - struct mm_struct; 9 - 10 6 extern void flush_cache_all(void); 11 7 extern void flush_cache_mm(struct mm_struct *mm); 12 8 extern void flush_cache_sigtramp(unsigned long vaddr); ··· 12 16 extern void flush_dcache_page(struct page *pg); 13 17 extern void flush_icache_range(unsigned long start, unsigned long end); 14 18 19 + /* XXX .. */ 20 + extern void (*__flush_wback_region)(void *start, int size); 21 + extern void (*__flush_purge_region)(void *start, int size); 22 + extern void (*__flush_invalidate_region)(void *start, int size); 23 + 15 24 #define flush_cache_dup_mm(mm) flush_cache_mm(mm) 16 25 #define flush_icache_page(vma, page) do { } while (0) 17 26 18 27 #endif /* __ASSEMBLY__ */ 19 28 20 29 #endif /* __ASM_SH_CPU_SH5_CACHEFLUSH_H */ 21 -
+46 -41
arch/sh/mm/cache-sh4.c
··· 26 26 #define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */ 27 27 #define MAX_ICACHE_PAGES 32 28 28 29 - static void __flush_dcache_segment_1way(unsigned long start, 30 - unsigned long extent); 31 - static void __flush_dcache_segment_2way(unsigned long start, 32 - unsigned long extent); 33 - static void __flush_dcache_segment_4way(unsigned long start, 34 - unsigned long extent); 35 - 36 29 static void __flush_cache_4096(unsigned long addr, unsigned long phys, 37 30 unsigned long exec_offset); 38 31 ··· 38 45 (void (*)(unsigned long, unsigned long))0xdeadbeef; 39 46 40 47 /* 41 - * SH-4 has virtually indexed and physically tagged cache. 42 - */ 43 - void __init sh4_cache_init(void) 44 - { 45 - printk("PVR=%08x CVR=%08x PRR=%08x\n", 46 - ctrl_inl(CCN_PVR), 47 - ctrl_inl(CCN_CVR), 48 - ctrl_inl(CCN_PRR)); 49 - 50 - switch (boot_cpu_data.dcache.ways) { 51 - case 1: 52 - __flush_dcache_segment_fn = __flush_dcache_segment_1way; 53 - break; 54 - case 2: 55 - __flush_dcache_segment_fn = __flush_dcache_segment_2way; 56 - break; 57 - case 4: 58 - __flush_dcache_segment_fn = __flush_dcache_segment_4way; 59 - break; 60 - default: 61 - panic("unknown number of cache ways\n"); 62 - break; 63 - } 64 - } 65 - 66 - /* 67 48 * Write back the range of D-cache, and purge the I-cache. 68 49 * 69 50 * Called from kernel/module.c:sys_init_module and routine for a.out format, 70 51 * signal handler code and kprobes code 71 52 */ 72 - void flush_icache_range(unsigned long start, unsigned long end) 53 + static void sh4_flush_icache_range(unsigned long start, unsigned long end) 73 54 { 74 55 int icacheaddr; 75 56 unsigned long flags, v; ··· 104 137 * Write back & invalidate the D-cache of the page. 105 138 * (To avoid "alias" issues) 106 139 */ 107 - void flush_dcache_page(struct page *page) 140 + static void sh4_flush_dcache_page(struct page *page) 108 141 { 109 142 struct address_space *mapping = page_mapping(page); 110 143 ··· 155 188 wmb(); 156 189 } 157 190 158 - void flush_cache_all(void) 191 + static void sh4_flush_cache_all(void) 159 192 { 160 193 flush_dcache_all(); 161 194 flush_icache_all(); ··· 247 280 * 248 281 * Caller takes mm->mmap_sem. 249 282 */ 250 - void flush_cache_mm(struct mm_struct *mm) 283 + static void sh4_flush_cache_mm(struct mm_struct *mm) 251 284 { 252 285 if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT) 253 286 return; ··· 287 320 * ADDR: Virtual Address (U0 address) 288 321 * PFN: Physical page number 289 322 */ 290 - void flush_cache_page(struct vm_area_struct *vma, unsigned long address, 291 - unsigned long pfn) 323 + static void sh4_flush_cache_page(struct vm_area_struct *vma, 324 + unsigned long address, unsigned long pfn) 292 325 { 293 326 unsigned long phys = pfn << PAGE_SHIFT; 294 327 unsigned int alias_mask; ··· 335 368 * Flushing the cache lines for U0 only isn't enough. 336 369 * We need to flush for P1 too, which may contain aliases. 337 370 */ 338 - void flush_cache_range(struct vm_area_struct *vma, unsigned long start, 339 - unsigned long end) 371 + static void sh4_flush_cache_range(struct vm_area_struct *vma, 372 + unsigned long start, unsigned long end) 340 373 { 341 374 if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT) 342 375 return; ··· 634 667 a2 += linesz; 635 668 a3 += linesz; 636 669 } while (a0 < a0e); 670 + } 671 + 672 + extern void __weak sh4__flush_region_init(void); 673 + 674 + /* 675 + * SH-4 has virtually indexed and physically tagged cache. 676 + */ 677 + void __init sh4_cache_init(void) 678 + { 679 + printk("PVR=%08x CVR=%08x PRR=%08x\n", 680 + ctrl_inl(CCN_PVR), 681 + ctrl_inl(CCN_CVR), 682 + ctrl_inl(CCN_PRR)); 683 + 684 + switch (boot_cpu_data.dcache.ways) { 685 + case 1: 686 + __flush_dcache_segment_fn = __flush_dcache_segment_1way; 687 + break; 688 + case 2: 689 + __flush_dcache_segment_fn = __flush_dcache_segment_2way; 690 + break; 691 + case 4: 692 + __flush_dcache_segment_fn = __flush_dcache_segment_4way; 693 + break; 694 + default: 695 + panic("unknown number of cache ways\n"); 696 + break; 697 + } 698 + 699 + flush_icache_range = sh4_flush_icache_range; 700 + flush_dcache_page = sh4_flush_dcache_page; 701 + flush_cache_all = sh4_flush_cache_all; 702 + flush_cache_mm = sh4_flush_cache_mm; 703 + flush_cache_dup_mm = sh4_flush_cache_mm; 704 + flush_cache_page = sh4_flush_cache_page; 705 + flush_cache_range = sh4_flush_cache_range; 706 + 707 + sh4__flush_region_init(); 637 708 }
+4
arch/sh/mm/cache-sh5.c
··· 20 20 #include <asm/uaccess.h> 21 21 #include <asm/mmu_context.h> 22 22 23 + extern void __weak sh4__flush_region_init(void); 24 + 23 25 /* Wired TLB entry for the D-cache */ 24 26 static unsigned long long dtlb_cache_slot; 25 27 ··· 29 27 { 30 28 /* Reserve a slot for dcache colouring in the DTLB */ 31 29 dtlb_cache_slot = sh64_get_wired_dtlb_entry(); 30 + 31 + sh4__flush_region_init(); 32 32 } 33 33 34 34 void __init kmap_coherent_init(void)
+70
arch/sh/mm/cache.c
··· 15 15 #include <asm/mmu_context.h> 16 16 #include <asm/cacheflush.h> 17 17 18 + void (*flush_cache_all)(void); 19 + void (*flush_cache_mm)(struct mm_struct *mm); 20 + void (*flush_cache_dup_mm)(struct mm_struct *mm); 21 + void (*flush_cache_page)(struct vm_area_struct *vma, 22 + unsigned long addr, unsigned long pfn); 23 + void (*flush_cache_range)(struct vm_area_struct *vma, 24 + unsigned long start, unsigned long end); 25 + void (*flush_dcache_page)(struct page *page); 26 + void (*flush_icache_range)(unsigned long start, unsigned long end); 27 + void (*flush_icache_page)(struct vm_area_struct *vma, 28 + struct page *page); 29 + void (*flush_cache_sigtramp)(unsigned long address); 30 + void (*__flush_wback_region)(void *start, int size); 31 + void (*__flush_purge_region)(void *start, int size); 32 + void (*__flush_invalidate_region)(void *start, int size); 33 + 34 + static inline void noop_flush_cache_all(void) 35 + { 36 + } 37 + 38 + static inline void noop_flush_cache_mm(struct mm_struct *mm) 39 + { 40 + } 41 + 42 + static inline void noop_flush_cache_page(struct vm_area_struct *vma, 43 + unsigned long addr, unsigned long pfn) 44 + { 45 + } 46 + 47 + static inline void noop_flush_cache_range(struct vm_area_struct *vma, 48 + unsigned long start, unsigned long end) 49 + { 50 + } 51 + 52 + static inline void noop_flush_dcache_page(struct page *page) 53 + { 54 + } 55 + 56 + static inline void noop_flush_icache_range(unsigned long start, 57 + unsigned long end) 58 + { 59 + } 60 + 61 + static inline void noop_flush_icache_page(struct vm_area_struct *vma, 62 + struct page *page) 63 + { 64 + } 65 + 66 + static inline void noop_flush_cache_sigtramp(unsigned long address) 67 + { 68 + } 69 + 70 + static inline void noop__flush_region(void *start, int size) 71 + { 72 + } 73 + 18 74 void copy_to_user_page(struct vm_area_struct *vma, struct page *page, 19 75 unsigned long vaddr, void *dst, const void *src, 20 76 unsigned long len) ··· 229 173 compute_alias(&boot_cpu_data.icache); 230 174 compute_alias(&boot_cpu_data.dcache); 231 175 compute_alias(&boot_cpu_data.scache); 176 + 177 + flush_cache_all = noop_flush_cache_all; 178 + flush_cache_mm = noop_flush_cache_mm; 179 + flush_cache_dup_mm = noop_flush_cache_mm; 180 + flush_cache_page = noop_flush_cache_page; 181 + flush_cache_range = noop_flush_cache_range; 182 + flush_dcache_page = noop_flush_dcache_page; 183 + flush_icache_range = noop_flush_icache_range; 184 + flush_icache_page = noop_flush_icache_page; 185 + flush_cache_sigtramp = noop_flush_cache_sigtramp; 186 + 187 + __flush_wback_region = noop__flush_region; 188 + __flush_purge_region = noop__flush_region; 189 + __flush_invalidate_region = noop__flush_region; 232 190 233 191 if ((boot_cpu_data.family == CPU_FAMILY_SH4) || 234 192 (boot_cpu_data.family == CPU_FAMILY_SH4A) ||
+10 -3
arch/sh/mm/flush-sh4.c
··· 8 8 * START: Virtual Address (U0, P1, or P3) 9 9 * SIZE: Size of the region. 10 10 */ 11 - void __weak __flush_wback_region(void *start, int size) 11 + static void sh4__flush_wback_region(void *start, int size) 12 12 { 13 13 reg_size_t aligned_start, v, cnt, end; 14 14 ··· 51 51 * START: Virtual Address (U0, P1, or P3) 52 52 * SIZE: Size of the region. 53 53 */ 54 - void __weak __flush_purge_region(void *start, int size) 54 + static void sh4__flush_purge_region(void *start, int size) 55 55 { 56 56 reg_size_t aligned_start, v, cnt, end; 57 57 ··· 90 90 /* 91 91 * No write back please 92 92 */ 93 - void __weak __flush_invalidate_region(void *start, int size) 93 + static void sh4__flush_invalidate_region(void *start, int size) 94 94 { 95 95 reg_size_t aligned_start, v, cnt, end; 96 96 ··· 125 125 v += L1_CACHE_BYTES; 126 126 cnt--; 127 127 } 128 + } 129 + 130 + void __init sh4__flush_region_init(void) 131 + { 132 + __flush_wback_region = sh4__flush_wback_region; 133 + __flush_invalidate_region = sh4__flush_invalidate_region; 134 + __flush_purge_region = sh4__flush_purge_region; 128 135 }
+3 -2
arch/sh/mm/init.c
··· 210 210 high_memory = node_high_memory; 211 211 } 212 212 213 + /* Set this up early, so we can take care of the zero page */ 214 + cpu_cache_init(); 215 + 213 216 /* clear the zero-page */ 214 217 memset(empty_zero_page, 0, PAGE_SIZE); 215 218 __flush_wback_region(empty_zero_page, PAGE_SIZE); ··· 232 229 codesize >> 10, 233 230 datasize >> 10, 234 231 initsize >> 10); 235 - 236 - cpu_cache_init(); 237 232 238 233 /* Initialize the vDSO */ 239 234 vsyscall_init();