aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ppc/kernel/entry.S164
-rw-r--r--arch/ppc/kernel/head_booke.h94
2 files changed, 87 insertions, 171 deletions
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 661523707e8c..8377b6ca26da 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -46,26 +46,23 @@
46 46
47#ifdef CONFIG_BOOKE 47#ifdef CONFIG_BOOKE
48#include "head_booke.h" 48#include "head_booke.h"
49#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level) \
50 mtspr exc_level##_SPRG,r8; \
51 BOOKE_LOAD_EXC_LEVEL_STACK(exc_level); \
52 lwz r0,GPR10-INT_FRAME_SIZE(r8); \
53 stw r0,GPR10(r11); \
54 lwz r0,GPR11-INT_FRAME_SIZE(r8); \
55 stw r0,GPR11(r11); \
56 mfspr r8,exc_level##_SPRG
57
49 .globl mcheck_transfer_to_handler 58 .globl mcheck_transfer_to_handler
50mcheck_transfer_to_handler: 59mcheck_transfer_to_handler:
51 mtspr MCHECK_SPRG,r8 60 TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
52 BOOKE_LOAD_MCHECK_STACK
53 lwz r0,GPR10-INT_FRAME_SIZE(r8)
54 stw r0,GPR10(r11)
55 lwz r0,GPR11-INT_FRAME_SIZE(r8)
56 stw r0,GPR11(r11)
57 mfspr r8,MCHECK_SPRG
58 b transfer_to_handler_full 61 b transfer_to_handler_full
59 62
60 .globl crit_transfer_to_handler 63 .globl crit_transfer_to_handler
61crit_transfer_to_handler: 64crit_transfer_to_handler:
62 mtspr CRIT_SPRG,r8 65 TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
63 BOOKE_LOAD_CRIT_STACK
64 lwz r0,GPR10-INT_FRAME_SIZE(r8)
65 stw r0,GPR10(r11)
66 lwz r0,GPR11-INT_FRAME_SIZE(r8)
67 stw r0,GPR11(r11)
68 mfspr r8,CRIT_SPRG
69 /* fall through */ 66 /* fall through */
70#endif 67#endif
71 68
@@ -783,99 +780,64 @@ exc_exit_restart_end:
783 * time of the critical interrupt. 780 * time of the critical interrupt.
784 * 781 *
785 */ 782 */
786 .globl ret_from_crit_exc
787ret_from_crit_exc:
788 REST_NVGPRS(r1)
789 lwz r3,_MSR(r1)
790 andi. r3,r3,MSR_PR
791 LOAD_MSR_KERNEL(r10,MSR_KERNEL)
792 bne user_exc_return
793
794 lwz r0,GPR0(r1)
795 lwz r2,GPR2(r1)
796 REST_4GPRS(3, r1)
797 REST_2GPRS(7, r1)
798
799 lwz r10,_XER(r1)
800 lwz r11,_CTR(r1)
801 mtspr SPRN_XER,r10
802 mtctr r11
803
804 PPC405_ERR77(0,r1)
805 stwcx. r0,0,r1 /* to clear the reservation */
806
807 lwz r11,_LINK(r1)
808 mtlr r11
809 lwz r10,_CCR(r1)
810 mtcrf 0xff,r10
811#ifdef CONFIG_40x 783#ifdef CONFIG_40x
812 /* avoid any possible TLB misses here by turning off MSR.DR, we 784#define PPC_40x_TURN_OFF_MSR_DR \
813 * assume the instructions here are mapped by a pinned TLB entry */ 785 /* avoid any possible TLB misses here by turning off MSR.DR, we \
814 li r10,MSR_IR 786 * assume the instructions here are mapped by a pinned TLB entry */ \
815 mtmsr r10 787 li r10,MSR_IR; \
816 isync 788 mtmsr r10; \
817 tophys(r1, r1) 789 isync; \
790 tophys(r1, r1);
791#else
792#define PPC_40x_TURN_OFF_MSR_DR
818#endif 793#endif
819 lwz r9,_DEAR(r1) 794
820 lwz r10,_ESR(r1) 795#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi) \
821 mtspr SPRN_DEAR,r9 796 REST_NVGPRS(r1); \
822 mtspr SPRN_ESR,r10 797 lwz r3,_MSR(r1); \
823 lwz r11,_NIP(r1) 798 andi. r3,r3,MSR_PR; \
824 lwz r12,_MSR(r1) 799 LOAD_MSR_KERNEL(r10,MSR_KERNEL); \
825 mtspr SPRN_CSRR0,r11 800 bne user_exc_return; \
826 mtspr SPRN_CSRR1,r12 801 lwz r0,GPR0(r1); \
827 lwz r9,GPR9(r1) 802 lwz r2,GPR2(r1); \
828 lwz r12,GPR12(r1) 803 REST_4GPRS(3, r1); \
829 lwz r10,GPR10(r1) 804 REST_2GPRS(7, r1); \
830 lwz r11,GPR11(r1) 805 lwz r10,_XER(r1); \
831 lwz r1,GPR1(r1) 806 lwz r11,_CTR(r1); \
832 PPC405_ERR77_SYNC 807 mtspr SPRN_XER,r10; \
833 rfci 808 mtctr r11; \
834 b . /* prevent prefetch past rfci */ 809 PPC405_ERR77(0,r1); \
810 stwcx. r0,0,r1; /* to clear the reservation */ \
811 lwz r11,_LINK(r1); \
812 mtlr r11; \
813 lwz r10,_CCR(r1); \
814 mtcrf 0xff,r10; \
815 PPC_40x_TURN_OFF_MSR_DR; \
816 lwz r9,_DEAR(r1); \
817 lwz r10,_ESR(r1); \
818 mtspr SPRN_DEAR,r9; \
819 mtspr SPRN_ESR,r10; \
820 lwz r11,_NIP(r1); \
821 lwz r12,_MSR(r1); \
822 mtspr exc_lvl_srr0,r11; \
823 mtspr exc_lvl_srr1,r12; \
824 lwz r9,GPR9(r1); \
825 lwz r12,GPR12(r1); \
826 lwz r10,GPR10(r1); \
827 lwz r11,GPR11(r1); \
828 lwz r1,GPR1(r1); \
829 PPC405_ERR77_SYNC; \
830 exc_lvl_rfi; \
831 b .; /* prevent prefetch past exc_lvl_rfi */
832
833 .globl ret_from_crit_exc
834ret_from_crit_exc:
835 RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
835 836
836#ifdef CONFIG_BOOKE 837#ifdef CONFIG_BOOKE
837/*
838 * Return from a machine check interrupt, similar to a critical
839 * interrupt.
840 */
841 .globl ret_from_mcheck_exc 838 .globl ret_from_mcheck_exc
842ret_from_mcheck_exc: 839ret_from_mcheck_exc:
843 REST_NVGPRS(r1) 840 RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
844 lwz r3,_MSR(r1)
845 andi. r3,r3,MSR_PR
846 LOAD_MSR_KERNEL(r10,MSR_KERNEL)
847 bne user_exc_return
848
849 lwz r0,GPR0(r1)
850 lwz r2,GPR2(r1)
851 REST_4GPRS(3, r1)
852 REST_2GPRS(7, r1)
853
854 lwz r10,_XER(r1)
855 lwz r11,_CTR(r1)
856 mtspr SPRN_XER,r10
857 mtctr r11
858
859 stwcx. r0,0,r1 /* to clear the reservation */
860
861 lwz r11,_LINK(r1)
862 mtlr r11
863 lwz r10,_CCR(r1)
864 mtcrf 0xff,r10
865 lwz r9,_DEAR(r1)
866 lwz r10,_ESR(r1)
867 mtspr SPRN_DEAR,r9
868 mtspr SPRN_ESR,r10
869 lwz r11,_NIP(r1)
870 lwz r12,_MSR(r1)
871 mtspr SPRN_MCSRR0,r11
872 mtspr SPRN_MCSRR1,r12
873 lwz r9,GPR9(r1)
874 lwz r12,GPR12(r1)
875 lwz r10,GPR10(r1)
876 lwz r11,GPR11(r1)
877 lwz r1,GPR1(r1)
878 RFMCI
879#endif /* CONFIG_BOOKE */ 841#endif /* CONFIG_BOOKE */
880 842
881/* 843/*
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
index f213d12eec08..9c50f9d2657c 100644
--- a/arch/ppc/kernel/head_booke.h
+++ b/arch/ppc/kernel/head_booke.h
@@ -67,46 +67,36 @@
67#define CRIT_STACK_TOP (exception_stack_top) 67#define CRIT_STACK_TOP (exception_stack_top)
68 68
69#ifdef CONFIG_SMP 69#ifdef CONFIG_SMP
70#define BOOKE_LOAD_CRIT_STACK \ 70#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
71 mfspr r8,SPRN_PIR; \ 71 mfspr r8,SPRN_PIR; \
72 mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \ 72 mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
73 neg r8,r8; \ 73 neg r8,r8; \
74 addis r8,r8,CRIT_STACK_TOP@ha; \ 74 addis r8,r8,level##_STACK_TOP@ha; \
75 addi r8,r8,CRIT_STACK_TOP@l 75 addi r8,r8,level##_STACK_TOP@l
76#define BOOKE_LOAD_MCHECK_STACK \
77 mfspr r8,SPRN_PIR; \
78 mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
79 neg r8,r8; \
80 addis r8,r8,MCHECK_STACK_TOP@ha; \
81 addi r8,r8,MCHECK_STACK_TOP@l
82#else 76#else
83#define BOOKE_LOAD_CRIT_STACK \ 77#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
84 lis r8,CRIT_STACK_TOP@h; \ 78 lis r8,level##_STACK_TOP@h; \
85 ori r8,r8,CRIT_STACK_TOP@l 79 ori r8,r8,level##_STACK_TOP@l
86#define BOOKE_LOAD_MCHECK_STACK \
87 lis r8,MCHECK_STACK_TOP@h; \
88 ori r8,r8,MCHECK_STACK_TOP@l
89#endif 80#endif
90 81
91/* 82/*
92 * Exception prolog for critical exceptions. This is a little different 83 * Exception prolog for critical/machine check exceptions. This is a
93 * from the normal exception prolog above since a critical exception 84 * little different from the normal exception prolog above since a
94 * can potentially occur at any point during normal exception processing. 85 * critical/machine check exception can potentially occur at any point
95 * Thus we cannot use the same SPRG registers as the normal prolog above. 86 * during normal exception processing. Thus we cannot use the same SPRG
96 * Instead we use a portion of the critical exception stack at low physical 87 * registers as the normal prolog above. Instead we use a portion of the
97 * addresses. 88 * critical/machine check exception stack at low physical addresses.
98 */ 89 */
99 90#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
100#define CRITICAL_EXCEPTION_PROLOG \ 91 mtspr exc_level##_SPRG,r8; \
101 mtspr CRIT_SPRG,r8; \ 92 BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
102 BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
103 stw r10,GPR10-INT_FRAME_SIZE(r8); \ 93 stw r10,GPR10-INT_FRAME_SIZE(r8); \
104 stw r11,GPR11-INT_FRAME_SIZE(r8); \ 94 stw r11,GPR11-INT_FRAME_SIZE(r8); \
105 mfcr r10; /* save CR in r10 for now */\ 95 mfcr r10; /* save CR in r10 for now */\
106 mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\ 96 mfspr r11,exc_level_srr1; /* check whether user or kernel */\
107 andi. r11,r11,MSR_PR; \ 97 andi. r11,r11,MSR_PR; \
108 mr r11,r8; \ 98 mr r11,r8; \
109 mfspr r8,CRIT_SPRG; \ 99 mfspr r8,exc_level##_SPRG; \
110 beq 1f; \ 100 beq 1f; \
111 /* COMING FROM USER MODE */ \ 101 /* COMING FROM USER MODE */ \
112 mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ 102 mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
@@ -122,9 +112,9 @@
122 stw r12,_DEAR(r11); /* since they may have had stuff */\ 112 stw r12,_DEAR(r11); /* since they may have had stuff */\
123 mfspr r9,SPRN_ESR; /* in them at the point where the */\ 113 mfspr r9,SPRN_ESR; /* in them at the point where the */\
124 stw r9,_ESR(r11); /* exception was taken */\ 114 stw r9,_ESR(r11); /* exception was taken */\
125 mfspr r12,SPRN_CSRR0; \ 115 mfspr r12,exc_level_srr0; \
126 stw r1,GPR1(r11); \ 116 stw r1,GPR1(r11); \
127 mfspr r9,SPRN_CSRR1; \ 117 mfspr r9,exc_level_srr1; \
128 stw r1,0(r11); \ 118 stw r1,0(r11); \
129 mr r1,r11; \ 119 mr r1,r11; \
130 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ 120 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
@@ -132,45 +122,10 @@
132 SAVE_4GPRS(3, r11); \ 122 SAVE_4GPRS(3, r11); \
133 SAVE_2GPRS(7, r11) 123 SAVE_2GPRS(7, r11)
134 124
135/* 125#define CRITICAL_EXCEPTION_PROLOG \
136 * Exception prolog for machine check exceptions. This is similar to 126 EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
137 * the critical exception prolog, except that machine check exceptions 127#define MCHECK_EXCEPTION_PROLOG \
138 * have their stack. 128 EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1)
139 */
140#define MCHECK_EXCEPTION_PROLOG \
141 mtspr MCHECK_SPRG,r8; \
142 BOOKE_LOAD_MCHECK_STACK; /* r8 points to the mcheck stack */\
143 stw r10,GPR10-INT_FRAME_SIZE(r8); \
144 stw r11,GPR11-INT_FRAME_SIZE(r8); \
145 mfcr r10; /* save CR in r10 for now */\
146 mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
147 andi. r11,r11,MSR_PR; \
148 mr r11,r8; \
149 mfspr r8,MCHECK_SPRG; \
150 beq 1f; \
151 /* COMING FROM USER MODE */ \
152 mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
153 lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
154 addi r11,r11,THREAD_SIZE; \
1551: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
156 stw r10,_CCR(r11); /* save various registers */\
157 stw r12,GPR12(r11); \
158 stw r9,GPR9(r11); \
159 mflr r10; \
160 stw r10,_LINK(r11); \
161 mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
162 stw r12,_DEAR(r11); /* since they may have had stuff */\
163 mfspr r9,SPRN_ESR; /* in them at the point where the */\
164 stw r9,_ESR(r11); /* exception was taken */\
165 mfspr r12,SPRN_MCSRR0; \
166 stw r1,GPR1(r11); \
167 mfspr r9,SPRN_MCSRR1; \
168 stw r1,0(r11); \
169 mr r1,r11; \
170 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
171 stw r0,GPR0(r11); \
172 SAVE_4GPRS(3, r11); \
173 SAVE_2GPRS(7, r11)
174 129
175/* 130/*
176 * Exception vectors. 131 * Exception vectors.
@@ -237,7 +192,6 @@ label:
237 EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ 192 EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
238 ret_from_except) 193 ret_from_except)
239 194
240
241/* Check for a single step debug exception while in an exception 195/* Check for a single step debug exception while in an exception
242 * handler before state has been saved. This is to catch the case 196 * handler before state has been saved. This is to catch the case
243 * where an instruction that we are trying to single step causes 197 * where an instruction that we are trying to single step causes
@@ -291,7 +245,7 @@ label:
291 lwz r9,GPR9(r11); \ 245 lwz r9,GPR9(r11); \
292 lwz r12,GPR12(r11); \ 246 lwz r12,GPR12(r11); \
293 mtspr CRIT_SPRG,r8; \ 247 mtspr CRIT_SPRG,r8; \
294 BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \ 248 BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \
295 lwz r10,GPR10-INT_FRAME_SIZE(r8); \ 249 lwz r10,GPR10-INT_FRAME_SIZE(r8); \
296 lwz r11,GPR11-INT_FRAME_SIZE(r8); \ 250 lwz r11,GPR11-INT_FRAME_SIZE(r8); \
297 mfspr r8,CRIT_SPRG; \ 251 mfspr r8,CRIT_SPRG; \