1 /* 2 * arch/sh/mm/cache-sh4.c 3 * 4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 5 * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt 6 * Copyright (C) 2003 Richard Curnow 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12 13 #include <linux/config.h> 14 #include <linux/init.h> 15 #include <linux/mman.h> 16 #include <linux/mm.h> 17 #include <linux/threads.h> 18 #include <asm/addrspace.h> 19 #include <asm/page.h> 20 #include <asm/pgtable.h> 21 #include <asm/processor.h> 22 #include <asm/cache.h> 23 #include <asm/io.h> 24 #include <asm/uaccess.h> 25 #include <asm/pgalloc.h> 26 #include <asm/mmu_context.h> 27 #include <asm/cacheflush.h> 28 29 extern void __flush_cache_4096_all(unsigned long start); 30 static void __flush_cache_4096_all_ex(unsigned long start); 31 extern void __flush_dcache_all(void); 32 static void __flush_dcache_all_ex(void); 33 34 /* 35 * SH-4 has virtually indexed and physically tagged cache. 36 */ 37 38 struct semaphore p3map_sem[4]; 39 40 void __init p3_cache_init(void) 41 { 42 if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE)) 43 panic("%s failed.", __FUNCTION__); 44 45 sema_init (&p3map_sem[0], 1); 46 sema_init (&p3map_sem[1], 1); 47 sema_init (&p3map_sem[2], 1); 48 sema_init (&p3map_sem[3], 1); 49 } 50 51 /* 52 * Write back the dirty D-caches, but not invalidate them. 53 * 54 * START: Virtual Address (U0, P1, or P3) 55 * SIZE: Size of the region. 56 */ 57 void __flush_wback_region(void *start, int size) 58 { 59 unsigned long v; 60 unsigned long begin, end; 61 62 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); 63 end = ((unsigned long)start + size + L1_CACHE_BYTES-1) 64 & ~(L1_CACHE_BYTES-1); 65 for (v = begin; v < end; v+=L1_CACHE_BYTES) { 66 asm volatile("ocbwb %0" 67 : /* no output */ 68 : "m" (__m(v))); 69 } 70 } 71 72 /* 73 * Write back the dirty D-caches and invalidate them. 74 * 75 * START: Virtual Address (U0, P1, or P3) 76 * SIZE: Size of the region. 77 */ 78 void __flush_purge_region(void *start, int size) 79 { 80 unsigned long v; 81 unsigned long begin, end; 82 83 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); 84 end = ((unsigned long)start + size + L1_CACHE_BYTES-1) 85 & ~(L1_CACHE_BYTES-1); 86 for (v = begin; v < end; v+=L1_CACHE_BYTES) { 87 asm volatile("ocbp %0" 88 : /* no output */ 89 : "m" (__m(v))); 90 } 91 } 92 93 94 /* 95 * No write back please 96 */ 97 void __flush_invalidate_region(void *start, int size) 98 { 99 unsigned long v; 100 unsigned long begin, end; 101 102 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); 103 end = ((unsigned long)start + size + L1_CACHE_BYTES-1) 104 & ~(L1_CACHE_BYTES-1); 105 for (v = begin; v < end; v+=L1_CACHE_BYTES) { 106 asm volatile("ocbi %0" 107 : /* no output */ 108 : "m" (__m(v))); 109 } 110 } 111 112 static void __flush_dcache_all_ex(void) 113 { 114 unsigned long addr, end_addr, entry_offset; 115 116 end_addr = CACHE_OC_ADDRESS_ARRAY + (cpu_data->dcache.sets << cpu_data->dcache.entry_shift) * cpu_data->dcache.ways; 117 entry_offset = 1 << cpu_data->dcache.entry_shift; 118 for (addr = CACHE_OC_ADDRESS_ARRAY; addr < end_addr; addr += entry_offset) { 119 ctrl_outl(0, addr); 120 } 121 } 122 123 static void __flush_cache_4096_all_ex(unsigned long start) 124 { 125 unsigned long addr, entry_offset; 126 int i; 127 128 entry_offset = 1 << cpu_data->dcache.entry_shift; 129 for (i = 0; i < cpu_data->dcache.ways; i++, start += cpu_data->dcache.way_incr) { 130 for (addr = CACHE_OC_ADDRESS_ARRAY + start; 131 addr < CACHE_OC_ADDRESS_ARRAY + 4096 + start; 132 addr += entry_offset) { 133 ctrl_outl(0, addr); 134 } 135 } 136 } 137 138 void flush_cache_4096_all(unsigned long start) 139 { 140 if (cpu_data->dcache.ways == 1) 141 __flush_cache_4096_all(start); 142 else 143 __flush_cache_4096_all_ex(start); 144 } 145 146 /* 147 * Write back the range of D-cache, and purge the I-cache. 148 * 149 * Called from kernel/module.c:sys_init_module and routine for a.out format. 150 */ 151 void flush_icache_range(unsigned long start, unsigned long end) 152 { 153 flush_cache_all(); 154 } 155 156 /* 157 * Write back the D-cache and purge the I-cache for signal trampoline. 158 * .. which happens to be the same behavior as flush_icache_range(). 159 * So, we simply flush out a line. 160 */ 161 void flush_cache_sigtramp(unsigned long addr) 162 { 163 unsigned long v, index; 164 unsigned long flags; 165 int i; 166 167 v = addr & ~(L1_CACHE_BYTES-1); 168 asm volatile("ocbwb %0" 169 : /* no output */ 170 : "m" (__m(v))); 171 172 index = CACHE_IC_ADDRESS_ARRAY | (v & cpu_data->icache.entry_mask); 173 174 local_irq_save(flags); 175 jump_to_P2(); 176 for(i = 0; i < cpu_data->icache.ways; i++, index += cpu_data->icache.way_incr) 177 ctrl_outl(0, index); /* Clear out Valid-bit */ 178 back_to_P1(); 179 local_irq_restore(flags); 180 } 181 182 static inline void flush_cache_4096(unsigned long start, 183 unsigned long phys) 184 { 185 unsigned long flags; 186 extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset); 187 188 /* 189 * SH7751, SH7751R, and ST40 have no restriction to handle cache. 190 * (While SH7750 must do that at P2 area.) 191 */ 192 if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) 193 || start < CACHE_OC_ADDRESS_ARRAY) { 194 local_irq_save(flags); 195 __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0x20000000); 196 local_irq_restore(flags); 197 } else { 198 __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0); 199 } 200 } 201 202 /* 203 * Write back & invalidate the D-cache of the page. 204 * (To avoid "alias" issues) 205 */ 206 void flush_dcache_page(struct page *page) 207 { 208 if (test_bit(PG_mapped, &page->flags)) { 209 unsigned long phys = PHYSADDR(page_address(page)); 210 211 /* Loop all the D-cache */ 212 flush_cache_4096(CACHE_OC_ADDRESS_ARRAY, phys); 213 flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys); 214 flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys); 215 flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys); 216 } 217 } 218 219 static inline void flush_icache_all(void) 220 { 221 unsigned long flags, ccr; 222 223 local_irq_save(flags); 224 jump_to_P2(); 225 226 /* Flush I-cache */ 227 ccr = ctrl_inl(CCR); 228 ccr |= CCR_CACHE_ICI; 229 ctrl_outl(ccr, CCR); 230 231 back_to_P1(); 232 local_irq_restore(flags); 233 } 234 235 void flush_cache_all(void) 236 { 237 if (cpu_data->dcache.ways == 1) 238 __flush_dcache_all(); 239 else 240 __flush_dcache_all_ex(); 241 flush_icache_all(); 242 } 243 244 void flush_cache_mm(struct mm_struct *mm) 245 { 246 /* Is there any good way? */ 247 /* XXX: possibly call flush_cache_range for each vm area */ 248 /* 249 * FIXME: Really, the optimal solution here would be able to flush out 250 * individual lines created by the specified context, but this isn't 251 * feasible for a number of architectures (such as MIPS, and some 252 * SPARC) .. is this possible for SuperH? 253 * 254 * In the meantime, we'll just flush all of the caches.. this 255 * seems to be the simplest way to avoid at least a few wasted 256 * cache flushes. -Lethal 257 */ 258 flush_cache_all(); 259 } 260 261 /* 262 * Write back and invalidate I/D-caches for the page. 263 * 264 * ADDR: Virtual Address (U0 address) 265 * PFN: Physical page number 266 */ 267 void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn) 268 { 269 unsigned long phys = pfn << PAGE_SHIFT; 270 271 /* We only need to flush D-cache when we have alias */ 272 if ((address^phys) & CACHE_ALIAS) { 273 /* Loop 4K of the D-cache */ 274 flush_cache_4096( 275 CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS), 276 phys); 277 /* Loop another 4K of the D-cache */ 278 flush_cache_4096( 279 CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS), 280 phys); 281 } 282 283 if (vma->vm_flags & VM_EXEC) 284 /* Loop 4K (half) of the I-cache */ 285 flush_cache_4096( 286 CACHE_IC_ADDRESS_ARRAY | (address & 0x1000), 287 phys); 288 } 289 290 /* 291 * Write back and invalidate D-caches. 292 * 293 * START, END: Virtual Address (U0 address) 294 * 295 * NOTE: We need to flush the _physical_ page entry. 296 * Flushing the cache lines for U0 only isn't enough. 297 * We need to flush for P1 too, which may contain aliases. 298 */ 299 void flush_cache_range(struct vm_area_struct *vma, unsigned long start, 300 unsigned long end) 301 { 302 unsigned long p = start & PAGE_MASK; 303 pgd_t *dir; 304 pmd_t *pmd; 305 pte_t *pte; 306 pte_t entry; 307 unsigned long phys; 308 unsigned long d = 0; 309 310 dir = pgd_offset(vma->vm_mm, p); 311 pmd = pmd_offset(dir, p); 312 313 do { 314 if (pmd_none(*pmd) || pmd_bad(*pmd)) { 315 p &= ~((1 << PMD_SHIFT) -1); 316 p += (1 << PMD_SHIFT); 317 pmd++; 318 continue; 319 } 320 pte = pte_offset_kernel(pmd, p); 321 do { 322 entry = *pte; 323 if ((pte_val(entry) & _PAGE_PRESENT)) { 324 phys = pte_val(entry)&PTE_PHYS_MASK; 325 if ((p^phys) & CACHE_ALIAS) { 326 d |= 1 << ((p & CACHE_ALIAS)>>12); 327 d |= 1 << ((phys & CACHE_ALIAS)>>12); 328 if (d == 0x0f) 329 goto loop_exit; 330 } 331 } 332 pte++; 333 p += PAGE_SIZE; 334 } while (p < end && ((unsigned long)pte & ~PAGE_MASK)); 335 pmd++; 336 } while (p < end); 337 loop_exit: 338 if (d & 1) 339 flush_cache_4096_all(0); 340 if (d & 2) 341 flush_cache_4096_all(0x1000); 342 if (d & 4) 343 flush_cache_4096_all(0x2000); 344 if (d & 8) 345 flush_cache_4096_all(0x3000); 346 if (vma->vm_flags & VM_EXEC) 347 flush_icache_all(); 348 } 349 350 /* 351 * flush_icache_user_range 352 * @vma: VMA of the process 353 * @page: page 354 * @addr: U0 address 355 * @len: length of the range (< page size) 356 */ 357 void flush_icache_user_range(struct vm_area_struct *vma, 358 struct page *page, unsigned long addr, int len) 359 { 360 flush_cache_page(vma, addr, page_to_pfn(page)); 361 } 362 363