1/* $Id: cache.c,v 1.1.1.1 2007/08/03 18:52:02 Exp $ 2 * 3 * This file is subject to the terms and conditions of the GNU General Public 4 * License. See the file "COPYING" in the main directory of this archive 5 * for more details. 6 * 7 * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> (07-13-1999) 8 * Copyright (C) 1999 SuSE GmbH Nuernberg 9 * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org) 10 * 11 * Cache and TLB management 12 * 13 */ 14 15#include <linux/init.h> 16#include <linux/kernel.h> 17#include <linux/mm.h> 18#include <linux/module.h> 19#include <linux/seq_file.h> 20#include <linux/pagemap.h> 21#include <linux/sched.h> 22#include <asm/pdc.h> 23#include <asm/cache.h> 24#include <asm/cacheflush.h> 25#include <asm/tlbflush.h> 26#include <asm/system.h> 27#include <asm/page.h> 28#include <asm/pgalloc.h> 29#include <asm/processor.h> 30#include <asm/sections.h> 31 32int split_tlb __read_mostly; 33int dcache_stride __read_mostly; 34int icache_stride __read_mostly; 35EXPORT_SYMBOL(dcache_stride); 36 37 38/* On some machines (e.g. ones with the Merced bus), there can be 39 * only a single PxTLB broadcast at a time; this must be guaranteed 40 * by software. We put a spinlock around all TLB flushes to 41 * ensure this. 42 */ 43DEFINE_SPINLOCK(pa_tlb_lock); 44 45struct pdc_cache_info cache_info __read_mostly; 46#ifndef CONFIG_PA20 47static struct pdc_btlb_info btlb_info __read_mostly; 48#endif 49 50#ifdef CONFIG_SMP 51void 52flush_data_cache(void) 53{ 54 on_each_cpu(flush_data_cache_local, NULL, 1, 1); 55} 56void 57flush_instruction_cache(void) 58{ 59 on_each_cpu(flush_instruction_cache_local, NULL, 1, 1); 60} 61#endif 62 63void 64flush_cache_all_local(void) 65{ 66 flush_instruction_cache_local(NULL); 67 flush_data_cache_local(NULL); 68} 69EXPORT_SYMBOL(flush_cache_all_local); 70 71void 72update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) 73{ 74 struct page *page = pte_page(pte); 75 76 if (pfn_valid(page_to_pfn(page)) && page_mapping(page) && 77 test_bit(PG_dcache_dirty, &page->flags)) { 78 79 flush_kernel_dcache_page(page); 80 clear_bit(PG_dcache_dirty, &page->flags); 81 } else if (parisc_requires_coherency()) 82 flush_kernel_dcache_page(page); 83} 84 85void 86show_cache_info(struct seq_file *m) 87{ 88 char buf[32]; 89 90 seq_printf(m, "I-cache\t\t: %ld KB\n", 91 cache_info.ic_size/1024 ); 92 if (cache_info.dc_loop != 1) 93 snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop); 94 seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n", 95 cache_info.dc_size/1024, 96 (cache_info.dc_conf.cc_wt ? "WT":"WB"), 97 (cache_info.dc_conf.cc_sh ? ", shared I/D":""), 98 ((cache_info.dc_loop == 1) ? "direct mapped" : buf)); 99 seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n", 100 cache_info.it_size, 101 cache_info.dt_size, 102 cache_info.dt_conf.tc_sh ? " - shared with ITLB":"" 103 ); 104 105#ifndef CONFIG_PA20 106 /* BTLB - Block TLB */ 107 if (btlb_info.max_size==0) { 108 seq_printf(m, "BTLB\t\t: not supported\n" ); 109 } else { 110 seq_printf(m, 111 "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n" 112 "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n" 113 "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n", 114 btlb_info.max_size, (int)4096, 115 btlb_info.max_size>>8, 116 btlb_info.fixed_range_info.num_i, 117 btlb_info.fixed_range_info.num_d, 118 btlb_info.fixed_range_info.num_comb, 119 btlb_info.variable_range_info.num_i, 120 btlb_info.variable_range_info.num_d, 121 btlb_info.variable_range_info.num_comb 122 ); 123 } 124#endif 125} 126 127void __init 128parisc_cache_init(void) 129{ 130 if (pdc_cache_info(&cache_info) < 0) 131 panic("parisc_cache_init: pdc_cache_info failed"); 132 133 134 split_tlb = 0; 135 if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) { 136 if (cache_info.dt_conf.tc_sh == 2) 137 printk(KERN_WARNING "Unexpected TLB configuration. " 138 "Will flush I/D separately (could be optimized).\n"); 139 140 split_tlb = 1; 141 } 142 143 /* "New and Improved" version from Jim Hull 144 * (1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift)) 145 * The following CAFL_STRIDE is an optimized version, see 146 * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023625.html 147 * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023671.html 148 */ 149#define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift)) 150 dcache_stride = CAFL_STRIDE(cache_info.dc_conf); 151 icache_stride = CAFL_STRIDE(cache_info.ic_conf); 152#undef CAFL_STRIDE 153 154#ifndef CONFIG_PA20 155 if (pdc_btlb_info(&btlb_info) < 0) { 156 memset(&btlb_info, 0, sizeof btlb_info); 157 } 158#endif 159 160 if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == 161 PDC_MODEL_NVA_UNSUPPORTED) { 162 printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n"); 163 } 164} 165 166void disable_sr_hashing(void) 167{ 168 int srhash_type, retval; 169 unsigned long space_bits; 170 171 switch (boot_cpu_data.cpu_type) { 172 case pcx: /* We shouldn't get this far. setup.c should prevent it. */ 173 BUG(); 174 return; 175 176 case pcxs: 177 case pcxt: 178 case pcxt_: 179 srhash_type = SRHASH_PCXST; 180 break; 181 182 case pcxl: 183 srhash_type = SRHASH_PCXL; 184 break; 185 186 case pcxl2: /* pcxl2 doesn't support space register hashing */ 187 return; 188 189 default: /* Currently all PA2.0 machines use the same ins. sequence */ 190 srhash_type = SRHASH_PA20; 191 break; 192 } 193 194 disable_sr_hashing_asm(srhash_type); 195 196 retval = pdc_spaceid_bits(&space_bits); 197 /* If this procedure isn't implemented, don't panic. */ 198 if (retval < 0 && retval != PDC_BAD_OPTION) 199 panic("pdc_spaceid_bits call failed.\n"); 200 if (space_bits != 0) 201 panic("SpaceID hashing is still on!\n"); 202} 203 204/* Simple function to work out if we have an existing address translation 205 * for a user space vma. */ 206static inline int translation_exists(struct vm_area_struct *vma, 207 unsigned long addr, unsigned long pfn) 208{ 209 pgd_t *pgd = pgd_offset(vma->vm_mm, addr); 210 pmd_t *pmd; 211 pte_t pte; 212 213 if(pgd_none(*pgd)) 214 return 0; 215 216 pmd = pmd_offset(pgd, addr); 217 if(pmd_none(*pmd) || pmd_bad(*pmd)) 218 return 0; 219 220 /* We cannot take the pte lock here: flush_cache_page is usually 221 * called with pte lock already held. Whereas flush_dcache_page 222 * takes flush_dcache_mmap_lock, which is lower in the hierarchy: 223 * the vma itself is secure, but the pte might come or go racily. 224 */ 225 pte = *pte_offset_map(pmd, addr); 226 /* But pte_unmap() does nothing on this architecture */ 227 228 /* Filter out coincidental file entries and swap entries */ 229 if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT))) 230 return 0; 231 232 return pte_pfn(pte) == pfn; 233} 234 235/* Private function to flush a page from the cache of a non-current 236 * process. cr25 contains the Page Directory of the current user 237 * process; we're going to hijack both it and the user space %sr3 to 238 * temporarily make the non-current process current. We have to do 239 * this because cache flushing may cause a non-access tlb miss which 240 * the handlers have to fill in from the pgd of the non-current 241 * process. */ 242static inline void 243flush_user_cache_page_non_current(struct vm_area_struct *vma, 244 unsigned long vmaddr) 245{ 246 /* save the current process space and pgd */ 247 unsigned long space = mfsp(3), pgd = mfctl(25); 248 249 /* we don't mind taking interrups since they may not 250 * do anything with user space, but we can't 251 * be preempted here */ 252 preempt_disable(); 253 254 /* make us current */ 255 mtctl(__pa(vma->vm_mm->pgd), 25); 256 mtsp(vma->vm_mm->context, 3); 257 258 flush_user_dcache_page(vmaddr); 259 if(vma->vm_flags & VM_EXEC) 260 flush_user_icache_page(vmaddr); 261 262 /* put the old current process back */ 263 mtsp(space, 3); 264 mtctl(pgd, 25); 265 preempt_enable(); 266} 267 268 269static inline void 270__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr) 271{ 272 if (likely(vma->vm_mm->context == mfsp(3))) { 273 flush_user_dcache_page(vmaddr); 274 if (vma->vm_flags & VM_EXEC) 275 flush_user_icache_page(vmaddr); 276 } else { 277 flush_user_cache_page_non_current(vma, vmaddr); 278 } 279} 280 281void flush_dcache_page(struct page *page) 282{ 283 struct address_space *mapping = page_mapping(page); 284 struct vm_area_struct *mpnt; 285 struct prio_tree_iter iter; 286 unsigned long offset; 287 unsigned long addr; 288 pgoff_t pgoff; 289 unsigned long pfn = page_to_pfn(page); 290 291 292 if (mapping && !mapping_mapped(mapping)) { 293 set_bit(PG_dcache_dirty, &page->flags); 294 return; 295 } 296 297 flush_kernel_dcache_page(page); 298 299 if (!mapping) 300 return; 301 302 pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); 303 304 /* We have carefully arranged in arch_get_unmapped_area() that 305 * *any* mappings of a file are always congruently mapped (whether 306 * declared as MAP_PRIVATE or MAP_SHARED), so we only need 307 * to flush one address here for them all to become coherent */ 308 309 flush_dcache_mmap_lock(mapping); 310 vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) { 311 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; 312 addr = mpnt->vm_start + offset; 313 314 /* Flush instructions produce non access tlb misses. 315 * On PA, we nullify these instructions rather than 316 * taking a page fault if the pte doesn't exist. 317 * This is just for speed. If the page translation 318 * isn't there, there's no point exciting the 319 * nadtlb handler into a nullification frenzy. 320 * 321 * Make sure we really have this page: the private 322 * mappings may cover this area but have COW'd this 323 * particular page. 324 */ 325 if (translation_exists(mpnt, addr, pfn)) { 326 __flush_cache_page(mpnt, addr); 327 break; 328 } 329 } 330 flush_dcache_mmap_unlock(mapping); 331} 332EXPORT_SYMBOL(flush_dcache_page); 333 334/* Defined in arch/parisc/kernel/pacache.S */ 335EXPORT_SYMBOL(flush_kernel_dcache_range_asm); 336EXPORT_SYMBOL(flush_kernel_dcache_page_asm); 337EXPORT_SYMBOL(flush_data_cache_local); 338EXPORT_SYMBOL(flush_kernel_icache_range_asm); 339 340void clear_user_page_asm(void *page, unsigned long vaddr) 341{ 342 /* This function is implemented in assembly in pacache.S */ 343 extern void __clear_user_page_asm(void *page, unsigned long vaddr); 344 345 purge_tlb_start(); 346 __clear_user_page_asm(page, vaddr); 347 purge_tlb_end(); 348} 349 350#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ 351int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; 352 353void __init parisc_setup_cache_timing(void) 354{ 355 unsigned long rangetime, alltime; 356 unsigned long size; 357 358 alltime = mfctl(16); 359 flush_data_cache(); 360 alltime = mfctl(16) - alltime; 361 362 size = (unsigned long)(_end - _text); 363 rangetime = mfctl(16); 364 flush_kernel_dcache_range((unsigned long)_text, size); 365 rangetime = mfctl(16) - rangetime; 366 367 printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n", 368 alltime, size, rangetime); 369 370 /* Racy, but if we see an intermediate value, it's ok too... */ 371 parisc_cache_flush_threshold = size * alltime / rangetime; 372 373 parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1); 374 if (!parisc_cache_flush_threshold) 375 parisc_cache_flush_threshold = FLUSH_THRESHOLD; 376 377 if (parisc_cache_flush_threshold > cache_info.dc_size) 378 parisc_cache_flush_threshold = cache_info.dc_size; 379 380 printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); 381} 382 383extern void purge_kernel_dcache_page(unsigned long); 384extern void clear_user_page_asm(void *page, unsigned long vaddr); 385 386void clear_user_page(void *page, unsigned long vaddr, struct page *pg) 387{ 388 purge_kernel_dcache_page((unsigned long)page); 389 purge_tlb_start(); 390 pdtlb_kernel(page); 391 purge_tlb_end(); 392 clear_user_page_asm(page, vaddr); 393} 394EXPORT_SYMBOL(clear_user_page); 395 396void flush_kernel_dcache_page_addr(void *addr) 397{ 398 flush_kernel_dcache_page_asm(addr); 399 purge_tlb_start(); 400 pdtlb_kernel(addr); 401 purge_tlb_end(); 402} 403EXPORT_SYMBOL(flush_kernel_dcache_page_addr); 404 405void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, 406 struct page *pg) 407{ 408 /* no coherency needed (all in kmap/kunmap) */ 409 copy_user_page_asm(vto, vfrom); 410 if (!parisc_requires_coherency()) 411 flush_kernel_dcache_page_asm(vto); 412} 413EXPORT_SYMBOL(copy_user_page); 414 415#ifdef CONFIG_PA8X00 416 417void kunmap_parisc(void *addr) 418{ 419 if (parisc_requires_coherency()) 420 flush_kernel_dcache_page_addr(addr); 421} 422EXPORT_SYMBOL(kunmap_parisc); 423#endif 424 425void __flush_tlb_range(unsigned long sid, unsigned long start, 426 unsigned long end) 427{ 428 unsigned long npages; 429 430 npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 431 if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */ 432 flush_tlb_all(); 433 else { 434 mtsp(sid, 1); 435 purge_tlb_start(); 436 if (split_tlb) { 437 while (npages--) { 438 pdtlb(start); 439 pitlb(start); 440 start += PAGE_SIZE; 441 } 442 } else { 443 while (npages--) { 444 pdtlb(start); 445 start += PAGE_SIZE; 446 } 447 } 448 purge_tlb_end(); 449 } 450} 451 452static void cacheflush_h_tmp_function(void *dummy) 453{ 454 flush_cache_all_local(); 455} 456 457void flush_cache_all(void) 458{ 459 on_each_cpu(cacheflush_h_tmp_function, NULL, 1, 1); 460} 461 462void flush_cache_mm(struct mm_struct *mm) 463{ 464#ifdef CONFIG_SMP 465 flush_cache_all(); 466#else 467 flush_cache_all_local(); 468#endif 469} 470 471void 472flush_user_dcache_range(unsigned long start, unsigned long end) 473{ 474 if ((end - start) < parisc_cache_flush_threshold) 475 flush_user_dcache_range_asm(start,end); 476 else 477 flush_data_cache(); 478} 479 480void 481flush_user_icache_range(unsigned long start, unsigned long end) 482{ 483 if ((end - start) < parisc_cache_flush_threshold) 484 flush_user_icache_range_asm(start,end); 485 else 486 flush_instruction_cache(); 487} 488 489 490void flush_cache_range(struct vm_area_struct *vma, 491 unsigned long start, unsigned long end) 492{ 493 int sr3; 494 495 if (!vma->vm_mm->context) { 496 BUG(); 497 return; 498 } 499 500 sr3 = mfsp(3); 501 if (vma->vm_mm->context == sr3) { 502 flush_user_dcache_range(start,end); 503 flush_user_icache_range(start,end); 504 } else { 505 flush_cache_all(); 506 } 507} 508 509void 510flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn) 511{ 512 BUG_ON(!vma->vm_mm->context); 513 514 if (likely(translation_exists(vma, vmaddr, pfn))) 515 __flush_cache_page(vma, vmaddr); 516 517} 518