diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2005-09-26 00:32:17 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-09-26 00:32:17 -0700 |
commit | 80dc0d6b44ce0f01df58d8899e46612690ed7d81 (patch) | |
tree | 570b8e834c0fae0793bdf75dd2fd2516b0fabf4f /arch/sparc64/kernel/traps.c | |
parent | 56425306517ef28a9b480161cdb96d182172bc1d (diff) |
[SPARC64]: Probe D/I/E-cache config and use.
At boot time, determine the D-cache, I-cache and E-cache size and
line-size. Use them in cache flushes when appropriate.
This change was motivated by discovering that the D-cache on
UltraSparc-IIIi and later are 64K not 32K, and the flushes done by the
Cheetah error handlers were assuming a 32K size.
There are still some pieces of code that are hard coding things and
will need to be fixed up at some point.
While we're here, fix the D-cache and I-cache parity error handlers
to run with interrupts disabled, and when the trap occurs at trap
level > 1 log the event via a counter displayed in /proc/cpuinfo.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r-- | arch/sparc64/kernel/traps.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index b280b2ef674f..f8e7005fede9 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -869,14 +869,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr) */ static void __cheetah_flush_icache(void) { - unsigned long i; + unsigned int icache_size, icache_line_size; + unsigned long addr; + + icache_size = local_cpu_data().icache_size; + icache_line_size = local_cpu_data().icache_line_size; /* Clear the valid bits in all the tags. */ - for (i = 0; i < (1 << 15); i += (1 << 5)) { + for (addr = 0; addr < icache_size; addr += icache_line_size) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ - : "r" (i | (2 << 3)), "i" (ASI_IC_TAG)); + : "r" (addr | (2 << 3)), + "i" (ASI_IC_TAG)); } } @@ -904,13 +909,17 @@ static void cheetah_flush_icache(void) static void cheetah_flush_dcache(void) { - unsigned long i; + unsigned int dcache_size, dcache_line_size; + unsigned long addr; + + dcache_size = local_cpu_data().dcache_size; + dcache_line_size = local_cpu_data().dcache_line_size; - for (i = 0; i < (1 << 16); i += (1 << 5)) { + for (addr = 0; addr < dcache_size; addr += dcache_line_size) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ - : "r" (i), "i" (ASI_DCACHE_TAG)); + : "r" (addr), "i" (ASI_DCACHE_TAG)); } } @@ -921,24 +930,29 @@ static void cheetah_flush_dcache(void) */ static void cheetah_plus_zap_dcache_parity(void) { - unsigned long i; + unsigned int dcache_size, dcache_line_size; + unsigned long addr; + + dcache_size = local_cpu_data().dcache_size; + dcache_line_size = local_cpu_data().dcache_line_size; - for (i = 0; i < (1 << 16); i += (1 << 5)) { - unsigned long tag = (i >> 14); - unsigned long j; + for (addr = 0; addr < dcache_size; addr += dcache_line_size) { + unsigned long tag = (addr >> 14); + unsigned long line; __asm__ __volatile__("membar #Sync\n\t" "stxa %0, [%1] %2\n\t" "membar #Sync" : /* no outputs */ - : "r" (tag), "r" (i), + : "r" (tag), "r" (addr), "i" (ASI_DCACHE_UTAG)); - for (j = i; j < i + (1 << 5); j += (1 << 3)) + for (line = addr; line < addr + dcache_line_size; line += 8) __asm__ __volatile__("membar #Sync\n\t" "stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ - : "r" (j), "i" (ASI_DCACHE_DATA)); + : "r" (line), + "i" (ASI_DCACHE_DATA)); } } |