Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cache.c
Go to the documentation of this file.
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) 1999-2006 Helge Deller <[email protected]> (07-13-1999)
7  * Copyright (C) 1999 SuSE GmbH Nuernberg
8  * Copyright (C) 2000 Philipp Rumpf ([email protected])
9  *
10  * Cache and TLB management
11  *
12  */
13 
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/mm.h>
17 #include <linux/module.h>
18 #include <linux/seq_file.h>
19 #include <linux/pagemap.h>
20 #include <linux/sched.h>
21 #include <asm/pdc.h>
22 #include <asm/cache.h>
23 #include <asm/cacheflush.h>
24 #include <asm/tlbflush.h>
25 #include <asm/page.h>
26 #include <asm/pgalloc.h>
27 #include <asm/processor.h>
28 #include <asm/sections.h>
29 #include <asm/shmparam.h>
30 
34 EXPORT_SYMBOL(dcache_stride);
35 
36 void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
38 void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
39 
40 
41 /* On some machines (e.g. ones with the Merced bus), there can be
42  * only a single PxTLB broadcast at a time; this must be guaranteed
43  * by software. We put a spinlock around all TLB flushes to
44  * ensure this.
45  */
46 DEFINE_SPINLOCK(pa_tlb_lock);
47 
49 #ifndef CONFIG_PA20
50 static struct pdc_btlb_info btlb_info __read_mostly;
51 #endif
52 
53 #ifdef CONFIG_SMP
54 void
55 flush_data_cache(void)
56 {
58 }
59 void
61 {
63 }
64 #endif
65 
66 void
68 {
71 }
73 
74 void
75 update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
76 {
77  struct page *page = pte_page(*ptep);
78 
79  if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
80  test_bit(PG_dcache_dirty, &page->flags)) {
81 
82  flush_kernel_dcache_page(page);
84  } else if (parisc_requires_coherency())
85  flush_kernel_dcache_page(page);
86 }
87 
88 void
90 {
91  char buf[32];
92 
93  seq_printf(m, "I-cache\t\t: %ld KB\n",
94  cache_info.ic_size/1024 );
95  if (cache_info.dc_loop != 1)
96  snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop);
97  seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n",
98  cache_info.dc_size/1024,
99  (cache_info.dc_conf.cc_wt ? "WT":"WB"),
100  (cache_info.dc_conf.cc_sh ? ", shared I/D":""),
101  ((cache_info.dc_loop == 1) ? "direct mapped" : buf));
102  seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
103  cache_info.it_size,
104  cache_info.dt_size,
105  cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
106  );
107 
108 #ifndef CONFIG_PA20
109  /* BTLB - Block TLB */
110  if (btlb_info.max_size==0) {
111  seq_printf(m, "BTLB\t\t: not supported\n" );
112  } else {
113  seq_printf(m,
114  "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
115  "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
116  "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
117  btlb_info.max_size, (int)4096,
118  btlb_info.max_size>>8,
119  btlb_info.fixed_range_info.num_i,
120  btlb_info.fixed_range_info.num_d,
121  btlb_info.fixed_range_info.num_comb,
122  btlb_info.variable_range_info.num_i,
123  btlb_info.variable_range_info.num_d,
124  btlb_info.variable_range_info.num_comb
125  );
126  }
127 #endif
128 }
129 
130 void __init
132 {
133  if (pdc_cache_info(&cache_info) < 0)
134  panic("parisc_cache_init: pdc_cache_info failed");
135 
136 #if 0
137  printk("ic_size %lx dc_size %lx it_size %lx\n",
138  cache_info.ic_size,
139  cache_info.dc_size,
140  cache_info.it_size);
141 
142  printk("DC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
143  cache_info.dc_base,
144  cache_info.dc_stride,
145  cache_info.dc_count,
146  cache_info.dc_loop);
147 
148  printk("dc_conf = 0x%lx alias %d blk %d line %d shift %d\n",
149  *(unsigned long *) (&cache_info.dc_conf),
150  cache_info.dc_conf.cc_alias,
151  cache_info.dc_conf.cc_block,
152  cache_info.dc_conf.cc_line,
153  cache_info.dc_conf.cc_shift);
154  printk(" wt %d sh %d cst %d hv %d\n",
155  cache_info.dc_conf.cc_wt,
156  cache_info.dc_conf.cc_sh,
157  cache_info.dc_conf.cc_cst,
158  cache_info.dc_conf.cc_hv);
159 
160  printk("IC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
161  cache_info.ic_base,
162  cache_info.ic_stride,
163  cache_info.ic_count,
164  cache_info.ic_loop);
165 
166  printk("ic_conf = 0x%lx alias %d blk %d line %d shift %d\n",
167  *(unsigned long *) (&cache_info.ic_conf),
168  cache_info.ic_conf.cc_alias,
169  cache_info.ic_conf.cc_block,
170  cache_info.ic_conf.cc_line,
171  cache_info.ic_conf.cc_shift);
172  printk(" wt %d sh %d cst %d hv %d\n",
173  cache_info.ic_conf.cc_wt,
174  cache_info.ic_conf.cc_sh,
175  cache_info.ic_conf.cc_cst,
176  cache_info.ic_conf.cc_hv);
177 
178  printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
179  cache_info.dt_conf.tc_sh,
180  cache_info.dt_conf.tc_page,
181  cache_info.dt_conf.tc_cst,
182  cache_info.dt_conf.tc_aid,
183  cache_info.dt_conf.tc_pad1);
184 
185  printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
186  cache_info.it_conf.tc_sh,
187  cache_info.it_conf.tc_page,
188  cache_info.it_conf.tc_cst,
189  cache_info.it_conf.tc_aid,
190  cache_info.it_conf.tc_pad1);
191 #endif
192 
193  split_tlb = 0;
194  if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {
195  if (cache_info.dt_conf.tc_sh == 2)
196  printk(KERN_WARNING "Unexpected TLB configuration. "
197  "Will flush I/D separately (could be optimized).\n");
198 
199  split_tlb = 1;
200  }
201 
202  /* "New and Improved" version from Jim Hull
203  * (1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift))
204  * The following CAFL_STRIDE is an optimized version, see
205  * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023625.html
206  * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023671.html
207  */
208 #define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift))
211 #undef CAFL_STRIDE
212 
213 #ifndef CONFIG_PA20
214  if (pdc_btlb_info(&btlb_info) < 0) {
215  memset(&btlb_info, 0, sizeof btlb_info);
216  }
217 #endif
218 
219  if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) ==
221  printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n");
222 #if 0
223  panic("SMP kernel required to avoid non-equivalent aliasing");
224 #endif
225  }
226 }
227 
229 {
230  int srhash_type, retval;
231  unsigned long space_bits;
232 
233  switch (boot_cpu_data.cpu_type) {
234  case pcx: /* We shouldn't get this far. setup.c should prevent it. */
235  BUG();
236  return;
237 
238  case pcxs:
239  case pcxt:
240  case pcxt_:
241  srhash_type = SRHASH_PCXST;
242  break;
243 
244  case pcxl:
245  srhash_type = SRHASH_PCXL;
246  break;
247 
248  case pcxl2: /* pcxl2 doesn't support space register hashing */
249  return;
250 
251  default: /* Currently all PA2.0 machines use the same ins. sequence */
252  srhash_type = SRHASH_PA20;
253  break;
254  }
255 
256  disable_sr_hashing_asm(srhash_type);
257 
258  retval = pdc_spaceid_bits(&space_bits);
259  /* If this procedure isn't implemented, don't panic. */
260  if (retval < 0 && retval != PDC_BAD_OPTION)
261  panic("pdc_spaceid_bits call failed.\n");
262  if (space_bits != 0)
263  panic("SpaceID hashing is still on!\n");
264 }
265 
266 static inline void
267 __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
268  unsigned long physaddr)
269 {
270  flush_dcache_page_asm(physaddr, vmaddr);
271  if (vma->vm_flags & VM_EXEC)
272  flush_icache_page_asm(physaddr, vmaddr);
273 }
274 
276 {
277  struct address_space *mapping = page_mapping(page);
278  struct vm_area_struct *mpnt;
279  unsigned long offset;
280  unsigned long addr, old_addr = 0;
281  pgoff_t pgoff;
282 
283  if (mapping && !mapping_mapped(mapping)) {
284  set_bit(PG_dcache_dirty, &page->flags);
285  return;
286  }
287 
288  flush_kernel_dcache_page(page);
289 
290  if (!mapping)
291  return;
292 
293  pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
294 
295  /* We have carefully arranged in arch_get_unmapped_area() that
296  * *any* mappings of a file are always congruently mapped (whether
297  * declared as MAP_PRIVATE or MAP_SHARED), so we only need
298  * to flush one address here for them all to become coherent */
299 
300  flush_dcache_mmap_lock(mapping);
301  vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
302  offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
303  addr = mpnt->vm_start + offset;
304 
305  /* The TLB is the engine of coherence on parisc: The
306  * CPU is entitled to speculate any page with a TLB
307  * mapping, so here we kill the mapping then flush the
308  * page along a special flush only alias mapping.
309  * This guarantees that the page is no-longer in the
310  * cache for any process and nor may it be
311  * speculatively read in (until the user or kernel
312  * specifically accesses it, of course) */
313 
314  flush_tlb_page(mpnt, addr);
315  if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
316  __flush_cache_page(mpnt, addr, page_to_phys(page));
317  if (old_addr)
318  printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? (char *)mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
319  old_addr = addr;
320  }
321  }
322  flush_dcache_mmap_unlock(mapping);
323 }
325 
326 /* Defined in arch/parisc/kernel/pacache.S */
331 
332 void clear_user_page_asm(void *page, unsigned long vaddr)
333 {
334  unsigned long flags;
335  /* This function is implemented in assembly in pacache.S */
336  extern void __clear_user_page_asm(void *page, unsigned long vaddr);
337 
338  purge_tlb_start(flags);
339  __clear_user_page_asm(page, vaddr);
340  purge_tlb_end(flags);
341 }
342 
343 #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
344 int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
345 
347 {
348  unsigned long rangetime, alltime;
349  unsigned long size;
350 
351  alltime = mfctl(16);
353  alltime = mfctl(16) - alltime;
354 
355  size = (unsigned long)(_end - _text);
356  rangetime = mfctl(16);
357  flush_kernel_dcache_range((unsigned long)_text, size);
358  rangetime = mfctl(16) - rangetime;
359 
360  printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
361  alltime, size, rangetime);
362 
363  /* Racy, but if we see an intermediate value, it's ok too... */
364  parisc_cache_flush_threshold = size * alltime / rangetime;
365 
366  parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1);
367  if (!parisc_cache_flush_threshold)
368  parisc_cache_flush_threshold = FLUSH_THRESHOLD;
369 
370  if (parisc_cache_flush_threshold > cache_info.dc_size)
371  parisc_cache_flush_threshold = cache_info.dc_size;
372 
373  printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
374 }
375 
376 extern void purge_kernel_dcache_page(unsigned long);
377 extern void clear_user_page_asm(void *page, unsigned long vaddr);
378 
379 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
380 {
381  unsigned long flags;
382 
383  purge_kernel_dcache_page((unsigned long)page);
384  purge_tlb_start(flags);
385  pdtlb_kernel(page);
386  purge_tlb_end(flags);
387  clear_user_page_asm(page, vaddr);
388 }
390 
392 {
393  unsigned long flags;
394 
396  purge_tlb_start(flags);
397  pdtlb_kernel(addr);
398  purge_tlb_end(flags);
399 }
401 
402 void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
403  struct page *pg)
404 {
405  /* no coherency needed (all in kmap/kunmap) */
406  copy_user_page_asm(vto, vfrom);
407  if (!parisc_requires_coherency())
409 }
411 
412 #ifdef CONFIG_PA8X00
413 
414 void kunmap_parisc(void *addr)
415 {
416  if (parisc_requires_coherency())
418 }
419 EXPORT_SYMBOL(kunmap_parisc);
420 #endif
421 
422 void __flush_tlb_range(unsigned long sid, unsigned long start,
423  unsigned long end)
424 {
425  unsigned long npages;
426 
427  npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
428  if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */
429  flush_tlb_all();
430  else {
431  unsigned long flags;
432 
433  mtsp(sid, 1);
434  purge_tlb_start(flags);
435  if (split_tlb) {
436  while (npages--) {
437  pdtlb(start);
438  pitlb(start);
439  start += PAGE_SIZE;
440  }
441  } else {
442  while (npages--) {
443  pdtlb(start);
444  start += PAGE_SIZE;
445  }
446  }
447  purge_tlb_end(flags);
448  }
449 }
450 
451 static void cacheflush_h_tmp_function(void *dummy)
452 {
454 }
455 
456 void flush_cache_all(void)
457 {
458  on_each_cpu(cacheflush_h_tmp_function, NULL, 1);
459 }
460 
461 void flush_cache_mm(struct mm_struct *mm)
462 {
463 #ifdef CONFIG_SMP
464  flush_cache_all();
465 #else
467 #endif
468 }
469 
470 void
471 flush_user_dcache_range(unsigned long start, unsigned long end)
472 {
473  if ((end - start) < parisc_cache_flush_threshold)
474  flush_user_dcache_range_asm(start,end);
475  else
477 }
478 
479 void
480 flush_user_icache_range(unsigned long start, unsigned long end)
481 {
482  if ((end - start) < parisc_cache_flush_threshold)
483  flush_user_icache_range_asm(start,end);
484  else
486 }
487 
488 
490  unsigned long start, unsigned long end)
491 {
492  int sr3;
493 
494  BUG_ON(!vma->vm_mm->context);
495 
496  sr3 = mfsp(3);
497  if (vma->vm_mm->context == sr3) {
498  flush_user_dcache_range(start,end);
499  flush_user_icache_range(start,end);
500  } else {
501  flush_cache_all();
502  }
503 }
504 
505 void
506 flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
507 {
508  BUG_ON(!vma->vm_mm->context);
509 
510  flush_tlb_page(vma, vmaddr);
511  __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn)));
512 
513 }