diff options
Diffstat (limited to 'arch/powerpc/include/asm/exception-64s.h')
-rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 7778d6f0c878..f5dfe3411f64 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define EX_CCR 60 | 46 | #define EX_CCR 60 |
47 | #define EX_R3 64 | 47 | #define EX_R3 64 |
48 | #define EX_LR 72 | 48 | #define EX_LR 72 |
49 | #define EX_CFAR 80 | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * We're short on space and time in the exception prolog, so we can't | 52 | * We're short on space and time in the exception prolog, so we can't |
@@ -56,30 +57,40 @@ | |||
56 | #define LOAD_HANDLER(reg, label) \ | 57 | #define LOAD_HANDLER(reg, label) \ |
57 | addi reg,reg,(label)-_stext; /* virt addr of handler ... */ | 58 | addi reg,reg,(label)-_stext; /* virt addr of handler ... */ |
58 | 59 | ||
59 | #define EXCEPTION_PROLOG_1(area) \ | 60 | /* Exception register prefixes */ |
60 | mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \ | 61 | #define EXC_HV H |
62 | #define EXC_STD | ||
63 | |||
64 | #define EXCEPTION_PROLOG_1(area) \ | ||
65 | GET_PACA(r13); \ | ||
61 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | 66 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ |
62 | std r10,area+EX_R10(r13); \ | 67 | std r10,area+EX_R10(r13); \ |
63 | std r11,area+EX_R11(r13); \ | 68 | std r11,area+EX_R11(r13); \ |
64 | std r12,area+EX_R12(r13); \ | 69 | std r12,area+EX_R12(r13); \ |
65 | mfspr r9,SPRN_SPRG_SCRATCH0; \ | 70 | BEGIN_FTR_SECTION_NESTED(66); \ |
71 | mfspr r10,SPRN_CFAR; \ | ||
72 | std r10,area+EX_CFAR(r13); \ | ||
73 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \ | ||
74 | GET_SCRATCH0(r9); \ | ||
66 | std r9,area+EX_R13(r13); \ | 75 | std r9,area+EX_R13(r13); \ |
67 | mfcr r9 | 76 | mfcr r9 |
68 | 77 | ||
69 | #define EXCEPTION_PROLOG_PSERIES_1(label) \ | 78 | #define __EXCEPTION_PROLOG_PSERIES_1(label, h) \ |
70 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ | 79 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ |
71 | ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ | 80 | ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ |
72 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | 81 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
73 | LOAD_HANDLER(r12,label) \ | 82 | LOAD_HANDLER(r12,label) \ |
74 | mtspr SPRN_SRR0,r12; \ | 83 | mtspr SPRN_##h##SRR0,r12; \ |
75 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | 84 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ |
76 | mtspr SPRN_SRR1,r10; \ | 85 | mtspr SPRN_##h##SRR1,r10; \ |
77 | rfid; \ | 86 | h##rfid; \ |
78 | b . /* prevent speculative execution */ | 87 | b . /* prevent speculative execution */ |
88 | #define EXCEPTION_PROLOG_PSERIES_1(label, h) \ | ||
89 | __EXCEPTION_PROLOG_PSERIES_1(label, h) | ||
79 | 90 | ||
80 | #define EXCEPTION_PROLOG_PSERIES(area, label) \ | 91 | #define EXCEPTION_PROLOG_PSERIES(area, label, h) \ |
81 | EXCEPTION_PROLOG_1(area); \ | 92 | EXCEPTION_PROLOG_1(area); \ |
82 | EXCEPTION_PROLOG_PSERIES_1(label); | 93 | EXCEPTION_PROLOG_PSERIES_1(label, h); |
83 | 94 | ||
84 | /* | 95 | /* |
85 | * The common exception prolog is used for all except a few exceptions | 96 | * The common exception prolog is used for all except a few exceptions |
@@ -98,10 +109,11 @@ | |||
98 | beq- 1f; \ | 109 | beq- 1f; \ |
99 | ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ | 110 | ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ |
100 | 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ | 111 | 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ |
101 | bge- cr1,2f; /* abort if it is */ \ | 112 | blt+ cr1,3f; /* abort if it is */ \ |
102 | b 3f; \ | 113 | li r1,(n); /* will be reloaded later */ \ |
103 | 2: li r1,(n); /* will be reloaded later */ \ | ||
104 | sth r1,PACA_TRAP_SAVE(r13); \ | 114 | sth r1,PACA_TRAP_SAVE(r13); \ |
115 | std r3,area+EX_R3(r13); \ | ||
116 | addi r3,r13,area; /* r3 -> where regs are saved*/ \ | ||
105 | b bad_stack; \ | 117 | b bad_stack; \ |
106 | 3: std r9,_CCR(r1); /* save CR in stackframe */ \ | 118 | 3: std r9,_CCR(r1); /* save CR in stackframe */ \ |
107 | std r11,_NIP(r1); /* save SRR0 in stackframe */ \ | 119 | std r11,_NIP(r1); /* save SRR0 in stackframe */ \ |
@@ -123,6 +135,10 @@ | |||
123 | std r9,GPR11(r1); \ | 135 | std r9,GPR11(r1); \ |
124 | std r10,GPR12(r1); \ | 136 | std r10,GPR12(r1); \ |
125 | std r11,GPR13(r1); \ | 137 | std r11,GPR13(r1); \ |
138 | BEGIN_FTR_SECTION_NESTED(66); \ | ||
139 | ld r10,area+EX_CFAR(r13); \ | ||
140 | std r10,ORIG_GPR3(r1); \ | ||
141 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \ | ||
126 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ | 142 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ |
127 | mflr r9; /* save LR in stackframe */ \ | 143 | mflr r9; /* save LR in stackframe */ \ |
128 | std r9,_LINK(r1); \ | 144 | std r9,_LINK(r1); \ |
@@ -143,57 +159,62 @@ | |||
143 | /* | 159 | /* |
144 | * Exception vectors. | 160 | * Exception vectors. |
145 | */ | 161 | */ |
146 | #define STD_EXCEPTION_PSERIES(n, label) \ | 162 | #define STD_EXCEPTION_PSERIES(loc, vec, label) \ |
147 | . = n; \ | 163 | . = loc; \ |
148 | .globl label##_pSeries; \ | 164 | .globl label##_pSeries; \ |
149 | label##_pSeries: \ | 165 | label##_pSeries: \ |
150 | HMT_MEDIUM; \ | 166 | HMT_MEDIUM; \ |
151 | DO_KVM n; \ | 167 | DO_KVM vec; \ |
152 | mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ | 168 | SET_SCRATCH0(r13); /* save r13 */ \ |
153 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | 169 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD) |
154 | 170 | ||
155 | #define HSTD_EXCEPTION_PSERIES(n, label) \ | 171 | #define STD_EXCEPTION_HV(loc, vec, label) \ |
156 | . = n; \ | 172 | . = loc; \ |
157 | .globl label##_pSeries; \ | 173 | .globl label##_hv; \ |
158 | label##_pSeries: \ | 174 | label##_hv: \ |
159 | HMT_MEDIUM; \ | 175 | HMT_MEDIUM; \ |
160 | mtspr SPRN_SPRG_SCRATCH0,r20; /* save r20 */ \ | 176 | DO_KVM vec; \ |
161 | mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \ | 177 | SET_SCRATCH0(r13); /* save r13 */ \ |
162 | mtspr SPRN_SRR0,r20; \ | 178 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV) |
163 | mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \ | ||
164 | mtspr SPRN_SRR1,r20; \ | ||
165 | mfspr r20,SPRN_SPRG_SCRATCH0; /* restore r20 */ \ | ||
166 | mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ | ||
167 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | ||
168 | 179 | ||
169 | 180 | #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h) \ | |
170 | #define MASKABLE_EXCEPTION_PSERIES(n, label) \ | ||
171 | . = n; \ | ||
172 | .globl label##_pSeries; \ | ||
173 | label##_pSeries: \ | ||
174 | HMT_MEDIUM; \ | 181 | HMT_MEDIUM; \ |
175 | DO_KVM n; \ | 182 | DO_KVM vec; \ |
176 | mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ | 183 | SET_SCRATCH0(r13); /* save r13 */ \ |
177 | mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \ | 184 | GET_PACA(r13); \ |
178 | std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ | 185 | std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ |
179 | std r10,PACA_EXGEN+EX_R10(r13); \ | 186 | std r10,PACA_EXGEN+EX_R10(r13); \ |
180 | lbz r10,PACASOFTIRQEN(r13); \ | 187 | lbz r10,PACASOFTIRQEN(r13); \ |
181 | mfcr r9; \ | 188 | mfcr r9; \ |
182 | cmpwi r10,0; \ | 189 | cmpwi r10,0; \ |
183 | beq masked_interrupt; \ | 190 | beq masked_##h##interrupt; \ |
184 | mfspr r10,SPRN_SPRG_SCRATCH0; \ | 191 | GET_SCRATCH0(r10); \ |
185 | std r10,PACA_EXGEN+EX_R13(r13); \ | 192 | std r10,PACA_EXGEN+EX_R13(r13); \ |
186 | std r11,PACA_EXGEN+EX_R11(r13); \ | 193 | std r11,PACA_EXGEN+EX_R11(r13); \ |
187 | std r12,PACA_EXGEN+EX_R12(r13); \ | 194 | std r12,PACA_EXGEN+EX_R12(r13); \ |
188 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ | 195 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ |
189 | ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ | 196 | ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ |
190 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | 197 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
191 | LOAD_HANDLER(r12,label##_common) \ | 198 | LOAD_HANDLER(r12,label##_common) \ |
192 | mtspr SPRN_SRR0,r12; \ | 199 | mtspr SPRN_##h##SRR0,r12; \ |
193 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | 200 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ |
194 | mtspr SPRN_SRR1,r10; \ | 201 | mtspr SPRN_##h##SRR1,r10; \ |
195 | rfid; \ | 202 | h##rfid; \ |
196 | b . /* prevent speculative execution */ | 203 | b . /* prevent speculative execution */ |
204 | #define _MASKABLE_EXCEPTION_PSERIES(vec, label, h) \ | ||
205 | __MASKABLE_EXCEPTION_PSERIES(vec, label, h) | ||
206 | |||
207 | #define MASKABLE_EXCEPTION_PSERIES(loc, vec, label) \ | ||
208 | . = loc; \ | ||
209 | .globl label##_pSeries; \ | ||
210 | label##_pSeries: \ | ||
211 | _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_STD) | ||
212 | |||
213 | #define MASKABLE_EXCEPTION_HV(loc, vec, label) \ | ||
214 | . = loc; \ | ||
215 | .globl label##_hv; \ | ||
216 | label##_hv: \ | ||
217 | _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_HV) | ||
197 | 218 | ||
198 | #ifdef CONFIG_PPC_ISERIES | 219 | #ifdef CONFIG_PPC_ISERIES |
199 | #define DISABLE_INTS \ | 220 | #define DISABLE_INTS \ |