diff options
Diffstat (limited to 'arch/powerpc/kernel/head_64.S')
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 604 |
1 files changed, 32 insertions, 572 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 171800002ede..97c5857faf00 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <asm/iseries/lpar_map.h> | 34 | #include <asm/iseries/lpar_map.h> |
35 | #include <asm/thread_info.h> | 35 | #include <asm/thread_info.h> |
36 | #include <asm/firmware.h> | 36 | #include <asm/firmware.h> |
37 | #include <asm/page_64.h> | ||
38 | #include <asm/exception.h> | ||
37 | 39 | ||
38 | #define DO_SOFT_DISABLE | 40 | #define DO_SOFT_DISABLE |
39 | 41 | ||
@@ -144,344 +146,9 @@ exception_marker: | |||
144 | .text | 146 | .text |
145 | 147 | ||
146 | /* | 148 | /* |
147 | * The following macros define the code that appears as | ||
148 | * the prologue to each of the exception handlers. They | ||
149 | * are split into two parts to allow a single kernel binary | ||
150 | * to be used for pSeries and iSeries. | ||
151 | * LOL. One day... - paulus | ||
152 | */ | ||
153 | |||
154 | /* | ||
155 | * We make as much of the exception code common between native | ||
156 | * exception handlers (including pSeries LPAR) and iSeries LPAR | ||
157 | * implementations as possible. | ||
158 | */ | ||
159 | |||
160 | /* | ||
161 | * This is the start of the interrupt handlers for pSeries | 149 | * This is the start of the interrupt handlers for pSeries |
162 | * This code runs with relocation off. | 150 | * This code runs with relocation off. |
163 | */ | 151 | */ |
164 | #define EX_R9 0 | ||
165 | #define EX_R10 8 | ||
166 | #define EX_R11 16 | ||
167 | #define EX_R12 24 | ||
168 | #define EX_R13 32 | ||
169 | #define EX_SRR0 40 | ||
170 | #define EX_DAR 48 | ||
171 | #define EX_DSISR 56 | ||
172 | #define EX_CCR 60 | ||
173 | #define EX_R3 64 | ||
174 | #define EX_LR 72 | ||
175 | |||
176 | /* | ||
177 | * We're short on space and time in the exception prolog, so we can't | ||
178 | * use the normal SET_REG_IMMEDIATE macro. Normally we just need the | ||
179 | * low halfword of the address, but for Kdump we need the whole low | ||
180 | * word. | ||
181 | */ | ||
182 | #ifdef CONFIG_CRASH_DUMP | ||
183 | #define LOAD_HANDLER(reg, label) \ | ||
184 | oris reg,reg,(label)@h; /* virt addr of handler ... */ \ | ||
185 | ori reg,reg,(label)@l; /* .. and the rest */ | ||
186 | #else | ||
187 | #define LOAD_HANDLER(reg, label) \ | ||
188 | ori reg,reg,(label)@l; /* virt addr of handler ... */ | ||
189 | #endif | ||
190 | |||
191 | /* | ||
192 | * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode. | ||
193 | * The firmware calls the registered system_reset_fwnmi and | ||
194 | * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run | ||
195 | * a 32bit application at the time of the event. | ||
196 | * This firmware bug is present on POWER4 and JS20. | ||
197 | */ | ||
198 | #define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label) \ | ||
199 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
200 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
201 | std r10,area+EX_R10(r13); \ | ||
202 | std r11,area+EX_R11(r13); \ | ||
203 | std r12,area+EX_R12(r13); \ | ||
204 | mfspr r9,SPRN_SPRG1; \ | ||
205 | std r9,area+EX_R13(r13); \ | ||
206 | mfcr r9; \ | ||
207 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
208 | mfmsr r10; \ | ||
209 | /* force 64bit mode */ \ | ||
210 | li r11,5; /* MSR_SF_LG|MSR_ISF_LG */ \ | ||
211 | rldimi r10,r11,61,0; /* insert into top 3 bits */ \ | ||
212 | /* done 64bit mode */ \ | ||
213 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
214 | LOAD_HANDLER(r12,label) \ | ||
215 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
216 | mtspr SPRN_SRR0,r12; \ | ||
217 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
218 | mtspr SPRN_SRR1,r10; \ | ||
219 | rfid; \ | ||
220 | b . /* prevent speculative execution */ | ||
221 | |||
222 | #define EXCEPTION_PROLOG_PSERIES(area, label) \ | ||
223 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
224 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
225 | std r10,area+EX_R10(r13); \ | ||
226 | std r11,area+EX_R11(r13); \ | ||
227 | std r12,area+EX_R12(r13); \ | ||
228 | mfspr r9,SPRN_SPRG1; \ | ||
229 | std r9,area+EX_R13(r13); \ | ||
230 | mfcr r9; \ | ||
231 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
232 | mfmsr r10; \ | ||
233 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
234 | LOAD_HANDLER(r12,label) \ | ||
235 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
236 | mtspr SPRN_SRR0,r12; \ | ||
237 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
238 | mtspr SPRN_SRR1,r10; \ | ||
239 | rfid; \ | ||
240 | b . /* prevent speculative execution */ | ||
241 | |||
242 | /* | ||
243 | * This is the start of the interrupt handlers for iSeries | ||
244 | * This code runs with relocation on. | ||
245 | */ | ||
246 | #define EXCEPTION_PROLOG_ISERIES_1(area) \ | ||
247 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
248 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
249 | std r10,area+EX_R10(r13); \ | ||
250 | std r11,area+EX_R11(r13); \ | ||
251 | std r12,area+EX_R12(r13); \ | ||
252 | mfspr r9,SPRN_SPRG1; \ | ||
253 | std r9,area+EX_R13(r13); \ | ||
254 | mfcr r9 | ||
255 | |||
256 | #define EXCEPTION_PROLOG_ISERIES_2 \ | ||
257 | mfmsr r10; \ | ||
258 | ld r12,PACALPPACAPTR(r13); \ | ||
259 | ld r11,LPPACASRR0(r12); \ | ||
260 | ld r12,LPPACASRR1(r12); \ | ||
261 | ori r10,r10,MSR_RI; \ | ||
262 | mtmsrd r10,1 | ||
263 | |||
264 | /* | ||
265 | * The common exception prolog is used for all except a few exceptions | ||
266 | * such as a segment miss on a kernel address. We have to be prepared | ||
267 | * to take another exception from the point where we first touch the | ||
268 | * kernel stack onwards. | ||
269 | * | ||
270 | * On entry r13 points to the paca, r9-r13 are saved in the paca, | ||
271 | * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and | ||
272 | * SRR1, and relocation is on. | ||
273 | */ | ||
274 | #define EXCEPTION_PROLOG_COMMON(n, area) \ | ||
275 | andi. r10,r12,MSR_PR; /* See if coming from user */ \ | ||
276 | mr r10,r1; /* Save r1 */ \ | ||
277 | subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ | ||
278 | beq- 1f; \ | ||
279 | ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ | ||
280 | 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ | ||
281 | bge- cr1,2f; /* abort if it is */ \ | ||
282 | b 3f; \ | ||
283 | 2: li r1,(n); /* will be reloaded later */ \ | ||
284 | sth r1,PACA_TRAP_SAVE(r13); \ | ||
285 | b bad_stack; \ | ||
286 | 3: std r9,_CCR(r1); /* save CR in stackframe */ \ | ||
287 | std r11,_NIP(r1); /* save SRR0 in stackframe */ \ | ||
288 | std r12,_MSR(r1); /* save SRR1 in stackframe */ \ | ||
289 | std r10,0(r1); /* make stack chain pointer */ \ | ||
290 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | ||
291 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | ||
292 | ACCOUNT_CPU_USER_ENTRY(r9, r10); \ | ||
293 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | ||
294 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | ||
295 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | ||
296 | ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ | ||
297 | ld r10,area+EX_R10(r13); \ | ||
298 | std r9,GPR9(r1); \ | ||
299 | std r10,GPR10(r1); \ | ||
300 | ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ | ||
301 | ld r10,area+EX_R12(r13); \ | ||
302 | ld r11,area+EX_R13(r13); \ | ||
303 | std r9,GPR11(r1); \ | ||
304 | std r10,GPR12(r1); \ | ||
305 | std r11,GPR13(r1); \ | ||
306 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ | ||
307 | mflr r9; /* save LR in stackframe */ \ | ||
308 | std r9,_LINK(r1); \ | ||
309 | mfctr r10; /* save CTR in stackframe */ \ | ||
310 | std r10,_CTR(r1); \ | ||
311 | lbz r10,PACASOFTIRQEN(r13); \ | ||
312 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ | ||
313 | std r10,SOFTE(r1); \ | ||
314 | std r11,_XER(r1); \ | ||
315 | li r9,(n)+1; \ | ||
316 | std r9,_TRAP(r1); /* set trap number */ \ | ||
317 | li r10,0; \ | ||
318 | ld r11,exception_marker@toc(r2); \ | ||
319 | std r10,RESULT(r1); /* clear regs->result */ \ | ||
320 | std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ | ||
321 | |||
322 | /* | ||
323 | * Exception vectors. | ||
324 | */ | ||
325 | #define STD_EXCEPTION_PSERIES(n, label) \ | ||
326 | . = n; \ | ||
327 | .globl label##_pSeries; \ | ||
328 | label##_pSeries: \ | ||
329 | HMT_MEDIUM; \ | ||
330 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
331 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | ||
332 | |||
333 | #define HSTD_EXCEPTION_PSERIES(n, label) \ | ||
334 | . = n; \ | ||
335 | .globl label##_pSeries; \ | ||
336 | label##_pSeries: \ | ||
337 | HMT_MEDIUM; \ | ||
338 | mtspr SPRN_SPRG1,r20; /* save r20 */ \ | ||
339 | mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \ | ||
340 | mtspr SPRN_SRR0,r20; \ | ||
341 | mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \ | ||
342 | mtspr SPRN_SRR1,r20; \ | ||
343 | mfspr r20,SPRN_SPRG1; /* restore r20 */ \ | ||
344 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
345 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | ||
346 | |||
347 | |||
348 | #define MASKABLE_EXCEPTION_PSERIES(n, label) \ | ||
349 | . = n; \ | ||
350 | .globl label##_pSeries; \ | ||
351 | label##_pSeries: \ | ||
352 | HMT_MEDIUM; \ | ||
353 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
354 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
355 | std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ | ||
356 | std r10,PACA_EXGEN+EX_R10(r13); \ | ||
357 | lbz r10,PACASOFTIRQEN(r13); \ | ||
358 | mfcr r9; \ | ||
359 | cmpwi r10,0; \ | ||
360 | beq masked_interrupt; \ | ||
361 | mfspr r10,SPRN_SPRG1; \ | ||
362 | std r10,PACA_EXGEN+EX_R13(r13); \ | ||
363 | std r11,PACA_EXGEN+EX_R11(r13); \ | ||
364 | std r12,PACA_EXGEN+EX_R12(r13); \ | ||
365 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
366 | mfmsr r10; \ | ||
367 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
368 | LOAD_HANDLER(r12,label##_common) \ | ||
369 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
370 | mtspr SPRN_SRR0,r12; \ | ||
371 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
372 | mtspr SPRN_SRR1,r10; \ | ||
373 | rfid; \ | ||
374 | b . /* prevent speculative execution */ | ||
375 | |||
376 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | ||
377 | .globl label##_iSeries; \ | ||
378 | label##_iSeries: \ | ||
379 | HMT_MEDIUM; \ | ||
380 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
381 | EXCEPTION_PROLOG_ISERIES_1(area); \ | ||
382 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
383 | b label##_common | ||
384 | |||
385 | #define MASKABLE_EXCEPTION_ISERIES(n, label) \ | ||
386 | .globl label##_iSeries; \ | ||
387 | label##_iSeries: \ | ||
388 | HMT_MEDIUM; \ | ||
389 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
390 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ | ||
391 | lbz r10,PACASOFTIRQEN(r13); \ | ||
392 | cmpwi 0,r10,0; \ | ||
393 | beq- label##_iSeries_masked; \ | ||
394 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
395 | b label##_common; \ | ||
396 | |||
397 | #ifdef CONFIG_PPC_ISERIES | ||
398 | #define DISABLE_INTS \ | ||
399 | li r11,0; \ | ||
400 | stb r11,PACASOFTIRQEN(r13); \ | ||
401 | BEGIN_FW_FTR_SECTION; \ | ||
402 | stb r11,PACAHARDIRQEN(r13); \ | ||
403 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ | ||
404 | BEGIN_FW_FTR_SECTION; \ | ||
405 | mfmsr r10; \ | ||
406 | ori r10,r10,MSR_EE; \ | ||
407 | mtmsrd r10,1; \ | ||
408 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | ||
409 | |||
410 | #else | ||
411 | #define DISABLE_INTS \ | ||
412 | li r11,0; \ | ||
413 | stb r11,PACASOFTIRQEN(r13); \ | ||
414 | stb r11,PACAHARDIRQEN(r13) | ||
415 | |||
416 | #endif /* CONFIG_PPC_ISERIES */ | ||
417 | |||
418 | #define ENABLE_INTS \ | ||
419 | ld r12,_MSR(r1); \ | ||
420 | mfmsr r11; \ | ||
421 | rlwimi r11,r12,0,MSR_EE; \ | ||
422 | mtmsrd r11,1 | ||
423 | |||
424 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | ||
425 | .align 7; \ | ||
426 | .globl label##_common; \ | ||
427 | label##_common: \ | ||
428 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
429 | DISABLE_INTS; \ | ||
430 | bl .save_nvgprs; \ | ||
431 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
432 | bl hdlr; \ | ||
433 | b .ret_from_except | ||
434 | |||
435 | /* | ||
436 | * Like STD_EXCEPTION_COMMON, but for exceptions that can occur | ||
437 | * in the idle task and therefore need the special idle handling. | ||
438 | */ | ||
439 | #define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr) \ | ||
440 | .align 7; \ | ||
441 | .globl label##_common; \ | ||
442 | label##_common: \ | ||
443 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
444 | FINISH_NAP; \ | ||
445 | DISABLE_INTS; \ | ||
446 | bl .save_nvgprs; \ | ||
447 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
448 | bl hdlr; \ | ||
449 | b .ret_from_except | ||
450 | |||
451 | #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \ | ||
452 | .align 7; \ | ||
453 | .globl label##_common; \ | ||
454 | label##_common: \ | ||
455 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
456 | FINISH_NAP; \ | ||
457 | DISABLE_INTS; \ | ||
458 | bl .ppc64_runlatch_on; \ | ||
459 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
460 | bl hdlr; \ | ||
461 | b .ret_from_except_lite | ||
462 | |||
463 | /* | ||
464 | * When the idle code in power4_idle puts the CPU into NAP mode, | ||
465 | * it has to do so in a loop, and relies on the external interrupt | ||
466 | * and decrementer interrupt entry code to get it out of the loop. | ||
467 | * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags | ||
468 | * to signal that it is in the loop and needs help to get out. | ||
469 | */ | ||
470 | #ifdef CONFIG_PPC_970_NAP | ||
471 | #define FINISH_NAP \ | ||
472 | BEGIN_FTR_SECTION \ | ||
473 | clrrdi r11,r1,THREAD_SHIFT; \ | ||
474 | ld r9,TI_LOCAL_FLAGS(r11); \ | ||
475 | andi. r10,r9,_TLF_NAPPING; \ | ||
476 | bnel power4_fixup_nap; \ | ||
477 | END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) | ||
478 | #else | ||
479 | #define FINISH_NAP | ||
480 | #endif | ||
481 | |||
482 | /* | ||
483 | * Start of pSeries system interrupt routines | ||
484 | */ | ||
485 | . = 0x100 | 152 | . = 0x100 |
486 | .globl __start_interrupts | 153 | .globl __start_interrupts |
487 | __start_interrupts: | 154 | __start_interrupts: |
@@ -674,6 +341,7 @@ slb_miss_user_pseries: | |||
674 | b . /* prevent spec. execution */ | 341 | b . /* prevent spec. execution */ |
675 | #endif /* __DISABLED__ */ | 342 | #endif /* __DISABLED__ */ |
676 | 343 | ||
344 | #ifdef CONFIG_PPC_PSERIES | ||
677 | /* | 345 | /* |
678 | * Vectors for the FWNMI option. Share common code. | 346 | * Vectors for the FWNMI option. Share common code. |
679 | */ | 347 | */ |
@@ -691,191 +359,7 @@ machine_check_fwnmi: | |||
691 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 359 | mtspr SPRN_SPRG1,r13 /* save r13 */ |
692 | EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common) | 360 | EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common) |
693 | 361 | ||
694 | #ifdef CONFIG_PPC_ISERIES | 362 | #endif /* CONFIG_PPC_PSERIES */ |
695 | /*** ISeries-LPAR interrupt handlers ***/ | ||
696 | |||
697 | STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC) | ||
698 | |||
699 | .globl data_access_iSeries | ||
700 | data_access_iSeries: | ||
701 | mtspr SPRN_SPRG1,r13 | ||
702 | BEGIN_FTR_SECTION | ||
703 | mtspr SPRN_SPRG2,r12 | ||
704 | mfspr r13,SPRN_DAR | ||
705 | mfspr r12,SPRN_DSISR | ||
706 | srdi r13,r13,60 | ||
707 | rlwimi r13,r12,16,0x20 | ||
708 | mfcr r12 | ||
709 | cmpwi r13,0x2c | ||
710 | beq .do_stab_bolted_iSeries | ||
711 | mtcrf 0x80,r12 | ||
712 | mfspr r12,SPRN_SPRG2 | ||
713 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
714 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN) | ||
715 | EXCEPTION_PROLOG_ISERIES_2 | ||
716 | b data_access_common | ||
717 | |||
718 | .do_stab_bolted_iSeries: | ||
719 | mtcrf 0x80,r12 | ||
720 | mfspr r12,SPRN_SPRG2 | ||
721 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) | ||
722 | EXCEPTION_PROLOG_ISERIES_2 | ||
723 | b .do_stab_bolted | ||
724 | |||
725 | .globl data_access_slb_iSeries | ||
726 | data_access_slb_iSeries: | ||
727 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
728 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
729 | std r3,PACA_EXSLB+EX_R3(r13) | ||
730 | mfspr r3,SPRN_DAR | ||
731 | std r9,PACA_EXSLB+EX_R9(r13) | ||
732 | mfcr r9 | ||
733 | #ifdef __DISABLED__ | ||
734 | cmpdi r3,0 | ||
735 | bge slb_miss_user_iseries | ||
736 | #endif | ||
737 | std r10,PACA_EXSLB+EX_R10(r13) | ||
738 | std r11,PACA_EXSLB+EX_R11(r13) | ||
739 | std r12,PACA_EXSLB+EX_R12(r13) | ||
740 | mfspr r10,SPRN_SPRG1 | ||
741 | std r10,PACA_EXSLB+EX_R13(r13) | ||
742 | ld r12,PACALPPACAPTR(r13) | ||
743 | ld r12,LPPACASRR1(r12) | ||
744 | b .slb_miss_realmode | ||
745 | |||
746 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) | ||
747 | |||
748 | .globl instruction_access_slb_iSeries | ||
749 | instruction_access_slb_iSeries: | ||
750 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
751 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
752 | std r3,PACA_EXSLB+EX_R3(r13) | ||
753 | ld r3,PACALPPACAPTR(r13) | ||
754 | ld r3,LPPACASRR0(r3) /* get SRR0 value */ | ||
755 | std r9,PACA_EXSLB+EX_R9(r13) | ||
756 | mfcr r9 | ||
757 | #ifdef __DISABLED__ | ||
758 | cmpdi r3,0 | ||
759 | bge .slb_miss_user_iseries | ||
760 | #endif | ||
761 | std r10,PACA_EXSLB+EX_R10(r13) | ||
762 | std r11,PACA_EXSLB+EX_R11(r13) | ||
763 | std r12,PACA_EXSLB+EX_R12(r13) | ||
764 | mfspr r10,SPRN_SPRG1 | ||
765 | std r10,PACA_EXSLB+EX_R13(r13) | ||
766 | ld r12,PACALPPACAPTR(r13) | ||
767 | ld r12,LPPACASRR1(r12) | ||
768 | b .slb_miss_realmode | ||
769 | |||
770 | #ifdef __DISABLED__ | ||
771 | slb_miss_user_iseries: | ||
772 | std r10,PACA_EXGEN+EX_R10(r13) | ||
773 | std r11,PACA_EXGEN+EX_R11(r13) | ||
774 | std r12,PACA_EXGEN+EX_R12(r13) | ||
775 | mfspr r10,SPRG1 | ||
776 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
777 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
778 | std r10,PACA_EXGEN+EX_R13(r13) | ||
779 | std r11,PACA_EXGEN+EX_R9(r13) | ||
780 | std r12,PACA_EXGEN+EX_R3(r13) | ||
781 | EXCEPTION_PROLOG_ISERIES_2 | ||
782 | b slb_miss_user_common | ||
783 | #endif | ||
784 | |||
785 | MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) | ||
786 | STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) | ||
787 | STD_EXCEPTION_ISERIES(0x700, program_check, PACA_EXGEN) | ||
788 | STD_EXCEPTION_ISERIES(0x800, fp_unavailable, PACA_EXGEN) | ||
789 | MASKABLE_EXCEPTION_ISERIES(0x900, decrementer) | ||
790 | STD_EXCEPTION_ISERIES(0xa00, trap_0a, PACA_EXGEN) | ||
791 | STD_EXCEPTION_ISERIES(0xb00, trap_0b, PACA_EXGEN) | ||
792 | |||
793 | .globl system_call_iSeries | ||
794 | system_call_iSeries: | ||
795 | mr r9,r13 | ||
796 | mfspr r13,SPRN_SPRG3 | ||
797 | EXCEPTION_PROLOG_ISERIES_2 | ||
798 | b system_call_common | ||
799 | |||
800 | STD_EXCEPTION_ISERIES( 0xd00, single_step, PACA_EXGEN) | ||
801 | STD_EXCEPTION_ISERIES( 0xe00, trap_0e, PACA_EXGEN) | ||
802 | STD_EXCEPTION_ISERIES( 0xf00, performance_monitor, PACA_EXGEN) | ||
803 | |||
804 | .globl system_reset_iSeries | ||
805 | system_reset_iSeries: | ||
806 | mfspr r13,SPRN_SPRG3 /* Get paca address */ | ||
807 | mfmsr r24 | ||
808 | ori r24,r24,MSR_RI | ||
809 | mtmsrd r24 /* RI on */ | ||
810 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ | ||
811 | cmpwi 0,r24,0 /* Are we processor 0? */ | ||
812 | bne 1f | ||
813 | b .__start_initialization_iSeries /* Start up the first processor */ | ||
814 | 1: mfspr r4,SPRN_CTRLF | ||
815 | li r5,CTRL_RUNLATCH /* Turn off the run light */ | ||
816 | andc r4,r4,r5 | ||
817 | mtspr SPRN_CTRLT,r4 | ||
818 | |||
819 | 1: | ||
820 | HMT_LOW | ||
821 | #ifdef CONFIG_SMP | ||
822 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | ||
823 | * should start */ | ||
824 | sync | ||
825 | LOAD_REG_IMMEDIATE(r3,current_set) | ||
826 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
827 | ldx r3,r3,r28 | ||
828 | addi r1,r3,THREAD_SIZE | ||
829 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
830 | |||
831 | cmpwi 0,r23,0 | ||
832 | beq iSeries_secondary_smp_loop /* Loop until told to go */ | ||
833 | bne __secondary_start /* Loop until told to go */ | ||
834 | iSeries_secondary_smp_loop: | ||
835 | /* Let the Hypervisor know we are alive */ | ||
836 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ | ||
837 | lis r3,0x8002 | ||
838 | rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ | ||
839 | #else /* CONFIG_SMP */ | ||
840 | /* Yield the processor. This is required for non-SMP kernels | ||
841 | which are running on multi-threaded machines. */ | ||
842 | lis r3,0x8000 | ||
843 | rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ | ||
844 | addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ | ||
845 | li r4,0 /* "yield timed" */ | ||
846 | li r5,-1 /* "yield forever" */ | ||
847 | #endif /* CONFIG_SMP */ | ||
848 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ | ||
849 | sc /* Invoke the hypervisor via a system call */ | ||
850 | mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */ | ||
851 | b 1b /* If SMP not configured, secondaries | ||
852 | * loop forever */ | ||
853 | |||
854 | decrementer_iSeries_masked: | ||
855 | /* We may not have a valid TOC pointer in here. */ | ||
856 | li r11,1 | ||
857 | ld r12,PACALPPACAPTR(r13) | ||
858 | stb r11,LPPACADECRINT(r12) | ||
859 | LOAD_REG_IMMEDIATE(r12, tb_ticks_per_jiffy) | ||
860 | lwz r12,0(r12) | ||
861 | mtspr SPRN_DEC,r12 | ||
862 | /* fall through */ | ||
863 | |||
864 | hardware_interrupt_iSeries_masked: | ||
865 | mtcrf 0x80,r9 /* Restore regs */ | ||
866 | ld r12,PACALPPACAPTR(r13) | ||
867 | ld r11,LPPACASRR0(r12) | ||
868 | ld r12,LPPACASRR1(r12) | ||
869 | mtspr SPRN_SRR0,r11 | ||
870 | mtspr SPRN_SRR1,r12 | ||
871 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
872 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
873 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
874 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
875 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
876 | rfid | ||
877 | b . /* prevent speculative execution */ | ||
878 | #endif /* CONFIG_PPC_ISERIES */ | ||
879 | 363 | ||
880 | /*** Common interrupt handlers ***/ | 364 | /*** Common interrupt handlers ***/ |
881 | 365 | ||
@@ -1175,7 +659,9 @@ hardware_interrupt_common: | |||
1175 | FINISH_NAP | 659 | FINISH_NAP |
1176 | hardware_interrupt_entry: | 660 | hardware_interrupt_entry: |
1177 | DISABLE_INTS | 661 | DISABLE_INTS |
662 | BEGIN_FTR_SECTION | ||
1178 | bl .ppc64_runlatch_on | 663 | bl .ppc64_runlatch_on |
664 | END_FTR_SECTION_IFSET(CPU_FTR_CTRL) | ||
1179 | addi r3,r1,STACK_FRAME_OVERHEAD | 665 | addi r3,r1,STACK_FRAME_OVERHEAD |
1180 | bl .do_IRQ | 666 | bl .do_IRQ |
1181 | b .ret_from_except_lite | 667 | b .ret_from_except_lite |
@@ -1449,7 +935,7 @@ _GLOBAL(do_stab_bolted) | |||
1449 | 935 | ||
1450 | /* Calculate VSID */ | 936 | /* Calculate VSID */ |
1451 | /* This is a kernel address, so protovsid = ESID */ | 937 | /* This is a kernel address, so protovsid = ESID */ |
1452 | ASM_VSID_SCRAMBLE(r11, r9) | 938 | ASM_VSID_SCRAMBLE(r11, r9, 256M) |
1453 | rldic r9,r11,12,16 /* r9 = vsid << 12 */ | 939 | rldic r9,r11,12,16 /* r9 = vsid << 12 */ |
1454 | 940 | ||
1455 | /* Search the primary group for a free entry */ | 941 | /* Search the primary group for a free entry */ |
@@ -1519,8 +1005,8 @@ _GLOBAL(do_stab_bolted) | |||
1519 | * Space for CPU0's segment table. | 1005 | * Space for CPU0's segment table. |
1520 | * | 1006 | * |
1521 | * On iSeries, the hypervisor must fill in at least one entry before | 1007 | * On iSeries, the hypervisor must fill in at least one entry before |
1522 | * we get control (with relocate on). The address is give to the hv | 1008 | * we get control (with relocate on). The address is given to the hv |
1523 | * as a page number (see xLparMap in lpardata.c), so this must be at a | 1009 | * as a page number (see xLparMap below), so this must be at a |
1524 | * fixed address (the linker can't compute (u64)&initial_stab >> | 1010 | * fixed address (the linker can't compute (u64)&initial_stab >> |
1525 | * PAGE_SHIFT). | 1011 | * PAGE_SHIFT). |
1526 | */ | 1012 | */ |
@@ -1529,6 +1015,7 @@ _GLOBAL(do_stab_bolted) | |||
1529 | initial_stab: | 1015 | initial_stab: |
1530 | .space 4096 | 1016 | .space 4096 |
1531 | 1017 | ||
1018 | #ifdef CONFIG_PPC_PSERIES | ||
1532 | /* | 1019 | /* |
1533 | * Data area reserved for FWNMI option. | 1020 | * Data area reserved for FWNMI option. |
1534 | * This address (0x7000) is fixed by the RPA. | 1021 | * This address (0x7000) is fixed by the RPA. |
@@ -1536,21 +1023,34 @@ initial_stab: | |||
1536 | .= 0x7000 | 1023 | .= 0x7000 |
1537 | .globl fwnmi_data_area | 1024 | .globl fwnmi_data_area |
1538 | fwnmi_data_area: | 1025 | fwnmi_data_area: |
1026 | #endif /* CONFIG_PPC_PSERIES */ | ||
1539 | 1027 | ||
1540 | /* iSeries does not use the FWNMI stuff, so it is safe to put | 1028 | /* iSeries does not use the FWNMI stuff, so it is safe to put |
1541 | * this here, even if we later allow kernels that will boot on | 1029 | * this here, even if we later allow kernels that will boot on |
1542 | * both pSeries and iSeries */ | 1030 | * both pSeries and iSeries */ |
1543 | #ifdef CONFIG_PPC_ISERIES | 1031 | #ifdef CONFIG_PPC_ISERIES |
1544 | . = LPARMAP_PHYS | 1032 | . = LPARMAP_PHYS |
1545 | #include "lparmap.s" | 1033 | .globl xLparMap |
1546 | /* | 1034 | xLparMap: |
1547 | * This ".text" is here for old compilers that generate a trailing | 1035 | .quad HvEsidsToMap /* xNumberEsids */ |
1548 | * .note section when compiling .c files to .s | 1036 | .quad HvRangesToMap /* xNumberRanges */ |
1549 | */ | 1037 | .quad STAB0_PAGE /* xSegmentTableOffs */ |
1550 | .text | 1038 | .zero 40 /* xRsvd */ |
1039 | /* xEsids (HvEsidsToMap entries of 2 quads) */ | ||
1040 | .quad PAGE_OFFSET_ESID /* xKernelEsid */ | ||
1041 | .quad PAGE_OFFSET_VSID /* xKernelVsid */ | ||
1042 | .quad VMALLOC_START_ESID /* xKernelEsid */ | ||
1043 | .quad VMALLOC_START_VSID /* xKernelVsid */ | ||
1044 | /* xRanges (HvRangesToMap entries of 3 quads) */ | ||
1045 | .quad HvPagesToMap /* xPages */ | ||
1046 | .quad 0 /* xOffset */ | ||
1047 | .quad PAGE_OFFSET_VSID << (SID_SHIFT - HW_PAGE_SHIFT) /* xVPN */ | ||
1048 | |||
1551 | #endif /* CONFIG_PPC_ISERIES */ | 1049 | #endif /* CONFIG_PPC_ISERIES */ |
1552 | 1050 | ||
1051 | #ifdef CONFIG_PPC_PSERIES | ||
1553 | . = 0x8000 | 1052 | . = 0x8000 |
1053 | #endif /* CONFIG_PPC_PSERIES */ | ||
1554 | 1054 | ||
1555 | /* | 1055 | /* |
1556 | * On pSeries and most other platforms, secondary processors spin | 1056 | * On pSeries and most other platforms, secondary processors spin |
@@ -1611,39 +1111,6 @@ _GLOBAL(generic_secondary_smp_init) | |||
1611 | b __secondary_start | 1111 | b __secondary_start |
1612 | #endif | 1112 | #endif |
1613 | 1113 | ||
1614 | #ifdef CONFIG_PPC_ISERIES | ||
1615 | _INIT_STATIC(__start_initialization_iSeries) | ||
1616 | /* Clear out the BSS */ | ||
1617 | LOAD_REG_IMMEDIATE(r11,__bss_stop) | ||
1618 | LOAD_REG_IMMEDIATE(r8,__bss_start) | ||
1619 | sub r11,r11,r8 /* bss size */ | ||
1620 | addi r11,r11,7 /* round up to an even double word */ | ||
1621 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
1622 | beq 4f | ||
1623 | addi r8,r8,-8 | ||
1624 | li r0,0 | ||
1625 | mtctr r11 /* zero this many doublewords */ | ||
1626 | 3: stdu r0,8(r8) | ||
1627 | bdnz 3b | ||
1628 | 4: | ||
1629 | LOAD_REG_IMMEDIATE(r1,init_thread_union) | ||
1630 | addi r1,r1,THREAD_SIZE | ||
1631 | li r0,0 | ||
1632 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1633 | |||
1634 | LOAD_REG_IMMEDIATE(r2,__toc_start) | ||
1635 | addi r2,r2,0x4000 | ||
1636 | addi r2,r2,0x4000 | ||
1637 | |||
1638 | bl .iSeries_early_setup | ||
1639 | bl .early_setup | ||
1640 | |||
1641 | /* relocation is on at this point */ | ||
1642 | |||
1643 | b .start_here_common | ||
1644 | #endif /* CONFIG_PPC_ISERIES */ | ||
1645 | |||
1646 | |||
1647 | _STATIC(__mmu_off) | 1114 | _STATIC(__mmu_off) |
1648 | mfmsr r3 | 1115 | mfmsr r3 |
1649 | andi. r0,r3,MSR_IR|MSR_DR | 1116 | andi. r0,r3,MSR_IR|MSR_DR |
@@ -1891,6 +1358,7 @@ _GLOBAL(pmac_secondary_start) | |||
1891 | * r13 = paca virtual address | 1358 | * r13 = paca virtual address |
1892 | * SPRG3 = paca virtual address | 1359 | * SPRG3 = paca virtual address |
1893 | */ | 1360 | */ |
1361 | .globl __secondary_start | ||
1894 | __secondary_start: | 1362 | __secondary_start: |
1895 | /* Set thread priority to MEDIUM */ | 1363 | /* Set thread priority to MEDIUM */ |
1896 | HMT_MEDIUM | 1364 | HMT_MEDIUM |
@@ -2021,7 +1489,7 @@ _INIT_STATIC(start_here_multiplatform) | |||
2021 | b . /* prevent speculative execution */ | 1489 | b . /* prevent speculative execution */ |
2022 | 1490 | ||
2023 | /* This is where all platforms converge execution */ | 1491 | /* This is where all platforms converge execution */ |
2024 | _INIT_STATIC(start_here_common) | 1492 | _INIT_GLOBAL(start_here_common) |
2025 | /* relocation is on at this point */ | 1493 | /* relocation is on at this point */ |
2026 | 1494 | ||
2027 | /* The following code sets up the SP and TOC now that we are */ | 1495 | /* The following code sets up the SP and TOC now that we are */ |
@@ -2078,12 +1546,4 @@ empty_zero_page: | |||
2078 | 1546 | ||
2079 | .globl swapper_pg_dir | 1547 | .globl swapper_pg_dir |
2080 | swapper_pg_dir: | 1548 | swapper_pg_dir: |
2081 | .space PAGE_SIZE | 1549 | .space PGD_TABLE_SIZE |
2082 | |||
2083 | /* | ||
2084 | * This space gets a copy of optional info passed to us by the bootstrap | ||
2085 | * Used to pass parameters into the kernel like root=/dev/sda1, etc. | ||
2086 | */ | ||
2087 | .globl cmd_line | ||
2088 | cmd_line: | ||
2089 | .space COMMAND_LINE_SIZE | ||