aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r--arch/sparc64/kernel/traps.c100
1 files changed, 47 insertions, 53 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index b280b2ef674f..5570e7bb22bb 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -189,19 +189,18 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un
189 189
190 if (regs->tstate & TSTATE_PRIV) { 190 if (regs->tstate & TSTATE_PRIV) {
191 /* Test if this comes from uaccess places. */ 191 /* Test if this comes from uaccess places. */
192 unsigned long fixup; 192 const struct exception_table_entry *entry;
193 unsigned long g2 = regs->u_regs[UREG_G2];
194 193
195 if ((fixup = search_extables_range(regs->tpc, &g2))) { 194 entry = search_exception_tables(regs->tpc);
196 /* Ouch, somebody is trying ugly VM hole tricks on us... */ 195 if (entry) {
196 /* Ouch, somebody is trying VM hole tricks on us... */
197#ifdef DEBUG_EXCEPTIONS 197#ifdef DEBUG_EXCEPTIONS
198 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); 198 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
199 printk("EX_TABLE: insn<%016lx> fixup<%016lx> " 199 printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
200 "g2<%016lx>\n", regs->tpc, fixup, g2); 200 regs->tpc, entry->fixup);
201#endif 201#endif
202 regs->tpc = fixup; 202 regs->tpc = entry->fixup;
203 regs->tnpc = regs->tpc + 4; 203 regs->tnpc = regs->tpc + 4;
204 regs->u_regs[UREG_G2] = g2;
205 return; 204 return;
206 } 205 }
207 /* Shit... */ 206 /* Shit... */
@@ -758,26 +757,12 @@ void __init cheetah_ecache_flush_init(void)
758 ecache_flush_size = (2 * largest_size); 757 ecache_flush_size = (2 * largest_size);
759 ecache_flush_linesize = smallest_linesize; 758 ecache_flush_linesize = smallest_linesize;
760 759
761 /* Discover a physically contiguous chunk of physical 760 ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size);
762 * memory in 'sp_banks' of size ecache_flush_size calculated
763 * above. Store the physical base of this area at
764 * ecache_flush_physbase.
765 */
766 for (node = 0; ; node++) {
767 if (sp_banks[node].num_bytes == 0)
768 break;
769 if (sp_banks[node].num_bytes >= ecache_flush_size) {
770 ecache_flush_physbase = sp_banks[node].base_addr;
771 break;
772 }
773 }
774 761
775 /* Note: Zero would be a valid value of ecache_flush_physbase so 762 if (ecache_flush_physbase == ~0UL) {
776 * don't use that as the success test. :-)
777 */
778 if (sp_banks[node].num_bytes == 0) {
779 prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " 763 prom_printf("cheetah_ecache_flush_init: Cannot find %d byte "
780 "contiguous physical memory.\n", ecache_flush_size); 764 "contiguous physical memory.\n",
765 ecache_flush_size);
781 prom_halt(); 766 prom_halt();
782 } 767 }
783 768
@@ -869,14 +854,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr)
869 */ 854 */
870static void __cheetah_flush_icache(void) 855static void __cheetah_flush_icache(void)
871{ 856{
872 unsigned long i; 857 unsigned int icache_size, icache_line_size;
858 unsigned long addr;
859
860 icache_size = local_cpu_data().icache_size;
861 icache_line_size = local_cpu_data().icache_line_size;
873 862
874 /* Clear the valid bits in all the tags. */ 863 /* Clear the valid bits in all the tags. */
875 for (i = 0; i < (1 << 15); i += (1 << 5)) { 864 for (addr = 0; addr < icache_size; addr += icache_line_size) {
876 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" 865 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
877 "membar #Sync" 866 "membar #Sync"
878 : /* no outputs */ 867 : /* no outputs */
879 : "r" (i | (2 << 3)), "i" (ASI_IC_TAG)); 868 : "r" (addr | (2 << 3)),
869 "i" (ASI_IC_TAG));
880 } 870 }
881} 871}
882 872
@@ -904,13 +894,17 @@ static void cheetah_flush_icache(void)
904 894
905static void cheetah_flush_dcache(void) 895static void cheetah_flush_dcache(void)
906{ 896{
907 unsigned long i; 897 unsigned int dcache_size, dcache_line_size;
898 unsigned long addr;
908 899
909 for (i = 0; i < (1 << 16); i += (1 << 5)) { 900 dcache_size = local_cpu_data().dcache_size;
901 dcache_line_size = local_cpu_data().dcache_line_size;
902
903 for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
910 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" 904 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
911 "membar #Sync" 905 "membar #Sync"
912 : /* no outputs */ 906 : /* no outputs */
913 : "r" (i), "i" (ASI_DCACHE_TAG)); 907 : "r" (addr), "i" (ASI_DCACHE_TAG));
914 } 908 }
915} 909}
916 910
@@ -921,24 +915,29 @@ static void cheetah_flush_dcache(void)
921 */ 915 */
922static void cheetah_plus_zap_dcache_parity(void) 916static void cheetah_plus_zap_dcache_parity(void)
923{ 917{
924 unsigned long i; 918 unsigned int dcache_size, dcache_line_size;
919 unsigned long addr;
920
921 dcache_size = local_cpu_data().dcache_size;
922 dcache_line_size = local_cpu_data().dcache_line_size;
925 923
926 for (i = 0; i < (1 << 16); i += (1 << 5)) { 924 for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
927 unsigned long tag = (i >> 14); 925 unsigned long tag = (addr >> 14);
928 unsigned long j; 926 unsigned long line;
929 927
930 __asm__ __volatile__("membar #Sync\n\t" 928 __asm__ __volatile__("membar #Sync\n\t"
931 "stxa %0, [%1] %2\n\t" 929 "stxa %0, [%1] %2\n\t"
932 "membar #Sync" 930 "membar #Sync"
933 : /* no outputs */ 931 : /* no outputs */
934 : "r" (tag), "r" (i), 932 : "r" (tag), "r" (addr),
935 "i" (ASI_DCACHE_UTAG)); 933 "i" (ASI_DCACHE_UTAG));
936 for (j = i; j < i + (1 << 5); j += (1 << 3)) 934 for (line = addr; line < addr + dcache_line_size; line += 8)
937 __asm__ __volatile__("membar #Sync\n\t" 935 __asm__ __volatile__("membar #Sync\n\t"
938 "stxa %%g0, [%0] %1\n\t" 936 "stxa %%g0, [%0] %1\n\t"
939 "membar #Sync" 937 "membar #Sync"
940 : /* no outputs */ 938 : /* no outputs */
941 : "r" (j), "i" (ASI_DCACHE_DATA)); 939 : "r" (line),
940 "i" (ASI_DCACHE_DATA));
942 } 941 }
943} 942}
944 943
@@ -1332,16 +1331,12 @@ static int cheetah_fix_ce(unsigned long physaddr)
1332/* Return non-zero if PADDR is a valid physical memory address. */ 1331/* Return non-zero if PADDR is a valid physical memory address. */
1333static int cheetah_check_main_memory(unsigned long paddr) 1332static int cheetah_check_main_memory(unsigned long paddr)
1334{ 1333{
1335 int i; 1334 unsigned long vaddr = PAGE_OFFSET + paddr;
1336 1335
1337 for (i = 0; ; i++) { 1336 if (vaddr > (unsigned long) high_memory)
1338 if (sp_banks[i].num_bytes == 0) 1337 return 0;
1339 break; 1338
1340 if (paddr >= sp_banks[i].base_addr && 1339 return kern_addr_valid(vaddr);
1341 paddr < (sp_banks[i].base_addr + sp_banks[i].num_bytes))
1342 return 1;
1343 }
1344 return 0;
1345} 1340}
1346 1341
1347void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) 1342void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
@@ -1596,10 +1591,10 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
1596 /* OK, usermode access. */ 1591 /* OK, usermode access. */
1597 recoverable = 1; 1592 recoverable = 1;
1598 } else { 1593 } else {
1599 unsigned long g2 = regs->u_regs[UREG_G2]; 1594 const struct exception_table_entry *entry;
1600 unsigned long fixup = search_extables_range(regs->tpc, &g2);
1601 1595
1602 if (fixup != 0UL) { 1596 entry = search_exception_tables(regs->tpc);
1597 if (entry) {
1603 /* OK, kernel access to userspace. */ 1598 /* OK, kernel access to userspace. */
1604 recoverable = 1; 1599 recoverable = 1;
1605 1600
@@ -1618,9 +1613,8 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
1618 * recoverable condition. 1613 * recoverable condition.
1619 */ 1614 */
1620 if (recoverable) { 1615 if (recoverable) {
1621 regs->tpc = fixup; 1616 regs->tpc = entry->fixup;
1622 regs->tnpc = regs->tpc + 4; 1617 regs->tnpc = regs->tpc + 4;
1623 regs->u_regs[UREG_G2] = g2;
1624 } 1618 }
1625 } 1619 }
1626 } 1620 }