aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/entry.S266
-rw-r--r--arch/sparc64/kernel/traps.c264
-rw-r--r--arch/sparc64/kernel/ttable.S27
-rw-r--r--arch/sparc64/kernel/unaligned.c18
-rw-r--r--arch/sparc64/kernel/winfixup.S6
5 files changed, 336 insertions, 245 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 214cd0ebe832..cecdc0a7521f 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -21,6 +21,7 @@
21#include <asm/visasm.h> 21#include <asm/visasm.h>
22#include <asm/estate.h> 22#include <asm/estate.h>
23#include <asm/auxio.h> 23#include <asm/auxio.h>
24#include <asm/sfafsr.h>
24 25
25#define curptr g6 26#define curptr g6
26 27
@@ -690,9 +691,159 @@ netbsd_syscall:
690 retl 691 retl
691 nop 692 nop
692 693
693 .globl __do_data_access_exception 694 /* We need to carefully read the error status, ACK
694 .globl __do_data_access_exception_tl1 695 * the errors, prevent recursive traps, and pass the
695__do_data_access_exception_tl1: 696 * information on to C code for logging.
697 *
698 * We pass the AFAR in as-is, and we encode the status
699 * information as described in asm-sparc64/sfafsr.h
700 */
701 .globl __spitfire_access_error
702__spitfire_access_error:
703 /* Disable ESTATE error reporting so that we do not
704 * take recursive traps and RED state the processor.
705 */
706 stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
707 membar #Sync
708
709 mov UDBE_UE, %g1
710 ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
711
712 /* __spitfire_cee_trap branches here with AFSR in %g4 and
713 * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the
714 * ESTATE Error Enable register.
715 */
716__spitfire_cee_trap_continue:
717 ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
718
719 rdpr %tt, %g3
720 and %g3, 0x1ff, %g3 ! Paranoia
721 sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
722 or %g4, %g3, %g4
723 rdpr %tl, %g3
724 cmp %g3, 1
725 mov 1, %g3
726 bleu %xcc, 1f
727 sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
728
729 or %g4, %g3, %g4
730
731 /* Read in the UDB error register state, clearing the
732 * sticky error bits as-needed. We only clear them if
733 * the UE bit is set. Likewise, __spitfire_cee_trap
734 * below will only do so if the CE bit is set.
735 *
736 * NOTE: UltraSparc-I/II have high and low UDB error
737 * registers, corresponding to the two UDB units
738 * present on those chips. UltraSparc-IIi only
739 * has a single UDB, called "SDB" in the manual.
740 * For IIi the upper UDB register always reads
741 * as zero so for our purposes things will just
742 * work with the checks below.
743 */
7441: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
745 and %g3, 0x3ff, %g7 ! Paranoia
746 sllx %g7, SFSTAT_UDBH_SHIFT, %g7
747 or %g4, %g7, %g4
748 andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
749 be,pn %xcc, 1f
750 nop
751 stxa %g3, [%g0] ASI_UDB_ERROR_W
752 membar #Sync
753
7541: mov 0x18, %g3
755 ldxa [%g3] ASI_UDBL_ERROR_R, %g3
756 and %g3, 0x3ff, %g7 ! Paranoia
757 sllx %g7, SFSTAT_UDBL_SHIFT, %g7
758 or %g4, %g7, %g4
759 andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
760 be,pn %xcc, 1f
761 nop
762 mov 0x18, %g7
763 stxa %g3, [%g7] ASI_UDB_ERROR_W
764 membar #Sync
765
7661: /* Ok, now that we've latched the error state,
767 * clear the sticky bits in the AFSR.
768 */
769 stxa %g4, [%g0] ASI_AFSR
770 membar #Sync
771
772 rdpr %tl, %g2
773 cmp %g2, 1
774 rdpr %pil, %g2
775 bleu,pt %xcc, 1f
776 wrpr %g0, 15, %pil
777
778 ba,pt %xcc, etraptl1
779 rd %pc, %g7
780
781 ba,pt %xcc, 2f
782 nop
783
7841: ba,pt %xcc, etrap_irq
785 rd %pc, %g7
786
7872: mov %l4, %o1
788 mov %l5, %o2
789 call spitfire_access_error
790 add %sp, PTREGS_OFF, %o0
791 ba,pt %xcc, rtrap
792 clr %l6
793
794 /* This is the trap handler entry point for ECC correctable
795 * errors. They are corrected, but we listen for the trap
796 * so that the event can be logged.
797 *
798 * Disrupting errors are either:
799 * 1) single-bit ECC errors during UDB reads to system
800 * memory
801 * 2) data parity errors during write-back events
802 *
803 * As far as I can make out from the manual, the CEE trap
804 * is only for correctable errors during memory read
805 * accesses by the front-end of the processor.
806 *
807 * The code below is only for trap level 1 CEE events,
808 * as it is the only situation where we can safely record
809 * and log. For trap level >1 we just clear the CE bit
810 * in the AFSR and return.
811 *
812 * This is just like __spiftire_access_error above, but it
813 * specifically handles correctable errors. If an
814 * uncorrectable error is indicated in the AFSR we
815 * will branch directly above to __spitfire_access_error
816 * to handle it instead. Uncorrectable therefore takes
817 * priority over correctable, and the error logging
818 * C code will notice this case by inspecting the
819 * trap type.
820 */
821 .globl __spitfire_cee_trap
822__spitfire_cee_trap:
823 ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
824 mov 1, %g3
825 sllx %g3, SFAFSR_UE_SHIFT, %g3
826 andcc %g4, %g3, %g0 ! Check for UE
827 bne,pn %xcc, __spitfire_access_error
828 nop
829
830 /* Ok, in this case we only have a correctable error.
831 * Indicate we only wish to capture that state in register
832 * %g1, and we only disable CE error reporting unlike UE
833 * handling which disables all errors.
834 */
835 ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
836 andn %g3, ESTATE_ERR_CE, %g3
837 stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
838 membar #Sync
839
840 /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
841 ba,pt %xcc, __spitfire_cee_trap_continue
842 mov UDBE_CE, %g1
843
844 .globl __spitfire_data_access_exception
845 .globl __spitfire_data_access_exception_tl1
846__spitfire_data_access_exception_tl1:
696 rdpr %pstate, %g4 847 rdpr %pstate, %g4
697 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 848 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
698 mov TLB_SFSR, %g3 849 mov TLB_SFSR, %g3
@@ -714,12 +865,12 @@ __do_data_access_exception_tl1:
714109: or %g7, %lo(109b), %g7 865109: or %g7, %lo(109b), %g7
715 mov %l4, %o1 866 mov %l4, %o1
716 mov %l5, %o2 867 mov %l5, %o2
717 call data_access_exception_tl1 868 call spitfire_data_access_exception_tl1
718 add %sp, PTREGS_OFF, %o0 869 add %sp, PTREGS_OFF, %o0
719 ba,pt %xcc, rtrap 870 ba,pt %xcc, rtrap
720 clr %l6 871 clr %l6
721 872
722__do_data_access_exception: 873__spitfire_data_access_exception:
723 rdpr %pstate, %g4 874 rdpr %pstate, %g4
724 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 875 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
725 mov TLB_SFSR, %g3 876 mov TLB_SFSR, %g3
@@ -733,14 +884,14 @@ __do_data_access_exception:
733109: or %g7, %lo(109b), %g7 884109: or %g7, %lo(109b), %g7
734 mov %l4, %o1 885 mov %l4, %o1
735 mov %l5, %o2 886 mov %l5, %o2
736 call data_access_exception 887 call spitfire_data_access_exception
737 add %sp, PTREGS_OFF, %o0 888 add %sp, PTREGS_OFF, %o0
738 ba,pt %xcc, rtrap 889 ba,pt %xcc, rtrap
739 clr %l6 890 clr %l6
740 891
741 .globl __do_instruction_access_exception 892 .globl __spitfire_insn_access_exception
742 .globl __do_instruction_access_exception_tl1 893 .globl __spitfire_insn_access_exception_tl1
743__do_instruction_access_exception_tl1: 894__spitfire_insn_access_exception_tl1:
744 rdpr %pstate, %g4 895 rdpr %pstate, %g4
745 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 896 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
746 mov TLB_SFSR, %g3 897 mov TLB_SFSR, %g3
@@ -753,12 +904,12 @@ __do_instruction_access_exception_tl1:
753109: or %g7, %lo(109b), %g7 904109: or %g7, %lo(109b), %g7
754 mov %l4, %o1 905 mov %l4, %o1
755 mov %l5, %o2 906 mov %l5, %o2
756 call instruction_access_exception_tl1 907 call spitfire_insn_access_exception_tl1
757 add %sp, PTREGS_OFF, %o0 908 add %sp, PTREGS_OFF, %o0
758 ba,pt %xcc, rtrap 909 ba,pt %xcc, rtrap
759 clr %l6 910 clr %l6
760 911
761__do_instruction_access_exception: 912__spitfire_insn_access_exception:
762 rdpr %pstate, %g4 913 rdpr %pstate, %g4
763 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 914 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
764 mov TLB_SFSR, %g3 915 mov TLB_SFSR, %g3
@@ -771,102 +922,11 @@ __do_instruction_access_exception:
771109: or %g7, %lo(109b), %g7 922109: or %g7, %lo(109b), %g7
772 mov %l4, %o1 923 mov %l4, %o1
773 mov %l5, %o2 924 mov %l5, %o2
774 call instruction_access_exception 925 call spitfire_insn_access_exception
775 add %sp, PTREGS_OFF, %o0 926 add %sp, PTREGS_OFF, %o0
776 ba,pt %xcc, rtrap 927 ba,pt %xcc, rtrap
777 clr %l6 928 clr %l6
778 929
779 /* This is the trap handler entry point for ECC correctable
780 * errors. They are corrected, but we listen for the trap
781 * so that the event can be logged.
782 *
783 * Disrupting errors are either:
784 * 1) single-bit ECC errors during UDB reads to system
785 * memory
786 * 2) data parity errors during write-back events
787 *
788 * As far as I can make out from the manual, the CEE trap
789 * is only for correctable errors during memory read
790 * accesses by the front-end of the processor.
791 *
792 * The code below is only for trap level 1 CEE events,
793 * as it is the only situation where we can safely record
794 * and log. For trap level >1 we just clear the CE bit
795 * in the AFSR and return.
796 */
797
798 /* Our trap handling infrastructure allows us to preserve
799 * two 64-bit values during etrap for arguments to
800 * subsequent C code. Therefore we encode the information
801 * as follows:
802 *
803 * value 1) Full 64-bits of AFAR
804 * value 2) Low 33-bits of AFSR, then bits 33-->42
805 * are UDBL error status and bits 43-->52
806 * are UDBH error status
807 */
808 .align 64
809 .globl cee_trap
810cee_trap:
811 ldxa [%g0] ASI_AFSR, %g1 ! Read AFSR
812 ldxa [%g0] ASI_AFAR, %g2 ! Read AFAR
813 sllx %g1, 31, %g1 ! Clear reserved bits
814 srlx %g1, 31, %g1 ! in AFSR
815
816 /* NOTE: UltraSparc-I/II have high and low UDB error
817 * registers, corresponding to the two UDB units
818 * present on those chips. UltraSparc-IIi only
819 * has a single UDB, called "SDB" in the manual.
820 * For IIi the upper UDB register always reads
821 * as zero so for our purposes things will just
822 * work with the checks below.
823 */
824 ldxa [%g0] ASI_UDBL_ERROR_R, %g3 ! Read UDB-Low error status
825 andcc %g3, (1 << 8), %g4 ! Check CE bit
826 sllx %g3, (64 - 10), %g3 ! Clear reserved bits
827 srlx %g3, (64 - 10), %g3 ! in UDB-Low error status
828
829 sllx %g3, (33 + 0), %g3 ! Shift up to encoding area
830 or %g1, %g3, %g1 ! Or it in
831 be,pn %xcc, 1f ! Branch if CE bit was clear
832 nop
833 stxa %g4, [%g0] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBL
834 membar #Sync ! Synchronize ASI stores
8351: mov 0x18, %g5 ! Addr of UDB-High error status
836 ldxa [%g5] ASI_UDBH_ERROR_R, %g3 ! Read it
837
838 andcc %g3, (1 << 8), %g4 ! Check CE bit
839 sllx %g3, (64 - 10), %g3 ! Clear reserved bits
840 srlx %g3, (64 - 10), %g3 ! in UDB-High error status
841 sllx %g3, (33 + 10), %g3 ! Shift up to encoding area
842 or %g1, %g3, %g1 ! Or it in
843 be,pn %xcc, 1f ! Branch if CE bit was clear
844 nop
845 nop
846
847 stxa %g4, [%g5] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBH
848 membar #Sync ! Synchronize ASI stores
8491: mov 1, %g5 ! AFSR CE bit is
850 sllx %g5, 20, %g5 ! bit 20
851 stxa %g5, [%g0] ASI_AFSR ! Clear CE sticky bit in AFSR
852 membar #Sync ! Synchronize ASI stores
853 sllx %g2, (64 - 41), %g2 ! Clear reserved bits
854 srlx %g2, (64 - 41), %g2 ! in latched AFAR
855
856 andn %g2, 0x0f, %g2 ! Finish resv bit clearing
857 mov %g1, %g4 ! Move AFSR+UDB* into save reg
858 mov %g2, %g5 ! Move AFAR into save reg
859 rdpr %pil, %g2
860 wrpr %g0, 15, %pil
861 ba,pt %xcc, etrap_irq
862 rd %pc, %g7
863 mov %l4, %o0
864
865 mov %l5, %o1
866 call cee_log
867 add %sp, PTREGS_OFF, %o2
868 ba,a,pt %xcc, rtrap_irq
869
870 /* Capture I/D/E-cache state into per-cpu error scoreboard. 930 /* Capture I/D/E-cache state into per-cpu error scoreboard.
871 * 931 *
872 * %g1: (TL>=0) ? 1 : 0 932 * %g1: (TL>=0) ? 1 : 0
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 210b3e321c29..b280b2ef674f 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -33,6 +33,7 @@
33#include <asm/dcu.h> 33#include <asm/dcu.h>
34#include <asm/estate.h> 34#include <asm/estate.h>
35#include <asm/chafsr.h> 35#include <asm/chafsr.h>
36#include <asm/sfafsr.h>
36#include <asm/psrcompat.h> 37#include <asm/psrcompat.h>
37#include <asm/processor.h> 38#include <asm/processor.h>
38#include <asm/timer.h> 39#include <asm/timer.h>
@@ -143,8 +144,7 @@ void do_BUG(const char *file, int line)
143} 144}
144#endif 145#endif
145 146
146void instruction_access_exception(struct pt_regs *regs, 147void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
147 unsigned long sfsr, unsigned long sfar)
148{ 148{
149 siginfo_t info; 149 siginfo_t info;
150 150
@@ -153,8 +153,8 @@ void instruction_access_exception(struct pt_regs *regs,
153 return; 153 return;
154 154
155 if (regs->tstate & TSTATE_PRIV) { 155 if (regs->tstate & TSTATE_PRIV) {
156 printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n", 156 printk("spitfire_insn_access_exception: SFSR[%016lx] "
157 sfsr, sfar); 157 "SFAR[%016lx], going.\n", sfsr, sfar);
158 die_if_kernel("Iax", regs); 158 die_if_kernel("Iax", regs);
159 } 159 }
160 if (test_thread_flag(TIF_32BIT)) { 160 if (test_thread_flag(TIF_32BIT)) {
@@ -169,19 +169,17 @@ void instruction_access_exception(struct pt_regs *regs,
169 force_sig_info(SIGSEGV, &info, current); 169 force_sig_info(SIGSEGV, &info, current);
170} 170}
171 171
172void instruction_access_exception_tl1(struct pt_regs *regs, 172void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
173 unsigned long sfsr, unsigned long sfar)
174{ 173{
175 if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs, 174 if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
176 0, 0x8, SIGTRAP) == NOTIFY_STOP) 175 0, 0x8, SIGTRAP) == NOTIFY_STOP)
177 return; 176 return;
178 177
179 dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); 178 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
180 instruction_access_exception(regs, sfsr, sfar); 179 spitfire_insn_access_exception(regs, sfsr, sfar);
181} 180}
182 181
183void data_access_exception(struct pt_regs *regs, 182void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
184 unsigned long sfsr, unsigned long sfar)
185{ 183{
186 siginfo_t info; 184 siginfo_t info;
187 185
@@ -207,8 +205,8 @@ void data_access_exception(struct pt_regs *regs,
207 return; 205 return;
208 } 206 }
209 /* Shit... */ 207 /* Shit... */
210 printk("data_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n", 208 printk("spitfire_data_access_exception: SFSR[%016lx] "
211 sfsr, sfar); 209 "SFAR[%016lx], going.\n", sfsr, sfar);
212 die_if_kernel("Dax", regs); 210 die_if_kernel("Dax", regs);
213 } 211 }
214 212
@@ -220,15 +218,14 @@ void data_access_exception(struct pt_regs *regs,
220 force_sig_info(SIGSEGV, &info, current); 218 force_sig_info(SIGSEGV, &info, current);
221} 219}
222 220
223void data_access_exception_tl1(struct pt_regs *regs, 221void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
224 unsigned long sfsr, unsigned long sfar)
225{ 222{
226 if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs, 223 if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
227 0, 0x30, SIGTRAP) == NOTIFY_STOP) 224 0, 0x30, SIGTRAP) == NOTIFY_STOP)
228 return; 225 return;
229 226
230 dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); 227 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
231 data_access_exception(regs, sfsr, sfar); 228 spitfire_data_access_exception(regs, sfsr, sfar);
232} 229}
233 230
234#ifdef CONFIG_PCI 231#ifdef CONFIG_PCI
@@ -264,54 +261,13 @@ static void spitfire_clean_and_reenable_l1_caches(void)
264 : "memory"); 261 : "memory");
265} 262}
266 263
267void do_iae(struct pt_regs *regs) 264static void spitfire_enable_estate_errors(void)
268{ 265{
269 siginfo_t info; 266 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
270 267 "membar #Sync"
271 spitfire_clean_and_reenable_l1_caches(); 268 : /* no outputs */
272 269 : "r" (ESTATE_ERR_ALL),
273 if (notify_die(DIE_TRAP, "instruction access exception", regs, 270 "i" (ASI_ESTATE_ERROR_EN));
274 0, 0x8, SIGTRAP) == NOTIFY_STOP)
275 return;
276
277 info.si_signo = SIGBUS;
278 info.si_errno = 0;
279 info.si_code = BUS_OBJERR;
280 info.si_addr = (void *)0;
281 info.si_trapno = 0;
282 force_sig_info(SIGBUS, &info, current);
283}
284
285void do_dae(struct pt_regs *regs)
286{
287 siginfo_t info;
288
289#ifdef CONFIG_PCI
290 if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
291 spitfire_clean_and_reenable_l1_caches();
292
293 pci_poke_faulted = 1;
294
295 /* Why the fuck did they have to change this? */
296 if (tlb_type == cheetah || tlb_type == cheetah_plus)
297 regs->tpc += 4;
298
299 regs->tnpc = regs->tpc + 4;
300 return;
301 }
302#endif
303 spitfire_clean_and_reenable_l1_caches();
304
305 if (notify_die(DIE_TRAP, "data access exception", regs,
306 0, 0x30, SIGTRAP) == NOTIFY_STOP)
307 return;
308
309 info.si_signo = SIGBUS;
310 info.si_errno = 0;
311 info.si_code = BUS_OBJERR;
312 info.si_addr = (void *)0;
313 info.si_trapno = 0;
314 force_sig_info(SIGBUS, &info, current);
315} 271}
316 272
317static char ecc_syndrome_table[] = { 273static char ecc_syndrome_table[] = {
@@ -349,65 +305,15 @@ static char ecc_syndrome_table[] = {
349 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a 305 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
350}; 306};
351 307
352/* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status
353 * in the following format. The AFAR is left as is, with
354 * reserved bits cleared, and is a raw 40-bit physical
355 * address.
356 */
357#define CE_STATUS_UDBH_UE (1UL << (43 + 9))
358#define CE_STATUS_UDBH_CE (1UL << (43 + 8))
359#define CE_STATUS_UDBH_ESYNDR (0xffUL << 43)
360#define CE_STATUS_UDBH_SHIFT 43
361#define CE_STATUS_UDBL_UE (1UL << (33 + 9))
362#define CE_STATUS_UDBL_CE (1UL << (33 + 8))
363#define CE_STATUS_UDBL_ESYNDR (0xffUL << 33)
364#define CE_STATUS_UDBL_SHIFT 33
365#define CE_STATUS_AFSR_MASK (0x1ffffffffUL)
366#define CE_STATUS_AFSR_ME (1UL << 32)
367#define CE_STATUS_AFSR_PRIV (1UL << 31)
368#define CE_STATUS_AFSR_ISAP (1UL << 30)
369#define CE_STATUS_AFSR_ETP (1UL << 29)
370#define CE_STATUS_AFSR_IVUE (1UL << 28)
371#define CE_STATUS_AFSR_TO (1UL << 27)
372#define CE_STATUS_AFSR_BERR (1UL << 26)
373#define CE_STATUS_AFSR_LDP (1UL << 25)
374#define CE_STATUS_AFSR_CP (1UL << 24)
375#define CE_STATUS_AFSR_WP (1UL << 23)
376#define CE_STATUS_AFSR_EDP (1UL << 22)
377#define CE_STATUS_AFSR_UE (1UL << 21)
378#define CE_STATUS_AFSR_CE (1UL << 20)
379#define CE_STATUS_AFSR_ETS (0xfUL << 16)
380#define CE_STATUS_AFSR_ETS_SHIFT 16
381#define CE_STATUS_AFSR_PSYND (0xffffUL << 0)
382#define CE_STATUS_AFSR_PSYND_SHIFT 0
383
384/* Layout of Ecache TAG Parity Syndrome of AFSR */
385#define AFSR_ETSYNDROME_7_0 0x1UL /* E$-tag bus bits <7:0> */
386#define AFSR_ETSYNDROME_15_8 0x2UL /* E$-tag bus bits <15:8> */
387#define AFSR_ETSYNDROME_21_16 0x4UL /* E$-tag bus bits <21:16> */
388#define AFSR_ETSYNDROME_24_22 0x8UL /* E$-tag bus bits <24:22> */
389
390static char *syndrome_unknown = "<Unknown>"; 308static char *syndrome_unknown = "<Unknown>";
391 309
392asmlinkage void cee_log(unsigned long ce_status, 310static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long bit)
393 unsigned long afar,
394 struct pt_regs *regs)
395{ 311{
396 char memmod_str[64]; 312 unsigned short scode;
397 char *p; 313 char memmod_str[64], *p;
398 unsigned short scode, udb_reg;
399 314
400 printk(KERN_WARNING "CPU[%d]: Correctable ECC Error " 315 if (udbl & bit) {
401 "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n", 316 scode = ecc_syndrome_table[udbl & 0xff];
402 smp_processor_id(),
403 (ce_status & CE_STATUS_AFSR_MASK),
404 afar,
405 ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),
406 ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));
407
408 udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);
409 if (udb_reg & (1 << 8)) {
410 scode = ecc_syndrome_table[udb_reg & 0xff];
411 if (prom_getunumber(scode, afar, 317 if (prom_getunumber(scode, afar,
412 memmod_str, sizeof(memmod_str)) == -1) 318 memmod_str, sizeof(memmod_str)) == -1)
413 p = syndrome_unknown; 319 p = syndrome_unknown;
@@ -418,9 +324,8 @@ asmlinkage void cee_log(unsigned long ce_status,
418 smp_processor_id(), scode, p); 324 smp_processor_id(), scode, p);
419 } 325 }
420 326
421 udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL); 327 if (udbh & bit) {
422 if (udb_reg & (1 << 8)) { 328 scode = ecc_syndrome_table[udbh & 0xff];
423 scode = ecc_syndrome_table[udb_reg & 0xff];
424 if (prom_getunumber(scode, afar, 329 if (prom_getunumber(scode, afar,
425 memmod_str, sizeof(memmod_str)) == -1) 330 memmod_str, sizeof(memmod_str)) == -1)
426 p = syndrome_unknown; 331 p = syndrome_unknown;
@@ -430,6 +335,127 @@ asmlinkage void cee_log(unsigned long ce_status,
430 "Memory Module \"%s\"\n", 335 "Memory Module \"%s\"\n",
431 smp_processor_id(), scode, p); 336 smp_processor_id(), scode, p);
432 } 337 }
338
339}
340
341static void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, int tl1, struct pt_regs *regs)
342{
343
344 printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
345 "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx] TL>1[%d]\n",
346 smp_processor_id(), afsr, afar, udbl, udbh, tl1);
347
348 spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_CE);
349
350 /* We always log it, even if someone is listening for this
351 * trap.
352 */
353 notify_die(DIE_TRAP, "Correctable ECC Error", regs,
354 0, TRAP_TYPE_CEE, SIGTRAP);
355
356 /* The Correctable ECC Error trap does not disable I/D caches. So
357 * we only have to restore the ESTATE Error Enable register.
358 */
359 spitfire_enable_estate_errors();
360}
361
362static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs)
363{
364 siginfo_t info;
365
366 printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] "
367 "AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n",
368 smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1);
369
370 /* XXX add more human friendly logging of the error status
371 * XXX as is implemented for cheetah
372 */
373
374 spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_UE);
375
376 /* We always log it, even if someone is listening for this
377 * trap.
378 */
379 notify_die(DIE_TRAP, "Uncorrectable Error", regs,
380 0, tt, SIGTRAP);
381
382 if (regs->tstate & TSTATE_PRIV) {
383 if (tl1)
384 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
385 die_if_kernel("UE", regs);
386 }
387
388 /* XXX need more intelligent processing here, such as is implemented
389 * XXX for cheetah errors, in fact if the E-cache still holds the
390 * XXX line with bad parity this will loop
391 */
392
393 spitfire_clean_and_reenable_l1_caches();
394 spitfire_enable_estate_errors();
395
396 if (test_thread_flag(TIF_32BIT)) {
397 regs->tpc &= 0xffffffff;
398 regs->tnpc &= 0xffffffff;
399 }
400 info.si_signo = SIGBUS;
401 info.si_errno = 0;
402 info.si_code = BUS_OBJERR;
403 info.si_addr = (void *)0;
404 info.si_trapno = 0;
405 force_sig_info(SIGBUS, &info, current);
406}
407
408void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
409{
410 unsigned long afsr, tt, udbh, udbl;
411 int tl1;
412
413 afsr = (status_encoded & SFSTAT_AFSR_MASK) >> SFSTAT_AFSR_SHIFT;
414 tt = (status_encoded & SFSTAT_TRAP_TYPE) >> SFSTAT_TRAP_TYPE_SHIFT;
415 tl1 = (status_encoded & SFSTAT_TL_GT_ONE) ? 1 : 0;
416 udbl = (status_encoded & SFSTAT_UDBL_MASK) >> SFSTAT_UDBL_SHIFT;
417 udbh = (status_encoded & SFSTAT_UDBH_MASK) >> SFSTAT_UDBH_SHIFT;
418
419#ifdef CONFIG_PCI
420 if (tt == TRAP_TYPE_DAE &&
421 pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
422 spitfire_clean_and_reenable_l1_caches();
423 spitfire_enable_estate_errors();
424
425 pci_poke_faulted = 1;
426 regs->tnpc = regs->tpc + 4;
427 return;
428 }
429#endif
430
431 if (afsr & SFAFSR_UE)
432 spitfire_ue_log(afsr, afar, udbh, udbl, tt, tl1, regs);
433
434 if (tt == TRAP_TYPE_CEE) {
435 /* Handle the case where we took a CEE trap, but ACK'd
436 * only the UE state in the UDB error registers.
437 */
438 if (afsr & SFAFSR_UE) {
439 if (udbh & UDBE_CE) {
440 __asm__ __volatile__(
441 "stxa %0, [%1] %2\n\t"
442 "membar #Sync"
443 : /* no outputs */
444 : "r" (udbh & UDBE_CE),
445 "r" (0x0), "i" (ASI_UDB_ERROR_W));
446 }
447 if (udbl & UDBE_CE) {
448 __asm__ __volatile__(
449 "stxa %0, [%1] %2\n\t"
450 "membar #Sync"
451 : /* no outputs */
452 : "r" (udbl & UDBE_CE),
453 "r" (0x18), "i" (ASI_UDB_ERROR_W));
454 }
455 }
456
457 spitfire_cee_log(afsr, afar, udbh, udbl, tl1, regs);
458 }
433} 459}
434 460
435int cheetah_pcache_forced_on; 461int cheetah_pcache_forced_on;
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 491bb3681f9d..8365bc1f81f3 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -18,9 +18,10 @@ sparc64_ttable_tl0:
18tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) 18tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3)
19tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7) 19tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7)
20tl0_iax: membar #Sync 20tl0_iax: membar #Sync
21 TRAP_NOSAVE_7INSNS(__do_instruction_access_exception) 21 TRAP_NOSAVE_7INSNS(__spitfire_insn_access_exception)
22tl0_resv009: BTRAP(0x9) 22tl0_resv009: BTRAP(0x9)
23tl0_iae: TRAP(do_iae) 23tl0_iae: membar #Sync
24 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
24tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) 25tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
25tl0_ill: membar #Sync 26tl0_ill: membar #Sync
26 TRAP_7INSNS(do_illegal_instruction) 27 TRAP_7INSNS(do_illegal_instruction)
@@ -36,9 +37,10 @@ tl0_cwin: CLEAN_WINDOW
36tl0_div0: TRAP(do_div0) 37tl0_div0: TRAP(do_div0)
37tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) 38tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e)
38tl0_resv02f: BTRAP(0x2f) 39tl0_resv02f: BTRAP(0x2f)
39tl0_dax: TRAP_NOSAVE(__do_data_access_exception) 40tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception)
40tl0_resv031: BTRAP(0x31) 41tl0_resv031: BTRAP(0x31)
41tl0_dae: TRAP(do_dae) 42tl0_dae: membar #Sync
43 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
42tl0_resv033: BTRAP(0x33) 44tl0_resv033: BTRAP(0x33)
43tl0_mna: TRAP_NOSAVE(do_mna) 45tl0_mna: TRAP_NOSAVE(do_mna)
44tl0_lddfmna: TRAP_NOSAVE(do_lddfmna) 46tl0_lddfmna: TRAP_NOSAVE(do_lddfmna)
@@ -73,7 +75,8 @@ tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f)
73tl0_ivec: TRAP_IVEC 75tl0_ivec: TRAP_IVEC
74tl0_paw: TRAP(do_paw) 76tl0_paw: TRAP(do_paw)
75tl0_vaw: TRAP(do_vaw) 77tl0_vaw: TRAP(do_vaw)
76tl0_cee: TRAP_NOSAVE(cee_trap) 78tl0_cee: membar #Sync
79 TRAP_NOSAVE_7INSNS(__spitfire_cee_trap)
77tl0_iamiss: 80tl0_iamiss:
78#include "itlb_base.S" 81#include "itlb_base.S"
79tl0_damiss: 82tl0_damiss:
@@ -175,9 +178,10 @@ tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
175sparc64_ttable_tl1: 178sparc64_ttable_tl1:
176tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3) 179tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3)
177tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7) 180tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7)
178tl1_iax: TRAP_NOSAVE(__do_instruction_access_exception_tl1) 181tl1_iax: TRAP_NOSAVE(__spitfire_insn_access_exception_tl1)
179tl1_resv009: BTRAPTL1(0x9) 182tl1_resv009: BTRAPTL1(0x9)
180tl1_iae: TRAPTL1(do_iae_tl1) 183tl1_iae: membar #Sync
184 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
181tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf) 185tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf)
182tl1_ill: TRAPTL1(do_ill_tl1) 186tl1_ill: TRAPTL1(do_ill_tl1)
183tl1_privop: BTRAPTL1(0x11) 187tl1_privop: BTRAPTL1(0x11)
@@ -193,9 +197,10 @@ tl1_cwin: CLEAN_WINDOW
193tl1_div0: TRAPTL1(do_div0_tl1) 197tl1_div0: TRAPTL1(do_div0_tl1)
194tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c) 198tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c)
195tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f) 199tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
196tl1_dax: TRAP_NOSAVE(__do_data_access_exception_tl1) 200tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1)
197tl1_resv031: BTRAPTL1(0x31) 201tl1_resv031: BTRAPTL1(0x31)
198tl1_dae: TRAPTL1(do_dae_tl1) 202tl1_dae: membar #Sync
203 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
199tl1_resv033: BTRAPTL1(0x33) 204tl1_resv033: BTRAPTL1(0x33)
200tl1_mna: TRAP_NOSAVE(do_mna) 205tl1_mna: TRAP_NOSAVE(do_mna)
201tl1_lddfmna: TRAPTL1(do_lddfmna_tl1) 206tl1_lddfmna: TRAPTL1(do_lddfmna_tl1)
@@ -219,8 +224,8 @@ tl1_paw: TRAPTL1(do_paw_tl1)
219tl1_vaw: TRAPTL1(do_vaw_tl1) 224tl1_vaw: TRAPTL1(do_vaw_tl1)
220 225
221 /* The grotty trick to save %g1 into current->thread.cee_stuff 226 /* The grotty trick to save %g1 into current->thread.cee_stuff
222 * is because when we take this trap we could be interrupting trap 227 * is because when we take this trap we could be interrupting
223 * code already using the trap alternate global registers. 228 * trap code already using the trap alternate global registers.
224 * 229 *
225 * We cross our fingers and pray that this store/load does 230 * We cross our fingers and pray that this store/load does
226 * not cause yet another CEE trap. 231 * not cause yet another CEE trap.
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 11c3e88732e4..da9739f0d437 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -349,9 +349,9 @@ int handle_popc(u32 insn, struct pt_regs *regs)
349 349
350extern void do_fpother(struct pt_regs *regs); 350extern void do_fpother(struct pt_regs *regs);
351extern void do_privact(struct pt_regs *regs); 351extern void do_privact(struct pt_regs *regs);
352extern void data_access_exception(struct pt_regs *regs, 352extern void spitfire_data_access_exception(struct pt_regs *regs,
353 unsigned long sfsr, 353 unsigned long sfsr,
354 unsigned long sfar); 354 unsigned long sfar);
355 355
356int handle_ldf_stq(u32 insn, struct pt_regs *regs) 356int handle_ldf_stq(u32 insn, struct pt_regs *regs)
357{ 357{
@@ -394,14 +394,14 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
394 break; 394 break;
395 } 395 }
396 default: 396 default:
397 data_access_exception(regs, 0, addr); 397 spitfire_data_access_exception(regs, 0, addr);
398 return 1; 398 return 1;
399 } 399 }
400 if (put_user (first >> 32, (u32 __user *)addr) || 400 if (put_user (first >> 32, (u32 __user *)addr) ||
401 __put_user ((u32)first, (u32 __user *)(addr + 4)) || 401 __put_user ((u32)first, (u32 __user *)(addr + 4)) ||
402 __put_user (second >> 32, (u32 __user *)(addr + 8)) || 402 __put_user (second >> 32, (u32 __user *)(addr + 8)) ||
403 __put_user ((u32)second, (u32 __user *)(addr + 12))) { 403 __put_user ((u32)second, (u32 __user *)(addr + 12))) {
404 data_access_exception(regs, 0, addr); 404 spitfire_data_access_exception(regs, 0, addr);
405 return 1; 405 return 1;
406 } 406 }
407 } else { 407 } else {
@@ -414,7 +414,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
414 do_privact(regs); 414 do_privact(regs);
415 return 1; 415 return 1;
416 } else if (asi > ASI_SNFL) { 416 } else if (asi > ASI_SNFL) {
417 data_access_exception(regs, 0, addr); 417 spitfire_data_access_exception(regs, 0, addr);
418 return 1; 418 return 1;
419 } 419 }
420 switch (insn & 0x180000) { 420 switch (insn & 0x180000) {
@@ -431,7 +431,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
431 err |= __get_user (data[i], (u32 __user *)(addr + 4*i)); 431 err |= __get_user (data[i], (u32 __user *)(addr + 4*i));
432 } 432 }
433 if (err && !(asi & 0x2 /* NF */)) { 433 if (err && !(asi & 0x2 /* NF */)) {
434 data_access_exception(regs, 0, addr); 434 spitfire_data_access_exception(regs, 0, addr);
435 return 1; 435 return 1;
436 } 436 }
437 if (asi & 0x8) /* Little */ { 437 if (asi & 0x8) /* Little */ {
@@ -534,7 +534,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
534 *(u64 *)(f->regs + freg) = value; 534 *(u64 *)(f->regs + freg) = value;
535 current_thread_info()->fpsaved[0] |= flag; 535 current_thread_info()->fpsaved[0] |= flag;
536 } else { 536 } else {
537daex: data_access_exception(regs, sfsr, sfar); 537daex: spitfire_data_access_exception(regs, sfsr, sfar);
538 return; 538 return;
539 } 539 }
540 advance(regs); 540 advance(regs);
@@ -578,7 +578,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
578 __put_user ((u32)value, (u32 __user *)(sfar + 4))) 578 __put_user ((u32)value, (u32 __user *)(sfar + 4)))
579 goto daex; 579 goto daex;
580 } else { 580 } else {
581daex: data_access_exception(regs, sfsr, sfar); 581daex: spitfire_data_access_exception(regs, sfsr, sfar);
582 return; 582 return;
583 } 583 }
584 advance(regs); 584 advance(regs);
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index dfbc7e0dcf70..99c809a1e5ac 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -318,7 +318,7 @@ fill_fixup_dax:
318 nop 318 nop
319 rdpr %pstate, %l1 ! Prepare to change globals. 319 rdpr %pstate, %l1 ! Prepare to change globals.
320 mov %g4, %o1 ! Setup args for 320 mov %g4, %o1 ! Setup args for
321 mov %g5, %o2 ! final call to data_access_exception. 321 mov %g5, %o2 ! final call to spitfire_data_access_exception.
322 andn %l1, PSTATE_MM, %l1 ! We want to be in RMO 322 andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
323 323
324 mov %g6, %o7 ! Stash away current. 324 mov %g6, %o7 ! Stash away current.
@@ -330,7 +330,7 @@ fill_fixup_dax:
330 mov TSB_REG, %g1 330 mov TSB_REG, %g1
331 ldxa [%g1] ASI_IMMU, %g5 331 ldxa [%g1] ASI_IMMU, %g5
332#endif 332#endif
333 call data_access_exception 333 call spitfire_data_access_exception
334 add %sp, PTREGS_OFF, %o0 334 add %sp, PTREGS_OFF, %o0
335 335
336 b,pt %xcc, rtrap 336 b,pt %xcc, rtrap
@@ -391,7 +391,7 @@ window_dax_from_user_common:
391109: or %g7, %lo(109b), %g7 391109: or %g7, %lo(109b), %g7
392 mov %l4, %o1 392 mov %l4, %o1
393 mov %l5, %o2 393 mov %l5, %o2
394 call data_access_exception 394 call spitfire_data_access_exception
395 add %sp, PTREGS_OFF, %o0 395 add %sp, PTREGS_OFF, %o0
396 ba,pt %xcc, rtrap 396 ba,pt %xcc, rtrap
397 clr %l6 397 clr %l6