aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
authorKumar Gala <galak@freescale.com>2005-06-21 20:15:27 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-21 21:46:25 -0400
commit1492ec8069ea6f82bc32df27cabbec72e554e2b8 (patch)
tree09e52d150482a105a63dc4b71758a7aa99ecb28c /arch/ppc
parent5be061eee931db2718feecaf10df17610386202b (diff)
[PATCH] ppc32: Factor out common exception code into macro's for 4xx/Book-E
4xx and Book-E PPC's have several exception levels. The code to handle each level is fairly regular. Turning the code into macro's will ease the handling of future exception levels (debug) in forth coming chips. Signed-off-by: Kumar Gala <kumar.gala@freescale.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ppc')
-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; \