diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-04-05 00:27:11 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-04-19 21:03:23 -0400 |
commit | b3e6b5dfcf0974069a8ddcce7dd071120d20d79c (patch) | |
tree | 96b8b9446ad134d9aab9021d97c292c0fafd8e90 /arch/powerpc/kernel/exceptions-64s.S | |
parent | a5d4f3ad3a28cf046836b9bfae61d532b8f77036 (diff) |
powerpc: More work to support HV exceptions
Rework exception macros a bit to split offset from vector and add
some basic support for HDEC, HDSI, HISI and a few more.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64s.S')
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 17f1d6670635..805e20657868 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -37,7 +37,7 @@ | |||
37 | .globl __start_interrupts | 37 | .globl __start_interrupts |
38 | __start_interrupts: | 38 | __start_interrupts: |
39 | 39 | ||
40 | STD_EXCEPTION_PSERIES(0x100, system_reset) | 40 | STD_EXCEPTION_PSERIES(0x100, 0x100, system_reset) |
41 | 41 | ||
42 | . = 0x200 | 42 | . = 0x200 |
43 | _machine_check_pSeries: | 43 | _machine_check_pSeries: |
@@ -113,7 +113,7 @@ data_access_slb_pSeries: | |||
113 | bctr | 113 | bctr |
114 | #endif | 114 | #endif |
115 | 115 | ||
116 | STD_EXCEPTION_PSERIES(0x400, instruction_access) | 116 | STD_EXCEPTION_PSERIES(0x400, 0x400, instruction_access) |
117 | 117 | ||
118 | . = 0x480 | 118 | . = 0x480 |
119 | .globl instruction_access_slb_pSeries | 119 | .globl instruction_access_slb_pSeries |
@@ -147,26 +147,29 @@ instruction_access_slb_pSeries: | |||
147 | bctr | 147 | bctr |
148 | #endif | 148 | #endif |
149 | 149 | ||
150 | /* We open code these as we can't have a ". = x" (even with | ||
151 | * x = "." within a feature section | ||
152 | */ | ||
150 | . = 0x500; | 153 | . = 0x500; |
151 | .globl hardware_interrupt_pSeries | 154 | .globl hardware_interrupt_pSeries; |
155 | .globl hardware_interrupt_hv; | ||
152 | hardware_interrupt_pSeries: | 156 | hardware_interrupt_pSeries: |
157 | hardware_interrupt_hv: | ||
153 | BEGIN_FTR_SECTION | 158 | BEGIN_FTR_SECTION |
154 | MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD) | 159 | _MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD) |
155 | FTR_SECTION_ELSE | 160 | FTR_SECTION_ELSE |
156 | MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV) | 161 | _MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV) |
157 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_HVMODE_206) | 162 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_HVMODE_206) |
158 | 163 | ||
159 | STD_EXCEPTION_PSERIES(0x600, alignment) | 164 | STD_EXCEPTION_PSERIES(0x600, 0x600, alignment) |
160 | STD_EXCEPTION_PSERIES(0x700, program_check) | 165 | STD_EXCEPTION_PSERIES(0x700, 0x700, program_check) |
161 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) | 166 | STD_EXCEPTION_PSERIES(0x800, 0x800, fp_unavailable) |
162 | 167 | ||
163 | . = 0x900; | 168 | MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer) |
164 | .globl decrementer_pSeries | 169 | MASKABLE_EXCEPTION_HV(0x980, 0x980, decrementer) |
165 | decrementer_pSeries: | ||
166 | MASKABLE_EXCEPTION_PSERIES(0x900, decrementer, EXC_STD) | ||
167 | 170 | ||
168 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) | 171 | STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a) |
169 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) | 172 | STD_EXCEPTION_PSERIES(0xb00, 0xb00, trap_0b) |
170 | 173 | ||
171 | . = 0xc00 | 174 | . = 0xc00 |
172 | .globl system_call_pSeries | 175 | .globl system_call_pSeries |
@@ -196,8 +199,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) | |||
196 | rfid /* return to userspace */ | 199 | rfid /* return to userspace */ |
197 | b . | 200 | b . |
198 | 201 | ||
199 | STD_EXCEPTION_PSERIES(0xd00, single_step) | 202 | STD_EXCEPTION_PSERIES(0xd00, 0xd00, single_step) |
200 | STD_EXCEPTION_PSERIES(0xe00, trap_0e) | 203 | |
204 | /* At 0xe??? we have a bunch of hypervisor exceptions, we branch | ||
205 | * out of line to handle them | ||
206 | */ | ||
207 | . = 0xe00 | ||
208 | b h_data_storage_hv | ||
209 | . = 0xe20 | ||
210 | b h_instr_storage_hv | ||
211 | . = 0xe40 | ||
212 | b emulation_assist_hv | ||
213 | . = 0xe50 | ||
214 | b hmi_exception_hv | ||
215 | . = 0xe60 | ||
216 | b hmi_exception_hv | ||
201 | 217 | ||
202 | /* We need to deal with the Altivec unavailable exception | 218 | /* We need to deal with the Altivec unavailable exception |
203 | * here which is at 0xf20, thus in the middle of the | 219 | * here which is at 0xf20, thus in the middle of the |
@@ -206,39 +222,42 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) | |||
206 | */ | 222 | */ |
207 | performance_monitor_pSeries_1: | 223 | performance_monitor_pSeries_1: |
208 | . = 0xf00 | 224 | . = 0xf00 |
209 | DO_KVM 0xf00 | ||
210 | b performance_monitor_pSeries | 225 | b performance_monitor_pSeries |
211 | 226 | ||
212 | altivec_unavailable_pSeries_1: | 227 | altivec_unavailable_pSeries_1: |
213 | . = 0xf20 | 228 | . = 0xf20 |
214 | DO_KVM 0xf20 | ||
215 | b altivec_unavailable_pSeries | 229 | b altivec_unavailable_pSeries |
216 | 230 | ||
217 | vsx_unavailable_pSeries_1: | 231 | vsx_unavailable_pSeries_1: |
218 | . = 0xf40 | 232 | . = 0xf40 |
219 | DO_KVM 0xf40 | ||
220 | b vsx_unavailable_pSeries | 233 | b vsx_unavailable_pSeries |
221 | 234 | ||
222 | #ifdef CONFIG_CBE_RAS | 235 | #ifdef CONFIG_CBE_RAS |
223 | HSTD_EXCEPTION_PSERIES(0x1202, cbe_system_error) | 236 | STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error) |
224 | #endif /* CONFIG_CBE_RAS */ | 237 | #endif /* CONFIG_CBE_RAS */ |
225 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) | 238 | STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint) |
226 | #ifdef CONFIG_CBE_RAS | 239 | #ifdef CONFIG_CBE_RAS |
227 | HSTD_EXCEPTION_PSERIES(0x1602, cbe_maintenance) | 240 | STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance) |
228 | #endif /* CONFIG_CBE_RAS */ | 241 | #endif /* CONFIG_CBE_RAS */ |
229 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) | 242 | STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist) |
230 | #ifdef CONFIG_CBE_RAS | 243 | #ifdef CONFIG_CBE_RAS |
231 | HSTD_EXCEPTION_PSERIES(0x1802, cbe_thermal) | 244 | STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal) |
232 | #endif /* CONFIG_CBE_RAS */ | 245 | #endif /* CONFIG_CBE_RAS */ |
233 | 246 | ||
234 | . = 0x3000 | 247 | . = 0x3000 |
235 | 248 | ||
236 | /*** pSeries interrupt support ***/ | 249 | /*** Out of line interrupts support ***/ |
250 | |||
251 | /* moved from 0xe00 */ | ||
252 | STD_EXCEPTION_HV(., 0xe00, h_data_storage) | ||
253 | STD_EXCEPTION_HV(., 0xe20, h_instr_storage) | ||
254 | STD_EXCEPTION_HV(., 0xe40, emulation_assist) | ||
255 | STD_EXCEPTION_HV(., 0xe60, hmi_exception) /* need to flush cache ? */ | ||
237 | 256 | ||
238 | /* moved from 0xf00 */ | 257 | /* moved from 0xf00 */ |
239 | STD_EXCEPTION_PSERIES(., performance_monitor) | 258 | STD_EXCEPTION_PSERIES(., 0xf00, performance_monitor) |
240 | STD_EXCEPTION_PSERIES(., altivec_unavailable) | 259 | STD_EXCEPTION_PSERIES(., 0xf20, altivec_unavailable) |
241 | STD_EXCEPTION_PSERIES(., vsx_unavailable) | 260 | STD_EXCEPTION_PSERIES(., 0xf40, vsx_unavailable) |
242 | 261 | ||
243 | /* | 262 | /* |
244 | * An interrupt came in while soft-disabled; clear EE in SRR1, | 263 | * An interrupt came in while soft-disabled; clear EE in SRR1, |
@@ -368,6 +387,8 @@ machine_check_common: | |||
368 | STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) | 387 | STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) |
369 | STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) | 388 | STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) |
370 | STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception) | 389 | STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception) |
390 | STD_EXCEPTION_COMMON(0xe40, emulation_assist, .program_check_exception) | ||
391 | STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception) | ||
371 | STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception) | 392 | STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception) |
372 | STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception) | 393 | STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception) |
373 | #ifdef CONFIG_ALTIVEC | 394 | #ifdef CONFIG_ALTIVEC |
@@ -445,6 +466,19 @@ data_access_common: | |||
445 | li r5,0x300 | 466 | li r5,0x300 |
446 | b .do_hash_page /* Try to handle as hpte fault */ | 467 | b .do_hash_page /* Try to handle as hpte fault */ |
447 | 468 | ||
469 | .align 7 | ||
470 | .globl h_data_storage_common | ||
471 | h_data_storage_common: | ||
472 | mfspr r10,SPRN_HDAR | ||
473 | std r10,PACA_EXGEN+EX_DAR(r13) | ||
474 | mfspr r10,SPRN_HDSISR | ||
475 | stw r10,PACA_EXGEN+EX_DSISR(r13) | ||
476 | EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN) | ||
477 | bl .save_nvgprs | ||
478 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
479 | bl .unknown_exception | ||
480 | b .ret_from_except | ||
481 | |||
448 | .align 7 | 482 | .align 7 |
449 | .globl instruction_access_common | 483 | .globl instruction_access_common |
450 | instruction_access_common: | 484 | instruction_access_common: |
@@ -454,6 +488,8 @@ instruction_access_common: | |||
454 | li r5,0x400 | 488 | li r5,0x400 |
455 | b .do_hash_page /* Try to handle as hpte fault */ | 489 | b .do_hash_page /* Try to handle as hpte fault */ |
456 | 490 | ||
491 | STD_EXCEPTION_COMMON(0xe20, h_instr_storage, .unknown_exception) | ||
492 | |||
457 | /* | 493 | /* |
458 | * Here is the common SLB miss user that is used when going to virtual | 494 | * Here is the common SLB miss user that is used when going to virtual |
459 | * mode for SLB misses, that is currently not used | 495 | * mode for SLB misses, that is currently not used |