at v2.6.21 166 lines 4.1 kB view raw
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, 07 by Ralf Baechle (ralf@linux-mips.org) 7 * Copyright (C) 2007 MIPS Technologies, Inc. 8 */ 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. */ 21void (*flush_cache_all)(void); 22void (*__flush_cache_all)(void); 23void (*flush_cache_mm)(struct mm_struct *mm); 24void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, 25 unsigned long end); 26void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, 27 unsigned long pfn); 28void (*flush_icache_range)(unsigned long start, unsigned long end); 29 30/* MIPS specific cache operations */ 31void (*flush_cache_sigtramp)(unsigned long addr); 32void (*local_flush_data_cache_page)(void * addr); 33void (*flush_data_cache_page)(unsigned long addr); 34void (*flush_icache_all)(void); 35 36EXPORT_SYMBOL_GPL(local_flush_data_cache_page); 37EXPORT_SYMBOL(flush_data_cache_page); 38 39#ifdef CONFIG_DMA_NONCOHERENT 40 41/* DMA cache operations. */ 42void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); 43void (*_dma_cache_wback)(unsigned long start, unsigned long size); 44void (*_dma_cache_inv)(unsigned long start, unsigned long size); 45 46EXPORT_SYMBOL(_dma_cache_wback_inv); 47EXPORT_SYMBOL(_dma_cache_wback); 48EXPORT_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 */ 56asmlinkage 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 69void __flush_dcache_page(struct page *page) 70{ 71 struct address_space *mapping = page_mapping(page); 72 unsigned long addr; 73 74 if (PageHighMem(page)) 75 return; 76 if (mapping && !mapping_mapped(mapping)) { 77 SetPageDcacheDirty(page); 78 return; 79 } 80 81 /* 82 * We could delay the flush for the !page_mapping case too. But that 83 * case is for exec env/arg pages and those are %99 certainly going to 84 * get faulted into the tlb (and thus flushed) anyways. 85 */ 86 addr = (unsigned long) page_address(page); 87 flush_data_cache_page(addr); 88} 89 90EXPORT_SYMBOL(__flush_dcache_page); 91 92void __flush_anon_page(struct page *page, unsigned long vmaddr) 93{ 94 if (pages_do_alias((unsigned long)page_address(page), vmaddr)) { 95 void *kaddr; 96 97 kaddr = kmap_coherent(page, vmaddr); 98 flush_data_cache_page((unsigned long)kaddr); 99 kunmap_coherent(kaddr); 100 } 101} 102 103EXPORT_SYMBOL(__flush_anon_page); 104 105void __update_cache(struct vm_area_struct *vma, unsigned long address, 106 pte_t pte) 107{ 108 struct page *page; 109 unsigned long pfn, addr; 110 int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; 111 112 pfn = pte_pfn(pte); 113 if (unlikely(!pfn_valid(pfn))) 114 return; 115 page = pfn_to_page(pfn); 116 if (page_mapping(page) && Page_dcache_dirty(page)) { 117 addr = (unsigned long) page_address(page); 118 if (exec || pages_do_alias(addr, address & PAGE_MASK)) 119 flush_data_cache_page(addr); 120 ClearPageDcacheDirty(page); 121 } 122} 123 124static char cache_panic[] __initdata = "Yeee, unsupported cache architecture."; 125 126void __init cpu_cache_init(void) 127{ 128 if (cpu_has_3k_cache) { 129 extern void __weak r3k_cache_init(void); 130 131 r3k_cache_init(); 132 return; 133 } 134 if (cpu_has_6k_cache) { 135 extern void __weak r6k_cache_init(void); 136 137 r6k_cache_init(); 138 return; 139 } 140 if (cpu_has_4k_cache) { 141 extern void __weak r4k_cache_init(void); 142 143 r4k_cache_init(); 144 return; 145 } 146 if (cpu_has_8k_cache) { 147 extern void __weak r8k_cache_init(void); 148 149 r8k_cache_init(); 150 return; 151 } 152 if (cpu_has_tx39_cache) { 153 extern void __weak tx39_cache_init(void); 154 155 tx39_cache_init(); 156 return; 157 } 158 if (cpu_has_sb1_cache) { 159 extern void __weak sb1_cache_init(void); 160 161 sb1_cache_init(); 162 return; 163 } 164 165 panic(cache_panic); 166}