blob: fc3ead066cec8c8ba61e1312785e3aabfc98d5a4 [file] [log] [blame]
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +00001/*
2 * This file contains the 64-bit "server" PowerPC variant
3 * of the low level exception handling including exception
4 * vectors, exception return, part of the slb and stab
5 * handling and other fixed offset specific things.
6 *
7 * This file is meant to be #included from head_64.S due to
8 * position dependant assembly.
9 *
10 * Most of this originates from head_64.S and thus has the same
11 * copyright history.
12 *
13 */
14
Benjamin Herrenschmidt8aa34ab2009-07-14 20:52:52 +000015#include <asm/exception-64s.h>
16
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000017/*
18 * We layout physical memory as follows:
19 * 0x0000 - 0x00ff : Secondary processor spin code
20 * 0x0100 - 0x2fff : pSeries Interrupt prologs
21 * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs
22 * 0x6000 - 0x6fff : Initial (CPU0) segment table
23 * 0x7000 - 0x7fff : FWNMI data area
24 * 0x8000 - : Early init and support code
25 */
26
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000027/*
28 * This is the start of the interrupt handlers for pSeries
29 * This code runs with relocation off.
30 * Code from here to __end_interrupts gets copied down to real
31 * address 0x100 when we are running a relocatable kernel.
32 * Therefore any relative branches in this section must only
33 * branch to labels in this section.
34 */
35 . = 0x100
36 .globl __start_interrupts
37__start_interrupts:
38
39 STD_EXCEPTION_PSERIES(0x100, system_reset)
40
41 . = 0x200
42_machine_check_pSeries:
43 HMT_MEDIUM
Alexander Graf842f2fe2009-10-30 05:47:17 +000044 DO_KVM 0x200
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +000045 mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000046 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
47
48 . = 0x300
49 .globl data_access_pSeries
50data_access_pSeries:
51 HMT_MEDIUM
Alexander Graf842f2fe2009-10-30 05:47:17 +000052 DO_KVM 0x300
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +000053 mtspr SPRN_SPRG_SCRATCH0,r13
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000054BEGIN_FTR_SECTION
Benjamin Herrenschmidtc5a8c0c2009-07-16 19:36:57 +000055 mfspr r13,SPRN_SPRG_PACA
56 std r9,PACA_EXSLB+EX_R9(r13)
57 std r10,PACA_EXSLB+EX_R10(r13)
58 mfspr r10,SPRN_DAR
59 mfspr r9,SPRN_DSISR
60 srdi r10,r10,60
61 rlwimi r10,r9,16,0x20
62 mfcr r9
63 cmpwi r10,0x2c
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000064 beq do_stab_bolted_pSeries
Benjamin Herrenschmidtc5a8c0c2009-07-16 19:36:57 +000065 ld r10,PACA_EXSLB+EX_R10(r13)
66 std r11,PACA_EXGEN+EX_R11(r13)
67 ld r11,PACA_EXSLB+EX_R9(r13)
68 std r12,PACA_EXGEN+EX_R12(r13)
69 mfspr r12,SPRN_SPRG_SCRATCH0
70 std r10,PACA_EXGEN+EX_R10(r13)
71 std r11,PACA_EXGEN+EX_R9(r13)
72 std r12,PACA_EXGEN+EX_R13(r13)
73 EXCEPTION_PROLOG_PSERIES_1(data_access_common)
74FTR_SECTION_ELSE
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000075 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common)
Benjamin Herrenschmidtc5a8c0c2009-07-16 19:36:57 +000076ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB)
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000077
78 . = 0x380
79 .globl data_access_slb_pSeries
80data_access_slb_pSeries:
81 HMT_MEDIUM
Alexander Graf842f2fe2009-10-30 05:47:17 +000082 DO_KVM 0x380
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +000083 mtspr SPRN_SPRG_SCRATCH0,r13
84 mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000085 std r3,PACA_EXSLB+EX_R3(r13)
86 mfspr r3,SPRN_DAR
87 std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
88 mfcr r9
89#ifdef __DISABLED__
90 /* Keep that around for when we re-implement dynamic VSIDs */
91 cmpdi r3,0
92 bge slb_miss_user_pseries
93#endif /* __DISABLED__ */
94 std r10,PACA_EXSLB+EX_R10(r13)
95 std r11,PACA_EXSLB+EX_R11(r13)
96 std r12,PACA_EXSLB+EX_R12(r13)
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +000097 mfspr r10,SPRN_SPRG_SCRATCH0
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +000098 std r10,PACA_EXSLB+EX_R13(r13)
99 mfspr r12,SPRN_SRR1 /* and SRR1 */
100#ifndef CONFIG_RELOCATABLE
101 b .slb_miss_realmode
102#else
103 /*
104 * We can't just use a direct branch to .slb_miss_realmode
105 * because the distance from here to there depends on where
106 * the kernel ends up being put.
107 */
108 mfctr r11
109 ld r10,PACAKBASE(r13)
110 LOAD_HANDLER(r10, .slb_miss_realmode)
111 mtctr r10
112 bctr
113#endif
114
115 STD_EXCEPTION_PSERIES(0x400, instruction_access)
116
117 . = 0x480
118 .globl instruction_access_slb_pSeries
119instruction_access_slb_pSeries:
120 HMT_MEDIUM
Alexander Graf842f2fe2009-10-30 05:47:17 +0000121 DO_KVM 0x480
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +0000122 mtspr SPRN_SPRG_SCRATCH0,r13
123 mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000124 std r3,PACA_EXSLB+EX_R3(r13)
125 mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
126 std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
127 mfcr r9
128#ifdef __DISABLED__
129 /* Keep that around for when we re-implement dynamic VSIDs */
130 cmpdi r3,0
131 bge slb_miss_user_pseries
132#endif /* __DISABLED__ */
133 std r10,PACA_EXSLB+EX_R10(r13)
134 std r11,PACA_EXSLB+EX_R11(r13)
135 std r12,PACA_EXSLB+EX_R12(r13)
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +0000136 mfspr r10,SPRN_SPRG_SCRATCH0
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000137 std r10,PACA_EXSLB+EX_R13(r13)
138 mfspr r12,SPRN_SRR1 /* and SRR1 */
139#ifndef CONFIG_RELOCATABLE
140 b .slb_miss_realmode
141#else
142 mfctr r11
143 ld r10,PACAKBASE(r13)
144 LOAD_HANDLER(r10, .slb_miss_realmode)
145 mtctr r10
146 bctr
147#endif
148
149 MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
150 STD_EXCEPTION_PSERIES(0x600, alignment)
151 STD_EXCEPTION_PSERIES(0x700, program_check)
152 STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
153 MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
154 STD_EXCEPTION_PSERIES(0xa00, trap_0a)
155 STD_EXCEPTION_PSERIES(0xb00, trap_0b)
156
157 . = 0xc00
158 .globl system_call_pSeries
159system_call_pSeries:
160 HMT_MEDIUM
Alexander Graf842f2fe2009-10-30 05:47:17 +0000161 DO_KVM 0xc00
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000162BEGIN_FTR_SECTION
163 cmpdi r0,0x1ebe
164 beq- 1f
165END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
166 mr r9,r13
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +0000167 mfspr r13,SPRN_SPRG_PACA
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000168 mfspr r11,SPRN_SRR0
169 ld r12,PACAKBASE(r13)
170 ld r10,PACAKMSR(r13)
171 LOAD_HANDLER(r12, system_call_entry)
172 mtspr SPRN_SRR0,r12
173 mfspr r12,SPRN_SRR1
174 mtspr SPRN_SRR1,r10
175 rfid
176 b . /* prevent speculative execution */
177
178/* Fast LE/BE switch system call */
1791: mfspr r12,SPRN_SRR1
180 xori r12,r12,MSR_LE
181 mtspr SPRN_SRR1,r12
182 rfid /* return to userspace */
183 b .
184
185 STD_EXCEPTION_PSERIES(0xd00, single_step)
186 STD_EXCEPTION_PSERIES(0xe00, trap_0e)
187
188 /* We need to deal with the Altivec unavailable exception
189 * here which is at 0xf20, thus in the middle of the
190 * prolog code of the PerformanceMonitor one. A little
191 * trickery is thus necessary
192 */
193 . = 0xf00
Alexander Graf842f2fe2009-10-30 05:47:17 +0000194 DO_KVM 0xf00
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000195 b performance_monitor_pSeries
196
197 . = 0xf20
Alexander Graf842f2fe2009-10-30 05:47:17 +0000198 DO_KVM 0xf20
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000199 b altivec_unavailable_pSeries
200
201 . = 0xf40
Alexander Graf842f2fe2009-10-30 05:47:17 +0000202 DO_KVM 0xf40
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000203 b vsx_unavailable_pSeries
204
205#ifdef CONFIG_CBE_RAS
206 HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
207#endif /* CONFIG_CBE_RAS */
208 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
209#ifdef CONFIG_CBE_RAS
210 HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
211#endif /* CONFIG_CBE_RAS */
212 STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
213#ifdef CONFIG_CBE_RAS
214 HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
215#endif /* CONFIG_CBE_RAS */
216
217 . = 0x3000
218
219/*** pSeries interrupt support ***/
220
221 /* moved from 0xf00 */
222 STD_EXCEPTION_PSERIES(., performance_monitor)
223 STD_EXCEPTION_PSERIES(., altivec_unavailable)
224 STD_EXCEPTION_PSERIES(., vsx_unavailable)
225
226/*
227 * An interrupt came in while soft-disabled; clear EE in SRR1,
228 * clear paca->hard_enabled and return.
229 */
230masked_interrupt:
231 stb r10,PACAHARDIRQEN(r13)
232 mtcrf 0x80,r9
233 ld r9,PACA_EXGEN+EX_R9(r13)
234 mfspr r10,SPRN_SRR1
235 rldicl r10,r10,48,1 /* clear MSR_EE */
236 rotldi r10,r10,16
237 mtspr SPRN_SRR1,r10
238 ld r10,PACA_EXGEN+EX_R10(r13)
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +0000239 mfspr r13,SPRN_SPRG_SCRATCH0
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000240 rfid
241 b .
242
243 .align 7
244do_stab_bolted_pSeries:
Benjamin Herrenschmidtc5a8c0c2009-07-16 19:36:57 +0000245 std r11,PACA_EXSLB+EX_R11(r13)
246 std r12,PACA_EXSLB+EX_R12(r13)
247 mfspr r10,SPRN_SPRG_SCRATCH0
248 std r10,PACA_EXSLB+EX_R13(r13)
249 EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted)
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000250
251#ifdef CONFIG_PPC_PSERIES
252/*
253 * Vectors for the FWNMI option. Share common code.
254 */
255 .globl system_reset_fwnmi
256 .align 7
257system_reset_fwnmi:
258 HMT_MEDIUM
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +0000259 mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000260 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
261
262 .globl machine_check_fwnmi
263 .align 7
264machine_check_fwnmi:
265 HMT_MEDIUM
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +0000266 mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000267 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
268
269#endif /* CONFIG_PPC_PSERIES */
270
271#ifdef __DISABLED__
272/*
273 * This is used for when the SLB miss handler has to go virtual,
274 * which doesn't happen for now anymore but will once we re-implement
275 * dynamic VSIDs for shared page tables
276 */
277slb_miss_user_pseries:
278 std r10,PACA_EXGEN+EX_R10(r13)
279 std r11,PACA_EXGEN+EX_R11(r13)
280 std r12,PACA_EXGEN+EX_R12(r13)
Benjamin Herrenschmidtee43eb72009-07-14 20:52:54 +0000281 mfspr r10,SPRG_SCRATCH0
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000282 ld r11,PACA_EXSLB+EX_R9(r13)
283 ld r12,PACA_EXSLB+EX_R3(r13)
284 std r10,PACA_EXGEN+EX_R13(r13)
285 std r11,PACA_EXGEN+EX_R9(r13)
286 std r12,PACA_EXGEN+EX_R3(r13)
287 clrrdi r12,r13,32
288 mfmsr r10
289 mfspr r11,SRR0 /* save SRR0 */
290 ori r12,r12,slb_miss_user_common@l /* virt addr of handler */
291 ori r10,r10,MSR_IR|MSR_DR|MSR_RI
292 mtspr SRR0,r12
293 mfspr r12,SRR1 /* and SRR1 */
294 mtspr SRR1,r10
295 rfid
296 b . /* prevent spec. execution */
297#endif /* __DISABLED__ */
298
299 .align 7
300 .globl __end_interrupts
301__end_interrupts:
302
303/*
304 * Code from here down to __end_handlers is invoked from the
305 * exception prologs above. Because the prologs assemble the
306 * addresses of these handlers using the LOAD_HANDLER macro,
307 * which uses an addi instruction, these handlers must be in
308 * the first 32k of the kernel image.
309 */
310
311/*** Common interrupt handlers ***/
312
313 STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
314
315 /*
316 * Machine check is different because we use a different
317 * save area: PACA_EXMC instead of PACA_EXGEN.
318 */
319 .align 7
320 .globl machine_check_common
321machine_check_common:
322 EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
323 FINISH_NAP
324 DISABLE_INTS
325 bl .save_nvgprs
326 addi r3,r1,STACK_FRAME_OVERHEAD
327 bl .machine_check_exception
328 b .ret_from_except
329
330 STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt)
331 STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)
332 STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
333 STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
334 STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
335 STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)
336 STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
337#ifdef CONFIG_ALTIVEC
338 STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
339#else
340 STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
341#endif
342#ifdef CONFIG_CBE_RAS
343 STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
344 STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
345 STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
346#endif /* CONFIG_CBE_RAS */
347
348 .align 7
349system_call_entry:
350 b system_call_common
351
352/*
353 * Here we have detected that the kernel stack pointer is bad.
354 * R9 contains the saved CR, r13 points to the paca,
355 * r10 contains the (bad) kernel stack pointer,
356 * r11 and r12 contain the saved SRR0 and SRR1.
357 * We switch to using an emergency stack, save the registers there,
358 * and call kernel_bad_stack(), which panics.
359 */
360bad_stack:
361 ld r1,PACAEMERGSP(r13)
362 subi r1,r1,64+INT_FRAME_SIZE
363 std r9,_CCR(r1)
364 std r10,GPR1(r1)
365 std r11,_NIP(r1)
366 std r12,_MSR(r1)
367 mfspr r11,SPRN_DAR
368 mfspr r12,SPRN_DSISR
369 std r11,_DAR(r1)
370 std r12,_DSISR(r1)
371 mflr r10
372 mfctr r11
373 mfxer r12
374 std r10,_LINK(r1)
375 std r11,_CTR(r1)
376 std r12,_XER(r1)
377 SAVE_GPR(0,r1)
378 SAVE_GPR(2,r1)
379 SAVE_4GPRS(3,r1)
380 SAVE_2GPRS(7,r1)
381 SAVE_10GPRS(12,r1)
382 SAVE_10GPRS(22,r1)
383 lhz r12,PACA_TRAP_SAVE(r13)
384 std r12,_TRAP(r1)
385 addi r11,r1,INT_FRAME_SIZE
386 std r11,0(r1)
387 li r12,0
388 std r12,0(r11)
389 ld r2,PACATOC(r13)
3901: addi r3,r1,STACK_FRAME_OVERHEAD
391 bl .kernel_bad_stack
392 b 1b
393
394/*
395 * Here r13 points to the paca, r9 contains the saved CR,
396 * SRR0 and SRR1 are saved in r11 and r12,
397 * r9 - r13 are saved in paca->exgen.
398 */
399 .align 7
400 .globl data_access_common
401data_access_common:
402 mfspr r10,SPRN_DAR
403 std r10,PACA_EXGEN+EX_DAR(r13)
404 mfspr r10,SPRN_DSISR
405 stw r10,PACA_EXGEN+EX_DSISR(r13)
406 EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
407 ld r3,PACA_EXGEN+EX_DAR(r13)
408 lwz r4,PACA_EXGEN+EX_DSISR(r13)
409 li r5,0x300
410 b .do_hash_page /* Try to handle as hpte fault */
411
412 .align 7
413 .globl instruction_access_common
414instruction_access_common:
415 EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
416 ld r3,_NIP(r1)
417 andis. r4,r12,0x5820
418 li r5,0x400
419 b .do_hash_page /* Try to handle as hpte fault */
420
421/*
422 * Here is the common SLB miss user that is used when going to virtual
423 * mode for SLB misses, that is currently not used
424 */
425#ifdef __DISABLED__
426 .align 7
427 .globl slb_miss_user_common
428slb_miss_user_common:
429 mflr r10
430 std r3,PACA_EXGEN+EX_DAR(r13)
431 stw r9,PACA_EXGEN+EX_CCR(r13)
432 std r10,PACA_EXGEN+EX_LR(r13)
433 std r11,PACA_EXGEN+EX_SRR0(r13)
434 bl .slb_allocate_user
435
436 ld r10,PACA_EXGEN+EX_LR(r13)
437 ld r3,PACA_EXGEN+EX_R3(r13)
438 lwz r9,PACA_EXGEN+EX_CCR(r13)
439 ld r11,PACA_EXGEN+EX_SRR0(r13)
440 mtlr r10
441 beq- slb_miss_fault
442
443 andi. r10,r12,MSR_RI /* check for unrecoverable exception */
444 beq- unrecov_user_slb
445 mfmsr r10
446
447.machine push
448.machine "power4"
449 mtcrf 0x80,r9
450.machine pop
451
452 clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */
453 mtmsrd r10,1
454
455 mtspr SRR0,r11
456 mtspr SRR1,r12
457
458 ld r9,PACA_EXGEN+EX_R9(r13)
459 ld r10,PACA_EXGEN+EX_R10(r13)
460 ld r11,PACA_EXGEN+EX_R11(r13)
461 ld r12,PACA_EXGEN+EX_R12(r13)
462 ld r13,PACA_EXGEN+EX_R13(r13)
463 rfid
464 b .
465
466slb_miss_fault:
467 EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN)
468 ld r4,PACA_EXGEN+EX_DAR(r13)
469 li r5,0
470 std r4,_DAR(r1)
471 std r5,_DSISR(r1)
472 b handle_page_fault
473
474unrecov_user_slb:
475 EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
476 DISABLE_INTS
477 bl .save_nvgprs
4781: addi r3,r1,STACK_FRAME_OVERHEAD
479 bl .unrecoverable_exception
480 b 1b
481
482#endif /* __DISABLED__ */
483
484
485/*
486 * r13 points to the PACA, r9 contains the saved CR,
487 * r12 contain the saved SRR1, SRR0 is still ready for return
488 * r3 has the faulting address
489 * r9 - r13 are saved in paca->exslb.
490 * r3 is saved in paca->slb_r3
491 * We assume we aren't going to take any exceptions during this procedure.
492 */
493_GLOBAL(slb_miss_realmode)
494 mflr r10
495#ifdef CONFIG_RELOCATABLE
496 mtctr r11
497#endif
498
499 stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
500 std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
501
502 bl .slb_allocate_realmode
503
504 /* All done -- return from exception. */
505
506 ld r10,PACA_EXSLB+EX_LR(r13)
507 ld r3,PACA_EXSLB+EX_R3(r13)
508 lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
509#ifdef CONFIG_PPC_ISERIES
510BEGIN_FW_FTR_SECTION
511 ld r11,PACALPPACAPTR(r13)
512 ld r11,LPPACASRR0(r11) /* get SRR0 value */
513END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
514#endif /* CONFIG_PPC_ISERIES */
515
516 mtlr r10
517
518 andi. r10,r12,MSR_RI /* check for unrecoverable exception */
519 beq- 2f
520
521.machine push
522.machine "power4"
523 mtcrf 0x80,r9
524 mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
525.machine pop
526
527#ifdef CONFIG_PPC_ISERIES
528BEGIN_FW_FTR_SECTION
529 mtspr SPRN_SRR0,r11
530 mtspr SPRN_SRR1,r12
531END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
532#endif /* CONFIG_PPC_ISERIES */
533 ld r9,PACA_EXSLB+EX_R9(r13)
534 ld r10,PACA_EXSLB+EX_R10(r13)
535 ld r11,PACA_EXSLB+EX_R11(r13)
536 ld r12,PACA_EXSLB+EX_R12(r13)
537 ld r13,PACA_EXSLB+EX_R13(r13)
538 rfid
539 b . /* prevent speculative execution */
540
5412:
542#ifdef CONFIG_PPC_ISERIES
543BEGIN_FW_FTR_SECTION
544 b unrecov_slb
545END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
546#endif /* CONFIG_PPC_ISERIES */
547 mfspr r11,SPRN_SRR0
548 ld r10,PACAKBASE(r13)
549 LOAD_HANDLER(r10,unrecov_slb)
550 mtspr SPRN_SRR0,r10
551 ld r10,PACAKMSR(r13)
552 mtspr SPRN_SRR1,r10
553 rfid
554 b .
555
556unrecov_slb:
557 EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
558 DISABLE_INTS
559 bl .save_nvgprs
5601: addi r3,r1,STACK_FRAME_OVERHEAD
561 bl .unrecoverable_exception
562 b 1b
563
564 .align 7
565 .globl hardware_interrupt_common
566 .globl hardware_interrupt_entry
567hardware_interrupt_common:
568 EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
569 FINISH_NAP
570hardware_interrupt_entry:
571 DISABLE_INTS
572BEGIN_FTR_SECTION
573 bl .ppc64_runlatch_on
574END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
575 addi r3,r1,STACK_FRAME_OVERHEAD
576 bl .do_IRQ
577 b .ret_from_except_lite
578
579#ifdef CONFIG_PPC_970_NAP
580power4_fixup_nap:
581 andc r9,r9,r10
582 std r9,TI_LOCAL_FLAGS(r11)
583 ld r10,_LINK(r1) /* make idle task do the */
584 std r10,_NIP(r1) /* equivalent of a blr */
585 blr
586#endif
587
588 .align 7
589 .globl alignment_common
590alignment_common:
591 mfspr r10,SPRN_DAR
592 std r10,PACA_EXGEN+EX_DAR(r13)
593 mfspr r10,SPRN_DSISR
594 stw r10,PACA_EXGEN+EX_DSISR(r13)
595 EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)
596 ld r3,PACA_EXGEN+EX_DAR(r13)
597 lwz r4,PACA_EXGEN+EX_DSISR(r13)
598 std r3,_DAR(r1)
599 std r4,_DSISR(r1)
600 bl .save_nvgprs
601 addi r3,r1,STACK_FRAME_OVERHEAD
602 ENABLE_INTS
603 bl .alignment_exception
604 b .ret_from_except
605
606 .align 7
607 .globl program_check_common
608program_check_common:
609 EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
610 bl .save_nvgprs
611 addi r3,r1,STACK_FRAME_OVERHEAD
612 ENABLE_INTS
613 bl .program_check_exception
614 b .ret_from_except
615
616 .align 7
617 .globl fp_unavailable_common
618fp_unavailable_common:
619 EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
620 bne 1f /* if from user, just load it up */
621 bl .save_nvgprs
622 addi r3,r1,STACK_FRAME_OVERHEAD
623 ENABLE_INTS
624 bl .kernel_fp_unavailable_exception
625 BUG_OPCODE
6261: bl .load_up_fpu
627 b fast_exception_return
628
629 .align 7
630 .globl altivec_unavailable_common
631altivec_unavailable_common:
632 EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)
633#ifdef CONFIG_ALTIVEC
634BEGIN_FTR_SECTION
635 beq 1f
636 bl .load_up_altivec
637 b fast_exception_return
6381:
639END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
640#endif
641 bl .save_nvgprs
642 addi r3,r1,STACK_FRAME_OVERHEAD
643 ENABLE_INTS
644 bl .altivec_unavailable_exception
645 b .ret_from_except
646
647 .align 7
648 .globl vsx_unavailable_common
649vsx_unavailable_common:
650 EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
651#ifdef CONFIG_VSX
652BEGIN_FTR_SECTION
653 bne .load_up_vsx
6541:
655END_FTR_SECTION_IFSET(CPU_FTR_VSX)
656#endif
657 bl .save_nvgprs
658 addi r3,r1,STACK_FRAME_OVERHEAD
659 ENABLE_INTS
660 bl .vsx_unavailable_exception
661 b .ret_from_except
662
663 .align 7
664 .globl __end_handlers
665__end_handlers:
666
667/*
668 * Return from an exception with minimal checks.
669 * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
670 * If interrupts have been enabled, or anything has been
671 * done that might have changed the scheduling status of
672 * any task or sent any task a signal, you should use
673 * ret_from_except or ret_from_except_lite instead of this.
674 */
675fast_exc_return_irq: /* restores irq state too */
676 ld r3,SOFTE(r1)
677 TRACE_AND_RESTORE_IRQ(r3);
678 ld r12,_MSR(r1)
679 rldicl r4,r12,49,63 /* get MSR_EE to LSB */
680 stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */
681 b 1f
682
683 .globl fast_exception_return
684fast_exception_return:
685 ld r12,_MSR(r1)
6861: ld r11,_NIP(r1)
687 andi. r3,r12,MSR_RI /* check if RI is set */
688 beq- unrecov_fer
689
690#ifdef CONFIG_VIRT_CPU_ACCOUNTING
691 andi. r3,r12,MSR_PR
692 beq 2f
693 ACCOUNT_CPU_USER_EXIT(r3, r4)
6942:
695#endif
696
697 ld r3,_CCR(r1)
698 ld r4,_LINK(r1)
699 ld r5,_CTR(r1)
700 ld r6,_XER(r1)
701 mtcr r3
702 mtlr r4
703 mtctr r5
704 mtxer r6
705 REST_GPR(0, r1)
706 REST_8GPRS(2, r1)
707
708 mfmsr r10
709 rldicl r10,r10,48,1 /* clear EE */
710 rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */
711 mtmsrd r10,1
712
713 mtspr SPRN_SRR1,r12
714 mtspr SPRN_SRR0,r11
715 REST_4GPRS(10, r1)
716 ld r1,GPR1(r1)
717 rfid
718 b . /* prevent speculative execution */
719
720unrecov_fer:
721 bl .save_nvgprs
7221: addi r3,r1,STACK_FRAME_OVERHEAD
723 bl .unrecoverable_exception
724 b 1b
725
726
727/*
728 * Hash table stuff
729 */
730 .align 7
731_STATIC(do_hash_page)
732 std r3,_DAR(r1)
733 std r4,_DSISR(r1)
734
735 andis. r0,r4,0xa450 /* weird error? */
736 bne- handle_page_fault /* if not, try to insert a HPTE */
737BEGIN_FTR_SECTION
738 andis. r0,r4,0x0020 /* Is it a segment table fault? */
739 bne- do_ste_alloc /* If so handle it */
740END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
741
Paul Mackerras9c1e1052009-08-17 15:17:54 +1000742 clrrdi r11,r1,THREAD_SHIFT
743 lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */
744 andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */
745 bne 77f /* then don't call hash_page now */
746
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000747 /*
748 * On iSeries, we soft-disable interrupts here, then
749 * hard-enable interrupts so that the hash_page code can spin on
750 * the hash_table_lock without problems on a shared processor.
751 */
752 DISABLE_INTS
753
754 /*
755 * Currently, trace_hardirqs_off() will be called by DISABLE_INTS
756 * and will clobber volatile registers when irq tracing is enabled
757 * so we need to reload them. It may be possible to be smarter here
758 * and move the irq tracing elsewhere but let's keep it simple for
759 * now
760 */
761#ifdef CONFIG_TRACE_IRQFLAGS
762 ld r3,_DAR(r1)
763 ld r4,_DSISR(r1)
764 ld r5,_TRAP(r1)
765 ld r12,_MSR(r1)
766 clrrdi r5,r5,4
767#endif /* CONFIG_TRACE_IRQFLAGS */
768 /*
769 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
770 * accessing a userspace segment (even from the kernel). We assume
771 * kernel addresses always have the high bit set.
772 */
773 rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */
774 rotldi r0,r3,15 /* Move high bit into MSR_PR posn */
775 orc r0,r12,r0 /* MSR_PR | ~high_bit */
776 rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */
777 ori r4,r4,1 /* add _PAGE_PRESENT */
778 rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */
779
780 /*
781 * r3 contains the faulting address
782 * r4 contains the required access permissions
783 * r5 contains the trap number
784 *
785 * at return r3 = 0 for success
786 */
787 bl .hash_page /* build HPTE if possible */
788 cmpdi r3,0 /* see if hash_page succeeded */
789
790BEGIN_FW_FTR_SECTION
791 /*
792 * If we had interrupts soft-enabled at the point where the
793 * DSI/ISI occurred, and an interrupt came in during hash_page,
794 * handle it now.
795 * We jump to ret_from_except_lite rather than fast_exception_return
796 * because ret_from_except_lite will check for and handle pending
797 * interrupts if necessary.
798 */
799 beq 13f
800END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
801
802BEGIN_FW_FTR_SECTION
803 /*
804 * Here we have interrupts hard-disabled, so it is sufficient
805 * to restore paca->{soft,hard}_enable and get out.
806 */
807 beq fast_exc_return_irq /* Return from exception on success */
808END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
809
810 /* For a hash failure, we don't bother re-enabling interrupts */
811 ble- 12f
812
813 /*
814 * hash_page couldn't handle it, set soft interrupt enable back
815 * to what it was before the trap. Note that .raw_local_irq_restore
816 * handles any interrupts pending at this point.
817 */
818 ld r3,SOFTE(r1)
819 TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
820 bl .raw_local_irq_restore
821 b 11f
822
823/* Here we have a page fault that hash_page can't handle. */
824handle_page_fault:
825 ENABLE_INTS
82611: ld r4,_DAR(r1)
827 ld r5,_DSISR(r1)
828 addi r3,r1,STACK_FRAME_OVERHEAD
829 bl .do_page_fault
830 cmpdi r3,0
831 beq+ 13f
832 bl .save_nvgprs
833 mr r5,r3
834 addi r3,r1,STACK_FRAME_OVERHEAD
835 lwz r4,_DAR(r1)
836 bl .bad_page_fault
837 b .ret_from_except
838
83913: b .ret_from_except_lite
840
841/* We have a page fault that hash_page could handle but HV refused
842 * the PTE insertion
843 */
84412: bl .save_nvgprs
845 mr r5,r3
846 addi r3,r1,STACK_FRAME_OVERHEAD
847 ld r4,_DAR(r1)
848 bl .low_hash_fault
849 b .ret_from_except
850
Paul Mackerras9c1e1052009-08-17 15:17:54 +1000851/*
852 * We come here as a result of a DSI at a point where we don't want
853 * to call hash_page, such as when we are accessing memory (possibly
854 * user memory) inside a PMU interrupt that occurred while interrupts
855 * were soft-disabled. We want to invoke the exception handler for
856 * the access, or panic if there isn't a handler.
857 */
85877: bl .save_nvgprs
859 mr r4,r3
860 addi r3,r1,STACK_FRAME_OVERHEAD
861 li r5,SIGSEGV
862 bl .bad_page_fault
863 b .ret_from_except
864
Benjamin Herrenschmidt0ebc4cd2009-06-02 21:17:38 +0000865 /* here we have a segment miss */
866do_ste_alloc:
867 bl .ste_allocate /* try to insert stab entry */
868 cmpdi r3,0
869 bne- handle_page_fault
870 b fast_exception_return
871
872/*
873 * r13 points to the PACA, r9 contains the saved CR,
874 * r11 and r12 contain the saved SRR0 and SRR1.
875 * r9 - r13 are saved in paca->exslb.
876 * We assume we aren't going to take any exceptions during this procedure.
877 * We assume (DAR >> 60) == 0xc.
878 */
879 .align 7
880_GLOBAL(do_stab_bolted)
881 stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
882 std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */
883
884 /* Hash to the primary group */
885 ld r10,PACASTABVIRT(r13)
886 mfspr r11,SPRN_DAR
887 srdi r11,r11,28
888 rldimi r10,r11,7,52 /* r10 = first ste of the group */
889
890 /* Calculate VSID */
891 /* This is a kernel address, so protovsid = ESID */
892 ASM_VSID_SCRAMBLE(r11, r9, 256M)
893 rldic r9,r11,12,16 /* r9 = vsid << 12 */
894
895 /* Search the primary group for a free entry */
8961: ld r11,0(r10) /* Test valid bit of the current ste */
897 andi. r11,r11,0x80
898 beq 2f
899 addi r10,r10,16
900 andi. r11,r10,0x70
901 bne 1b
902
903 /* Stick for only searching the primary group for now. */
904 /* At least for now, we use a very simple random castout scheme */
905 /* Use the TB as a random number ; OR in 1 to avoid entry 0 */
906 mftb r11
907 rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */
908 ori r11,r11,0x10
909
910 /* r10 currently points to an ste one past the group of interest */
911 /* make it point to the randomly selected entry */
912 subi r10,r10,128
913 or r10,r10,r11 /* r10 is the entry to invalidate */
914
915 isync /* mark the entry invalid */
916 ld r11,0(r10)
917 rldicl r11,r11,56,1 /* clear the valid bit */
918 rotldi r11,r11,8
919 std r11,0(r10)
920 sync
921
922 clrrdi r11,r11,28 /* Get the esid part of the ste */
923 slbie r11
924
9252: std r9,8(r10) /* Store the vsid part of the ste */
926 eieio
927
928 mfspr r11,SPRN_DAR /* Get the new esid */
929 clrrdi r11,r11,28 /* Permits a full 32b of ESID */
930 ori r11,r11,0x90 /* Turn on valid and kp */
931 std r11,0(r10) /* Put new entry back into the stab */
932
933 sync
934
935 /* All done -- return from exception. */
936 lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
937 ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */
938
939 andi. r10,r12,MSR_RI
940 beq- unrecov_slb
941
942 mtcrf 0x80,r9 /* restore CR */
943
944 mfmsr r10
945 clrrdi r10,r10,2
946 mtmsrd r10,1
947
948 mtspr SPRN_SRR0,r11
949 mtspr SPRN_SRR1,r12
950 ld r9,PACA_EXSLB+EX_R9(r13)
951 ld r10,PACA_EXSLB+EX_R10(r13)
952 ld r11,PACA_EXSLB+EX_R11(r13)
953 ld r12,PACA_EXSLB+EX_R12(r13)
954 ld r13,PACA_EXSLB+EX_R13(r13)
955 rfid
956 b . /* prevent speculative execution */
957
958/*
959 * Space for CPU0's segment table.
960 *
961 * On iSeries, the hypervisor must fill in at least one entry before
962 * we get control (with relocate on). The address is given to the hv
963 * as a page number (see xLparMap below), so this must be at a
964 * fixed address (the linker can't compute (u64)&initial_stab >>
965 * PAGE_SHIFT).
966 */
967 . = STAB0_OFFSET /* 0x6000 */
968 .globl initial_stab
969initial_stab:
970 .space 4096
971
972#ifdef CONFIG_PPC_PSERIES
973/*
974 * Data area reserved for FWNMI option.
975 * This address (0x7000) is fixed by the RPA.
976 */
977 .= 0x7000
978 .globl fwnmi_data_area
979fwnmi_data_area:
980#endif /* CONFIG_PPC_PSERIES */
981
982 /* iSeries does not use the FWNMI stuff, so it is safe to put
983 * this here, even if we later allow kernels that will boot on
984 * both pSeries and iSeries */
985#ifdef CONFIG_PPC_ISERIES
986 . = LPARMAP_PHYS
987 .globl xLparMap
988xLparMap:
989 .quad HvEsidsToMap /* xNumberEsids */
990 .quad HvRangesToMap /* xNumberRanges */
991 .quad STAB0_PAGE /* xSegmentTableOffs */
992 .zero 40 /* xRsvd */
993 /* xEsids (HvEsidsToMap entries of 2 quads) */
994 .quad PAGE_OFFSET_ESID /* xKernelEsid */
995 .quad PAGE_OFFSET_VSID /* xKernelVsid */
996 .quad VMALLOC_START_ESID /* xKernelEsid */
997 .quad VMALLOC_START_VSID /* xKernelVsid */
998 /* xRanges (HvRangesToMap entries of 3 quads) */
999 .quad HvPagesToMap /* xPages */
1000 .quad 0 /* xOffset */
1001 .quad PAGE_OFFSET_VSID << (SID_SHIFT - HW_PAGE_SHIFT) /* xVPN */
1002
1003#endif /* CONFIG_PPC_ISERIES */
1004
1005#ifdef CONFIG_PPC_PSERIES
1006 . = 0x8000
1007#endif /* CONFIG_PPC_PSERIES */