aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/mm/cache_arc700.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/mm/cache_arc700.c')
-rw-r--r--arch/arc/mm/cache_arc700.c269
1 files changed, 57 insertions, 212 deletions
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
index 88d617d84234..c854cf95f706 100644
--- a/arch/arc/mm/cache_arc700.c
+++ b/arch/arc/mm/cache_arc700.c
@@ -72,16 +72,6 @@
72#include <asm/cachectl.h> 72#include <asm/cachectl.h>
73#include <asm/setup.h> 73#include <asm/setup.h>
74 74
75
76#ifdef CONFIG_ARC_HAS_ICACHE
77static void __ic_line_inv_no_alias(unsigned long, int);
78static void __ic_line_inv_2_alias(unsigned long, int);
79static void __ic_line_inv_4_alias(unsigned long, int);
80
81/* Holds the ptr to flush routine, dependign on size due to aliasing issues */
82static void (*___flush_icache_rtn) (unsigned long, int);
83#endif
84
85char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) 75char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len)
86{ 76{
87 int n = 0; 77 int n = 0;
@@ -109,7 +99,7 @@ char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len)
109 * the cpuinfo structure for later use. 99 * the cpuinfo structure for later use.
110 * No Validation done here, simply read/convert the BCRs 100 * No Validation done here, simply read/convert the BCRs
111 */ 101 */
112void __init read_decode_cache_bcr(void) 102void __cpuinit read_decode_cache_bcr(void)
113{ 103{
114 struct bcr_cache ibcr, dbcr; 104 struct bcr_cache ibcr, dbcr;
115 struct cpuinfo_arc_cache *p_ic, *p_dc; 105 struct cpuinfo_arc_cache *p_ic, *p_dc;
@@ -141,7 +131,7 @@ void __init read_decode_cache_bcr(void)
141 * 3. Enable the Caches, setup default flush mode for D-Cache 131 * 3. Enable the Caches, setup default flush mode for D-Cache
142 * 3. Calculate the SHMLBA used by user space 132 * 3. Calculate the SHMLBA used by user space
143 */ 133 */
144void __init arc_cache_init(void) 134void __cpuinit arc_cache_init(void)
145{ 135{
146 unsigned int temp; 136 unsigned int temp;
147 unsigned int cpu = smp_processor_id(); 137 unsigned int cpu = smp_processor_id();
@@ -171,30 +161,6 @@ void __init arc_cache_init(void)
171 161
172 } 162 }
173#endif 163#endif
174
175 /*
176 * if Cache way size is <= page size then no aliasing exhibited
177 * otherwise ratio determines num of aliases.
178 * e.g. 32K I$, 2 way set assoc, 8k pg size
179 * way-sz = 32k/2 = 16k
180 * way-pg-ratio = 16k/8k = 2, so 2 aliases possible
181 * (meaning 1 line could be in 2 possible locations).
182 */
183 way_pg_ratio = ic->sz / ARC_ICACHE_WAYS / PAGE_SIZE;
184 switch (way_pg_ratio) {
185 case 0:
186 case 1:
187 ___flush_icache_rtn = __ic_line_inv_no_alias;
188 break;
189 case 2:
190 ___flush_icache_rtn = __ic_line_inv_2_alias;
191 break;
192 case 4:
193 ___flush_icache_rtn = __ic_line_inv_4_alias;
194 break;
195 default:
196 panic("Unsupported I-Cache Sz\n");
197 }
198#endif 164#endif
199 165
200 /* Enable/disable I-Cache */ 166 /* Enable/disable I-Cache */
@@ -391,75 +357,38 @@ static inline void __dc_line_op(unsigned long start, unsigned long sz,
391/* 357/*
392 * I-Cache Aliasing in ARC700 VIPT caches 358 * I-Cache Aliasing in ARC700 VIPT caches
393 * 359 *
394 * For fetching code from I$, ARC700 uses vaddr (embedded in program code) 360 * ARC VIPT I-cache uses vaddr to index into cache and paddr to match the tag.
395 * to "index" into SET of cache-line and paddr from MMU to match the TAG 361 * The orig Cache Management Module "CDU" only required paddr to invalidate a
396 * in the WAYS of SET. 362 * certain line since it sufficed as index in Non-Aliasing VIPT cache-geometry.
363 * Infact for distinct V1,V2,P: all of {V1-P},{V2-P},{P-P} would end up fetching
364 * the exact same line.
397 * 365 *
398 * However the CDU iterface (to flush/inv) lines from software, only takes 366 * However for larger Caches (way-size > page-size) - i.e. in Aliasing config,
399 * paddr (to have simpler hardware interface). For simpler cases, using paddr 367 * paddr alone could not be used to correctly index the cache.
400 * alone suffices.
401 * e.g. 2-way-set-assoc, 16K I$ (8k MMU pg sz, 32b cache line size):
402 * way_sz = cache_sz / num_ways = 16k/2 = 8k
403 * num_sets = way_sz / line_sz = 8k/32 = 256 => 8 bits
404 * Ignoring the bottom 5 bits corresp to the off within a 32b cacheline,
405 * bits req for calc set-index = bits 12:5 (0 based). Since this range fits
406 * inside the bottom 13 bits of paddr, which are same for vaddr and paddr
407 * (with 8k pg sz), paddr alone can be safely used by CDU to unambigously
408 * locate a cache-line.
409 *
410 * However for a difft sized cache, say 32k I$, above math yields need
411 * for 14 bits of vaddr to locate a cache line, which can't be provided by
412 * paddr, since the bit 13 (0 based) might differ between the two.
413 *
414 * This lack of extra bits needed for correct line addressing, defines the
415 * classical problem of Cache aliasing with VIPT architectures
416 * num_aliases = 1 << extra_bits
417 * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz => 2 aliases
418 * 2-way-set-assoc, 64K I$ with 8k MMU pg sz => 4 aliases
419 * 2-way-set-assoc, 16K I$ with 8k MMU pg sz => NO aliases
420 * 368 *
421 * ------------------ 369 * ------------------
422 * MMU v1/v2 (Fixed Page Size 8k) 370 * MMU v1/v2 (Fixed Page Size 8k)
423 * ------------------ 371 * ------------------
424 * The solution was to provide CDU with these additonal vaddr bits. These 372 * The solution was to provide CDU with these additonal vaddr bits. These
425 * would be bits [x:13], x would depend on cache-geom. 373 * would be bits [x:13], x would depend on cache-geometry, 13 comes from
374 * standard page size of 8k.
426 * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits 375 * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits
427 * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the 376 * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the
428 * orig 5 bits of paddr were anyways ignored by CDU line ops, as they 377 * orig 5 bits of paddr were anyways ignored by CDU line ops, as they
429 * represent the offset within cache-line. The adv of using this "clumsy" 378 * represent the offset within cache-line. The adv of using this "clumsy"
430 * interface for additional info was no new reg was needed in CDU. 379 * interface for additional info was no new reg was needed in CDU programming
380 * model.
431 * 381 *
432 * 17:13 represented the max num of bits passable, actual bits needed were 382 * 17:13 represented the max num of bits passable, actual bits needed were
433 * fewer, based on the num-of-aliases possible. 383 * fewer, based on the num-of-aliases possible.
434 * -for 2 alias possibility, only bit 13 needed (32K cache) 384 * -for 2 alias possibility, only bit 13 needed (32K cache)
435 * -for 4 alias possibility, bits 14:13 needed (64K cache) 385 * -for 4 alias possibility, bits 14:13 needed (64K cache)
436 * 386 *
437 * Since vaddr was not available for all instances of I$ flush req by core
438 * kernel, the only safe way (non-optimal though) was to kill all possible
439 * lines which could represent an alias (even if they didnt represent one
440 * in execution).
441 * e.g. for 64K I$, 4 aliases possible, so we did
442 * flush start
443 * flush start | 0x01
444 * flush start | 0x2
445 * flush start | 0x3
446 *
447 * The penalty was invoking the operation itself, since tag match is anyways
448 * paddr based, a line which didn't represent an alias would not match the
449 * paddr, hence wont be killed
450 *
451 * Note that aliasing concerns are independent of line-sz for a given cache
452 * geometry (size + set_assoc) because the extra bits required by line-sz are
453 * reduced from the set calc.
454 * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz and using math above
455 * 32b line-sz: 9 bits set-index-calc, 5 bits offset-in-line => 1 extra bit
456 * 64b line-sz: 8 bits set-index-calc, 6 bits offset-in-line => 1 extra bit
457 *
458 * ------------------ 387 * ------------------
459 * MMU v3 388 * MMU v3
460 * ------------------ 389 * ------------------
461 * This ver of MMU supports var page sizes (1k-16k) - Linux will support 390 * This ver of MMU supports variable page sizes (1k-16k): although Linux will
462 * 8k (default), 16k and 4k. 391 * only support 8k (default), 16k and 4k.
463 * However from hardware perspective, smaller page sizes aggrevate aliasing 392 * However from hardware perspective, smaller page sizes aggrevate aliasing
464 * meaning more vaddr bits needed to disambiguate the cache-line-op ; 393 * meaning more vaddr bits needed to disambiguate the cache-line-op ;
465 * the existing scheme of piggybacking won't work for certain configurations. 394 * the existing scheme of piggybacking won't work for certain configurations.
@@ -468,115 +397,29 @@ static inline void __dc_line_op(unsigned long start, unsigned long sz,
468 */ 397 */
469 398
470/*********************************************************** 399/***********************************************************
471 * Machine specific helpers for per line I-Cache invalidate. 400 * Machine specific helper for per line I-Cache invalidate.
472 * 3 routines to accpunt for 1, 2, 4 aliases possible
473 */ 401 */
474 402static void __ic_line_inv_vaddr(unsigned long phy_start, unsigned long vaddr,
475static void __ic_line_inv_no_alias(unsigned long start, int num_lines) 403 unsigned long sz)
476{
477 while (num_lines-- > 0) {
478#if (CONFIG_ARC_MMU_VER > 2)
479 write_aux_reg(ARC_REG_IC_PTAG, start);
480#endif
481 write_aux_reg(ARC_REG_IC_IVIL, start);
482 start += ARC_ICACHE_LINE_LEN;
483 }
484}
485
486static void __ic_line_inv_2_alias(unsigned long start, int num_lines)
487{
488 while (num_lines-- > 0) {
489
490#if (CONFIG_ARC_MMU_VER > 2)
491 /*
492 * MMU v3, CDU prog model (for line ops) now uses a new IC_PTAG
493 * reg to pass the "tag" bits and existing IVIL reg only looks
494 * at bits relevant for "index" (details above)
495 * Programming Notes:
496 * -when writing tag to PTAG reg, bit chopping can be avoided,
497 * CDU ignores non-tag bits.
498 * -Ideally "index" must be computed from vaddr, but it is not
499 * avail in these rtns. So to be safe, we kill the lines in all
500 * possible indexes corresp to num of aliases possible for
501 * given cache config.
502 */
503 write_aux_reg(ARC_REG_IC_PTAG, start);
504 write_aux_reg(ARC_REG_IC_IVIL,
505 start & ~(0x1 << PAGE_SHIFT));
506 write_aux_reg(ARC_REG_IC_IVIL, start | (0x1 << PAGE_SHIFT));
507#else
508 write_aux_reg(ARC_REG_IC_IVIL, start);
509 write_aux_reg(ARC_REG_IC_IVIL, start | 0x01);
510#endif
511 start += ARC_ICACHE_LINE_LEN;
512 }
513}
514
515static void __ic_line_inv_4_alias(unsigned long start, int num_lines)
516{
517 while (num_lines-- > 0) {
518
519#if (CONFIG_ARC_MMU_VER > 2)
520 write_aux_reg(ARC_REG_IC_PTAG, start);
521
522 write_aux_reg(ARC_REG_IC_IVIL,
523 start & ~(0x3 << PAGE_SHIFT));
524 write_aux_reg(ARC_REG_IC_IVIL,
525 start & ~(0x2 << PAGE_SHIFT));
526 write_aux_reg(ARC_REG_IC_IVIL,
527 start & ~(0x1 << PAGE_SHIFT));
528 write_aux_reg(ARC_REG_IC_IVIL, start | (0x3 << PAGE_SHIFT));
529#else
530 write_aux_reg(ARC_REG_IC_IVIL, start);
531 write_aux_reg(ARC_REG_IC_IVIL, start | 0x01);
532 write_aux_reg(ARC_REG_IC_IVIL, start | 0x02);
533 write_aux_reg(ARC_REG_IC_IVIL, start | 0x03);
534#endif
535 start += ARC_ICACHE_LINE_LEN;
536 }
537}
538
539static void __ic_line_inv(unsigned long start, unsigned long sz)
540{ 404{
541 unsigned long flags; 405 unsigned long flags;
542 int num_lines, slack; 406 int num_lines, slack;
407 unsigned int addr;
543 408
544 /* 409 /*
545 * Ensure we properly floor/ceil the non-line aligned/sized requests 410 * Ensure we properly floor/ceil the non-line aligned/sized requests:
546 * and have @start - aligned to cache line, and integral @num_lines
547 * However page sized flushes can be compile time optimised. 411 * However page sized flushes can be compile time optimised.
548 * -@start will be cache-line aligned already (being page aligned) 412 * -@phy_start will be cache-line aligned already (being page aligned)
549 * -@sz will be integral multiple of line size (being page sized). 413 * -@sz will be integral multiple of line size (being page sized).
550 */ 414 */
551 if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) { 415 if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
552 slack = start & ~ICACHE_LINE_MASK; 416 slack = phy_start & ~ICACHE_LINE_MASK;
553 sz += slack; 417 sz += slack;
554 start -= slack; 418 phy_start -= slack;
555 } 419 }
556 420
557 num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN); 421 num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN);
558 422
559 local_irq_save(flags);
560 (*___flush_icache_rtn) (start, num_lines);
561 local_irq_restore(flags);
562}
563
564/* Unlike routines above, having vaddr for flush op (along with paddr),
565 * prevents the need to speculatively kill the lines in multiple sets
566 * based on ratio of way_sz : pg_sz
567 */
568static void __ic_line_inv_vaddr(unsigned long phy_start,
569 unsigned long vaddr, unsigned long sz)
570{
571 unsigned long flags;
572 int num_lines, slack;
573 unsigned int addr;
574
575 slack = phy_start & ~ICACHE_LINE_MASK;
576 sz += slack;
577 phy_start -= slack;
578 num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN);
579
580#if (CONFIG_ARC_MMU_VER > 2) 423#if (CONFIG_ARC_MMU_VER > 2)
581 vaddr &= ~ICACHE_LINE_MASK; 424 vaddr &= ~ICACHE_LINE_MASK;
582 addr = phy_start; 425 addr = phy_start;
@@ -595,7 +438,7 @@ static void __ic_line_inv_vaddr(unsigned long phy_start,
595 write_aux_reg(ARC_REG_IC_IVIL, vaddr); 438 write_aux_reg(ARC_REG_IC_IVIL, vaddr);
596 vaddr += ARC_ICACHE_LINE_LEN; 439 vaddr += ARC_ICACHE_LINE_LEN;
597#else 440#else
598 /* this paddr contains vaddrs bits as needed */ 441 /* paddr contains stuffed vaddrs bits */
599 write_aux_reg(ARC_REG_IC_IVIL, addr); 442 write_aux_reg(ARC_REG_IC_IVIL, addr);
600#endif 443#endif
601 addr += ARC_ICACHE_LINE_LEN; 444 addr += ARC_ICACHE_LINE_LEN;
@@ -605,7 +448,6 @@ static void __ic_line_inv_vaddr(unsigned long phy_start,
605 448
606#else 449#else
607 450
608#define __ic_line_inv(start, sz)
609#define __ic_line_inv_vaddr(pstart, vstart, sz) 451#define __ic_line_inv_vaddr(pstart, vstart, sz)
610 452
611#endif /* CONFIG_ARC_HAS_ICACHE */ 453#endif /* CONFIG_ARC_HAS_ICACHE */
@@ -615,10 +457,10 @@ static void __ic_line_inv_vaddr(unsigned long phy_start,
615 * Exported APIs 457 * Exported APIs
616 */ 458 */
617 459
618/* TBD: use pg_arch_1 to optimize this */
619void flush_dcache_page(struct page *page) 460void flush_dcache_page(struct page *page)
620{ 461{
621 __dc_line_op((unsigned long)page_address(page), PAGE_SIZE, OP_FLUSH); 462 /* Make a note that dcache is not yet flushed for this page */
463 set_bit(PG_arch_1, &page->flags);
622} 464}
623EXPORT_SYMBOL(flush_dcache_page); 465EXPORT_SYMBOL(flush_dcache_page);
624 466
@@ -642,8 +484,8 @@ void dma_cache_wback(unsigned long start, unsigned long sz)
642EXPORT_SYMBOL(dma_cache_wback); 484EXPORT_SYMBOL(dma_cache_wback);
643 485
644/* 486/*
645 * This is API for making I/D Caches consistent when modifying code 487 * This is API for making I/D Caches consistent when modifying
646 * (loadable modules, kprobes, etc) 488 * kernel code (loadable modules, kprobes, kgdb...)
647 * This is called on insmod, with kernel virtual address for CODE of 489 * This is called on insmod, with kernel virtual address for CODE of
648 * the module. ARC cache maintenance ops require PHY address thus we 490 * the module. ARC cache maintenance ops require PHY address thus we
649 * need to convert vmalloc addr to PHY addr 491 * need to convert vmalloc addr to PHY addr
@@ -652,7 +494,6 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
652{ 494{
653 unsigned int tot_sz, off, sz; 495 unsigned int tot_sz, off, sz;
654 unsigned long phy, pfn; 496 unsigned long phy, pfn;
655 unsigned long flags;
656 497
657 /* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */ 498 /* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
658 499
@@ -673,8 +514,13 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
673 514
674 /* Case: Kernel Phy addr (0x8000_0000 onwards) */ 515 /* Case: Kernel Phy addr (0x8000_0000 onwards) */
675 if (likely(kstart > PAGE_OFFSET)) { 516 if (likely(kstart > PAGE_OFFSET)) {
676 __ic_line_inv(kstart, kend - kstart); 517 /*
677 __dc_line_op(kstart, kend - kstart, OP_FLUSH); 518 * The 2nd arg despite being paddr will be used to index icache
519 * This is OK since no alternate virtual mappings will exist
520 * given the callers for this case: kprobe/kgdb in built-in
521 * kernel code only.
522 */
523 __sync_icache_dcache(kstart, kstart, kend - kstart);
678 return; 524 return;
679 } 525 }
680 526
@@ -692,42 +538,41 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
692 pfn = vmalloc_to_pfn((void *)kstart); 538 pfn = vmalloc_to_pfn((void *)kstart);
693 phy = (pfn << PAGE_SHIFT) + off; 539 phy = (pfn << PAGE_SHIFT) + off;
694 sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off); 540 sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off);
695 local_irq_save(flags); 541 __sync_icache_dcache(phy, kstart, sz);
696 __dc_line_op(phy, sz, OP_FLUSH);
697 __ic_line_inv(phy, sz);
698 local_irq_restore(flags);
699 kstart += sz; 542 kstart += sz;
700 tot_sz -= sz; 543 tot_sz -= sz;
701 } 544 }
702} 545}
703 546
704/* 547/*
705 * Optimised ver of flush_icache_range() with spec callers: ptrace/signals 548 * General purpose helper to make I and D cache lines consistent.
706 * where vaddr is also available. This allows passing both vaddr and paddr 549 * @paddr is phy addr of region
707 * bits to CDU for cache flush, short-circuting the current pessimistic algo 550 * @vaddr is typically user or kernel vaddr (vmalloc)
708 * which kills all possible aliases. 551 * Howver in one instance, flush_icache_range() by kprobe (for a breakpt in
709 * An added adv of knowing that vaddr is user-vaddr avoids various checks 552 * builtin kernel code) @vaddr will be paddr only, meaning CDU operation will
710 * and handling for k-vaddr, k-paddr as done in orig ver above 553 * use a paddr to index the cache (despite VIPT). This is fine since since a
554 * built-in kernel page will not have any virtual mappings (not even kernel)
555 * kprobe on loadable module is different as it will have kvaddr.
711 */ 556 */
712void flush_icache_range_vaddr(unsigned long paddr, unsigned long u_vaddr, 557void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len)
713 int len)
714{ 558{
715 __ic_line_inv_vaddr(paddr, u_vaddr, len); 559 unsigned long flags;
560
561 local_irq_save(flags);
562 __ic_line_inv_vaddr(paddr, vaddr, len);
716 __dc_line_op(paddr, len, OP_FLUSH); 563 __dc_line_op(paddr, len, OP_FLUSH);
564 local_irq_restore(flags);
717} 565}
718 566
719/* 567/* wrapper to compile time eliminate alignment checks in flush loop */
720 * XXX: This also needs to be optim using pg_arch_1 568void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
721 * This is called when a page-cache page is about to be mapped into a
722 * user process' address space. It offers an opportunity for a
723 * port to ensure d-cache/i-cache coherency if necessary.
724 */
725void flush_icache_page(struct vm_area_struct *vma, struct page *page)
726{ 569{
727 if (!(vma->vm_flags & VM_EXEC)) 570 __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE);
728 return; 571}
729 572
730 __ic_line_inv((unsigned long)page_address(page), PAGE_SIZE); 573void __flush_dcache_page(unsigned long paddr)
574{
575 __dc_line_op(paddr, PAGE_SIZE, OP_FLUSH_N_INV);
731} 576}
732 577
733void flush_icache_all(void) 578void flush_icache_all(void)