diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2005-09-26 03:32:17 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-09-26 03:32:17 -0400 |
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 b280b2ef674..f8e7005fede 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) | |||
869 | */ | 869 | */ |
870 | static void __cheetah_flush_icache(void) | 870 | static void __cheetah_flush_icache(void) |
871 | { | 871 | { |
872 | unsigned long i; | 872 | unsigned int icache_size, icache_line_size; |
873 | unsigned long addr; | ||
874 | |||
875 | icache_size = local_cpu_data().icache_size; | ||
876 | icache_line_size = local_cpu_data().icache_line_size; | ||
873 | 877 | ||
874 | /* Clear the valid bits in all the tags. */ | 878 | /* Clear the valid bits in all the tags. */ |
875 | for (i = 0; i < (1 << 15); i += (1 << 5)) { | 879 | for (addr = 0; addr < icache_size; addr += icache_line_size) { |
876 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" | 880 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" |
877 | "membar #Sync" | 881 | "membar #Sync" |
878 | : /* no outputs */ | 882 | : /* no outputs */ |
879 | : "r" (i | (2 << 3)), "i" (ASI_IC_TAG)); | 883 | : "r" (addr | (2 << 3)), |
884 | "i" (ASI_IC_TAG)); | ||
880 | } | 885 | } |
881 | } | 886 | } |
882 | 887 | ||
@@ -904,13 +909,17 @@ static void cheetah_flush_icache(void) | |||
904 | 909 | ||
905 | static void cheetah_flush_dcache(void) | 910 | static void cheetah_flush_dcache(void) |
906 | { | 911 | { |
907 | unsigned long i; | 912 | unsigned int dcache_size, dcache_line_size; |
913 | unsigned long addr; | ||
914 | |||
915 | dcache_size = local_cpu_data().dcache_size; | ||
916 | dcache_line_size = local_cpu_data().dcache_line_size; | ||
908 | 917 | ||
909 | for (i = 0; i < (1 << 16); i += (1 << 5)) { | 918 | for (addr = 0; addr < dcache_size; addr += dcache_line_size) { |
910 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" | 919 | __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" |
911 | "membar #Sync" | 920 | "membar #Sync" |
912 | : /* no outputs */ | 921 | : /* no outputs */ |
913 | : "r" (i), "i" (ASI_DCACHE_TAG)); | 922 | : "r" (addr), "i" (ASI_DCACHE_TAG)); |
914 | } | 923 | } |
915 | } | 924 | } |
916 | 925 | ||
@@ -921,24 +930,29 @@ static void cheetah_flush_dcache(void) | |||
921 | */ | 930 | */ |
922 | static void cheetah_plus_zap_dcache_parity(void) | 931 | static void cheetah_plus_zap_dcache_parity(void) |
923 | { | 932 | { |
924 | unsigned long i; | 933 | unsigned int dcache_size, dcache_line_size; |
934 | unsigned long addr; | ||
935 | |||
936 | dcache_size = local_cpu_data().dcache_size; | ||
937 | dcache_line_size = local_cpu_data().dcache_line_size; | ||
925 | 938 | ||
926 | for (i = 0; i < (1 << 16); i += (1 << 5)) { | 939 | for (addr = 0; addr < dcache_size; addr += dcache_line_size) { |
927 | unsigned long tag = (i >> 14); | 940 | unsigned long tag = (addr >> 14); |
928 | unsigned long j; | 941 | unsigned long line; |
929 | 942 | ||
930 | __asm__ __volatile__("membar #Sync\n\t" | 943 | __asm__ __volatile__("membar #Sync\n\t" |
931 | "stxa %0, [%1] %2\n\t" | 944 | "stxa %0, [%1] %2\n\t" |
932 | "membar #Sync" | 945 | "membar #Sync" |
933 | : /* no outputs */ | 946 | : /* no outputs */ |
934 | : "r" (tag), "r" (i), | 947 | : "r" (tag), "r" (addr), |
935 | "i" (ASI_DCACHE_UTAG)); | 948 | "i" (ASI_DCACHE_UTAG)); |
936 | for (j = i; j < i + (1 << 5); j += (1 << 3)) | 949 | for (line = addr; line < addr + dcache_line_size; line += 8) |
937 | __asm__ __volatile__("membar #Sync\n\t" | 950 | __asm__ __volatile__("membar #Sync\n\t" |
938 | "stxa %%g0, [%0] %1\n\t" | 951 | "stxa %%g0, [%0] %1\n\t" |
939 | "membar #Sync" | 952 | "membar #Sync" |
940 | : /* no outputs */ | 953 | : /* no outputs */ |
941 | : "r" (j), "i" (ASI_DCACHE_DATA)); | 954 | : "r" (line), |
955 | "i" (ASI_DCACHE_DATA)); | ||
942 | } | 956 | } |
943 | } | 957 | } |
944 | 958 | ||