1 /* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1994 - 2003 by Ralf Baechle 7 */ 8 #include <linux/config.h> 9 #include <linux/init.h> 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/sched.h> 13 #include <linux/mm.h> 14 15 #include <asm/cacheflush.h> 16 #include <asm/processor.h> 17 #include <asm/cpu.h> 18 #include <asm/cpu-features.h> 19 20 /* Cache operations. */ 21 void (*flush_cache_all)(void); 22 void (*__flush_cache_all)(void); 23 void (*flush_cache_mm)(struct mm_struct *mm); 24 void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, 25 unsigned long end); 26 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, 27 unsigned long pfn); 28 void (*flush_icache_range)(unsigned long start, unsigned long end); 29 void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); 30 31 /* MIPS specific cache operations */ 32 void (*flush_cache_sigtramp)(unsigned long addr); 33 void (*local_flush_data_cache_page)(void * addr); 34 void (*flush_data_cache_page)(unsigned long addr); 35 void (*flush_icache_all)(void); 36 37 EXPORT_SYMBOL(flush_data_cache_page); 38 39 #ifdef CONFIG_DMA_NONCOHERENT 40 41 /* DMA cache operations. */ 42 void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); 43 void (*_dma_cache_wback)(unsigned long start, unsigned long size); 44 void (*_dma_cache_inv)(unsigned long start, unsigned long size); 45 46 EXPORT_SYMBOL(_dma_cache_wback_inv); 47 EXPORT_SYMBOL(_dma_cache_wback); 48 EXPORT_SYMBOL(_dma_cache_inv); 49 50 #endif /* CONFIG_DMA_NONCOHERENT */ 51 52 /* 53 * We could optimize the case where the cache argument is not BCACHE but 54 * that seems very atypical use ... 55 */ 56 asmlinkage int sys_cacheflush(unsigned long addr, 57 unsigned long bytes, unsigned int cache) 58 { 59 if (bytes == 0) 60 return 0; 61 if (!access_ok(VERIFY_WRITE, (void __user *) addr, bytes)) 62 return -EFAULT; 63 64 flush_icache_range(addr, addr + bytes); 65 66 return 0; 67 } 68 69 void __flush_dcache_page(struct page *page) 70 { 71 struct address_space *mapping = page_mapping(page); 72 unsigned long addr; 73 74 if (mapping && !mapping_mapped(mapping)) { 75 SetPageDcacheDirty(page); 76 return; 77 } 78 79 /* 80 * We could delay the flush for the !page_mapping case too. But that 81 * case is for exec env/arg pages and those are %99 certainly going to 82 * get faulted into the tlb (and thus flushed) anyways. 83 */ 84 addr = (unsigned long) page_address(page); 85 flush_data_cache_page(addr); 86 } 87 88 EXPORT_SYMBOL(__flush_dcache_page); 89 90 void __update_cache(struct vm_area_struct *vma, unsigned long address, 91 pte_t pte) 92 { 93 struct page *page; 94 unsigned long pfn, addr; 95 96 pfn = pte_pfn(pte); 97 if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) && 98 Page_dcache_dirty(page)) { 99 if (pages_do_alias((unsigned long)page_address(page), 100 address & PAGE_MASK)) { 101 addr = (unsigned long) page_address(page); 102 flush_data_cache_page(addr); 103 } 104 105 ClearPageDcacheDirty(page); 106 } 107 } 108 109 #define __weak __attribute__((weak)) 110 111 static char cache_panic[] __initdata = "Yeee, unsupported cache architecture."; 112 113 void __init cpu_cache_init(void) 114 { 115 if (cpu_has_3k_cache) { 116 extern void __weak r3k_cache_init(void); 117 118 r3k_cache_init(); 119 return; 120 } 121 if (cpu_has_6k_cache) { 122 extern void __weak r6k_cache_init(void); 123 124 r6k_cache_init(); 125 return; 126 } 127 if (cpu_has_4k_cache) { 128 extern void __weak r4k_cache_init(void); 129 130 r4k_cache_init(); 131 return; 132 } 133 if (cpu_has_8k_cache) { 134 extern void __weak r8k_cache_init(void); 135 136 r8k_cache_init(); 137 return; 138 } 139 if (cpu_has_tx39_cache) { 140 extern void __weak tx39_cache_init(void); 141 142 tx39_cache_init(); 143 return; 144 } 145 if (cpu_has_sb1_cache) { 146 extern void __weak sb1_cache_init(void); 147 148 sb1_cache_init(); 149 return; 150 } 151 152 panic(cache_panic); 153 } 154