summaryrefslogtreecommitdiff
path: root/arch/sparc64/kernel/traps.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-09-26 00:32:17 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2005-09-26 00:32:17 -0700
commit80dc0d6b44ce0f01df58d8899e46612690ed7d81 (patch)
tree570b8e834c0fae0793bdf75dd2fd2516b0fabf4f /arch/sparc64/kernel/traps.c
parent56425306517ef28a9b480161cdb96d182172bc1d (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.c40
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));
}
}