aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-05-09 05:40:18 -0400
committerVineet Gupta <vgupta@synopsys.com>2013-05-09 12:23:16 -0400
commit6ec18a81b22ab2b40df8424f2b5fc6be20ccad87 (patch)
tree974447f69a0a4b10dc0f1f7ff81440539761b4dc /arch/arc
parenta690984d60abcb627ce1bcc0300a14043b5e224a (diff)
ARC: [mm] Aliasing VIPT dcache support 1/4
This preps the low level dcache flush helpers to take vaddr argument in addition to the existing paddr to properly flush the VIPT dcache Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc')
-rw-r--r--arch/arc/include/asm/cacheflush.h2
-rw-r--r--arch/arc/mm/cache_arc700.c48
-rw-r--r--arch/arc/mm/tlb.c2
3 files changed, 34 insertions, 18 deletions
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
index ee1f6eae82d2..ed820bcb745e 100644
--- a/arch/arc/include/asm/cacheflush.h
+++ b/arch/arc/include/asm/cacheflush.h
@@ -33,7 +33,7 @@ void flush_cache_all(void);
33void flush_icache_range(unsigned long start, unsigned long end); 33void flush_icache_range(unsigned long start, unsigned long end);
34void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len); 34void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len);
35void __inv_icache_page(unsigned long paddr, unsigned long vaddr); 35void __inv_icache_page(unsigned long paddr, unsigned long vaddr);
36void __flush_dcache_page(unsigned long paddr); 36void __flush_dcache_page(unsigned long paddr, unsigned long vaddr);
37 37
38#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 38#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
39 39
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
index 8a760e2c0341..a9a37089257a 100644
--- a/arch/arc/mm/cache_arc700.c
+++ b/arch/arc/mm/cache_arc700.c
@@ -269,9 +269,10 @@ static inline void __dc_entire_op(const int cacheop)
269 * Per Line Operation on D-Cache 269 * Per Line Operation on D-Cache
270 * Doesn't deal with type-of-op/IRQ-disabling/waiting-for-flush-to-complete 270 * Doesn't deal with type-of-op/IRQ-disabling/waiting-for-flush-to-complete
271 * It's sole purpose is to help gcc generate ZOL 271 * It's sole purpose is to help gcc generate ZOL
272 * (aliasing VIPT dcache flushing needs both vaddr and paddr)
272 */ 273 */
273static inline void __dc_line_loop(unsigned long paddr, unsigned long sz, 274static inline void __dc_line_loop(unsigned long paddr, unsigned long vaddr,
274 int aux_reg) 275 unsigned long sz, const int aux_reg)
275{ 276{
276 int num_lines; 277 int num_lines;
277 278
@@ -284,31 +285,41 @@ static inline void __dc_line_loop(unsigned long paddr, unsigned long sz,
284 if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) { 285 if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
285 sz += paddr & ~DCACHE_LINE_MASK; 286 sz += paddr & ~DCACHE_LINE_MASK;
286 paddr &= DCACHE_LINE_MASK; 287 paddr &= DCACHE_LINE_MASK;
288 vaddr &= DCACHE_LINE_MASK;
287 } 289 }
288 290
289 num_lines = DIV_ROUND_UP(sz, ARC_DCACHE_LINE_LEN); 291 num_lines = DIV_ROUND_UP(sz, ARC_DCACHE_LINE_LEN);
290 292
293#if (CONFIG_ARC_MMU_VER <= 2)
294 paddr |= (vaddr >> PAGE_SHIFT) & 0x1F;
295#endif
296
291 while (num_lines-- > 0) { 297 while (num_lines-- > 0) {
292#if (CONFIG_ARC_MMU_VER > 2) 298#if (CONFIG_ARC_MMU_VER > 2)
293 /* 299 /*
294 * Just as for I$, in MMU v3, D$ ops also require 300 * Just as for I$, in MMU v3, D$ ops also require
295 * "tag" bits in DC_PTAG, "index" bits in FLDL,IVDL ops 301 * "tag" bits in DC_PTAG, "index" bits in FLDL,IVDL ops
296 * But we pass phy addr for both. This works since Linux
297 * doesn't support aliasing configs for D$, yet.
298 * Thus paddr is enough to provide both tag and index.
299 */ 302 */
300 write_aux_reg(ARC_REG_DC_PTAG, paddr); 303 write_aux_reg(ARC_REG_DC_PTAG, paddr);
301#endif 304
305 write_aux_reg(aux_reg, vaddr);
306 vaddr += ARC_DCACHE_LINE_LEN;
307#else
308 /* paddr contains stuffed vaddrs bits */
302 write_aux_reg(aux_reg, paddr); 309 write_aux_reg(aux_reg, paddr);
310#endif
303 paddr += ARC_DCACHE_LINE_LEN; 311 paddr += ARC_DCACHE_LINE_LEN;
304 } 312 }
305} 313}
306 314
315/* For kernel mappings cache op index is same as paddr */
316#define __dc_line_op_k(p, sz, op) __dc_line_op(p, p, sz, op)
317
307/* 318/*
308 * D-Cache : Per Line INV (discard or wback+discard) or FLUSH (wback) 319 * D-Cache : Per Line INV (discard or wback+discard) or FLUSH (wback)
309 */ 320 */
310static inline void __dc_line_op(unsigned long paddr, unsigned long sz, 321static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
311 const int cacheop) 322 unsigned long sz, const int cacheop)
312{ 323{
313 unsigned long flags, tmp = tmp; 324 unsigned long flags, tmp = tmp;
314 int aux; 325 int aux;
@@ -331,7 +342,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
331 else 342 else
332 aux = ARC_REG_DC_FLDL; 343 aux = ARC_REG_DC_FLDL;
333 344
334 __dc_line_loop(paddr, sz, aux); 345 __dc_line_loop(paddr, vaddr, sz, aux);
335 346
336 if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */ 347 if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */
337 wait_for_flush(); 348 wait_for_flush();
@@ -346,7 +357,8 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
346#else 357#else
347 358
348#define __dc_entire_op(cacheop) 359#define __dc_entire_op(cacheop)
349#define __dc_line_op(paddr, sz, cacheop) 360#define __dc_line_op(paddr, vaddr, sz, cacheop)
361#define __dc_line_op_k(paddr, sz, cacheop)
350 362
351#endif /* CONFIG_ARC_HAS_DCACHE */ 363#endif /* CONFIG_ARC_HAS_DCACHE */
352 364
@@ -462,19 +474,19 @@ EXPORT_SYMBOL(flush_dcache_page);
462 474
463void dma_cache_wback_inv(unsigned long start, unsigned long sz) 475void dma_cache_wback_inv(unsigned long start, unsigned long sz)
464{ 476{
465 __dc_line_op(start, sz, OP_FLUSH_N_INV); 477 __dc_line_op_k(start, sz, OP_FLUSH_N_INV);
466} 478}
467EXPORT_SYMBOL(dma_cache_wback_inv); 479EXPORT_SYMBOL(dma_cache_wback_inv);
468 480
469void dma_cache_inv(unsigned long start, unsigned long sz) 481void dma_cache_inv(unsigned long start, unsigned long sz)
470{ 482{
471 __dc_line_op(start, sz, OP_INV); 483 __dc_line_op_k(start, sz, OP_INV);
472} 484}
473EXPORT_SYMBOL(dma_cache_inv); 485EXPORT_SYMBOL(dma_cache_inv);
474 486
475void dma_cache_wback(unsigned long start, unsigned long sz) 487void dma_cache_wback(unsigned long start, unsigned long sz)
476{ 488{
477 __dc_line_op(start, sz, OP_FLUSH); 489 __dc_line_op_k(start, sz, OP_FLUSH);
478} 490}
479EXPORT_SYMBOL(dma_cache_wback); 491EXPORT_SYMBOL(dma_cache_wback);
480 492
@@ -555,7 +567,7 @@ void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len)
555 567
556 local_irq_save(flags); 568 local_irq_save(flags);
557 __ic_line_inv_vaddr(paddr, vaddr, len); 569 __ic_line_inv_vaddr(paddr, vaddr, len);
558 __dc_line_op(paddr, len, OP_FLUSH); 570 __dc_line_op(paddr, vaddr, len, OP_FLUSH);
559 local_irq_restore(flags); 571 local_irq_restore(flags);
560} 572}
561 573
@@ -565,9 +577,13 @@ void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
565 __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE); 577 __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE);
566} 578}
567 579
568void __flush_dcache_page(unsigned long paddr) 580/*
581 * wrapper to clearout kernel or userspace mappings of a page
582 * For kernel mappings @vaddr == @paddr
583 */
584void __flush_dcache_page(unsigned long paddr, unsigned long vaddr)
569{ 585{
570 __dc_line_op(paddr, PAGE_SIZE, OP_FLUSH_N_INV); 586 __dc_line_op(paddr, vaddr & PAGE_MASK, PAGE_SIZE, OP_FLUSH_N_INV);
571} 587}
572 588
573void flush_icache_all(void) 589void flush_icache_all(void)
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 003d69ac6ffa..5810c7a92b77 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -438,7 +438,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
438 int dirty = test_and_clear_bit(PG_arch_1, &page->flags); 438 int dirty = test_and_clear_bit(PG_arch_1, &page->flags);
439 if (dirty) { 439 if (dirty) {
440 unsigned long paddr = pte_val(*ptep) & PAGE_MASK; 440 unsigned long paddr = pte_val(*ptep) & PAGE_MASK;
441 __flush_dcache_page(paddr); 441 __flush_dcache_page(paddr, paddr);
442 __inv_icache_page(paddr, vaddr); 442 __inv_icache_page(paddr, vaddr);
443 } 443 }
444 } 444 }