aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/head_8xx.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/head_8xx.S')
-rw-r--r--arch/powerpc/kernel/head_8xx.S150
1 files changed, 56 insertions, 94 deletions
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 7ee876d2adb5..fafff8dbd5d9 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -104,12 +104,15 @@ turn_on_mmu:
104 * task's thread_struct. 104 * task's thread_struct.
105 */ 105 */
106#define EXCEPTION_PROLOG \ 106#define EXCEPTION_PROLOG \
107 mtspr SPRN_SPRG_SCRATCH0,r10; \ 107 EXCEPTION_PROLOG_0; \
108 mtspr SPRN_SPRG_SCRATCH1,r11; \
109 mfcr r10; \
110 EXCEPTION_PROLOG_1; \ 108 EXCEPTION_PROLOG_1; \
111 EXCEPTION_PROLOG_2 109 EXCEPTION_PROLOG_2
112 110
111#define EXCEPTION_PROLOG_0 \
112 mtspr SPRN_SPRG_SCRATCH0,r10; \
113 mtspr SPRN_SPRG_SCRATCH1,r11; \
114 mfcr r10
115
113#define EXCEPTION_PROLOG_1 \ 116#define EXCEPTION_PROLOG_1 \
114 mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \ 117 mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
115 andi. r11,r11,MSR_PR; \ 118 andi. r11,r11,MSR_PR; \
@@ -145,6 +148,14 @@ turn_on_mmu:
145 SAVE_2GPRS(7, r11) 148 SAVE_2GPRS(7, r11)
146 149
147/* 150/*
151 * Exception exit code.
152 */
153#define EXCEPTION_EPILOG_0 \
154 mtcr r10; \
155 mfspr r10,SPRN_SPRG_SCRATCH0; \
156 mfspr r11,SPRN_SPRG_SCRATCH1
157
158/*
148 * Note: code which follows this uses cr0.eq (set if from kernel), 159 * Note: code which follows this uses cr0.eq (set if from kernel),
149 * r11, r12 (SRR0), and r9 (SRR1). 160 * r11, r12 (SRR0), and r9 (SRR1).
150 * 161 *
@@ -293,16 +304,8 @@ InstructionTLBMiss:
293#ifdef CONFIG_8xx_CPU6 304#ifdef CONFIG_8xx_CPU6
294 stw r3, 8(r0) 305 stw r3, 8(r0)
295#endif 306#endif
296 DO_8xx_CPU6(0x3f80, r3) 307 EXCEPTION_PROLOG_0
297 mtspr SPRN_M_TW, r10 /* Save a couple of working registers */ 308 mtspr SPRN_SPRG_SCRATCH2, r10
298 mfcr r10
299#ifdef CONFIG_8xx_CPU6
300 stw r10, 0(r0)
301 stw r11, 4(r0)
302#else
303 mtspr SPRN_DAR, r10
304 mtspr SPRN_SPRG2, r11
305#endif
306 mfspr r10, SPRN_SRR0 /* Get effective address of fault */ 309 mfspr r10, SPRN_SRR0 /* Get effective address of fault */
307#ifdef CONFIG_8xx_CPU15 310#ifdef CONFIG_8xx_CPU15
308 addi r11, r10, 0x1000 311 addi r11, r10, 0x1000
@@ -359,18 +362,11 @@ InstructionTLBMiss:
359 mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ 362 mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
360 363
361 /* Restore registers */ 364 /* Restore registers */
362#ifndef CONFIG_8xx_CPU6 365#ifdef CONFIG_8xx_CPU6
363 mfspr r10, SPRN_DAR
364 mtcr r10
365 mtspr SPRN_DAR, r11 /* Tag DAR */
366 mfspr r11, SPRN_SPRG2
367#else
368 lwz r11, 0(r0)
369 mtcr r11
370 lwz r11, 4(r0)
371 lwz r3, 8(r0) 366 lwz r3, 8(r0)
372#endif 367#endif
373 mfspr r10, SPRN_M_TW 368 mfspr r10, SPRN_SPRG_SCRATCH2
369 EXCEPTION_EPILOG_0
374 rfi 370 rfi
3752: 3712:
376 mfspr r11, SPRN_SRR1 372 mfspr r11, SPRN_SRR1
@@ -381,19 +377,11 @@ InstructionTLBMiss:
381 mtspr SPRN_SRR1, r11 377 mtspr SPRN_SRR1, r11
382 378
383 /* Restore registers */ 379 /* Restore registers */
384#ifndef CONFIG_8xx_CPU6 380#ifdef CONFIG_8xx_CPU6
385 mfspr r10, SPRN_DAR
386 mtcr r10
387 li r11, 0x00f0
388 mtspr SPRN_DAR, r11 /* Tag DAR */
389 mfspr r11, SPRN_SPRG2
390#else
391 lwz r11, 0(r0)
392 mtcr r11
393 lwz r11, 4(r0)
394 lwz r3, 8(r0) 381 lwz r3, 8(r0)
395#endif 382#endif
396 mfspr r10, SPRN_M_TW 383 mfspr r10, SPRN_SPRG_SCRATCH2
384 EXCEPTION_EPILOG_0
397 b InstructionAccess 385 b InstructionAccess
398 386
399 . = 0x1200 387 . = 0x1200
@@ -401,16 +389,8 @@ DataStoreTLBMiss:
401#ifdef CONFIG_8xx_CPU6 389#ifdef CONFIG_8xx_CPU6
402 stw r3, 8(r0) 390 stw r3, 8(r0)
403#endif 391#endif
404 DO_8xx_CPU6(0x3f80, r3) 392 EXCEPTION_PROLOG_0
405 mtspr SPRN_M_TW, r10 /* Save a couple of working registers */ 393 mtspr SPRN_SPRG_SCRATCH2, r10
406 mfcr r10
407#ifdef CONFIG_8xx_CPU6
408 stw r10, 0(r0)
409 stw r11, 4(r0)
410#else
411 mtspr SPRN_DAR, r10
412 mtspr SPRN_SPRG2, r11
413#endif
414 mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ 394 mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
415 395
416 /* If we are faulting a kernel address, we have to use the 396 /* If we are faulting a kernel address, we have to use the
@@ -483,19 +463,12 @@ DataStoreTLBMiss:
483 mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ 463 mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
484 464
485 /* Restore registers */ 465 /* Restore registers */
486#ifndef CONFIG_8xx_CPU6 466#ifdef CONFIG_8xx_CPU6
487 mfspr r10, SPRN_DAR
488 mtcr r10
489 mtspr SPRN_DAR, r11 /* Tag DAR */
490 mfspr r11, SPRN_SPRG2
491#else
492 mtspr SPRN_DAR, r11 /* Tag DAR */
493 lwz r11, 0(r0)
494 mtcr r11
495 lwz r11, 4(r0)
496 lwz r3, 8(r0) 467 lwz r3, 8(r0)
497#endif 468#endif
498 mfspr r10, SPRN_M_TW 469 mtspr SPRN_DAR, r11 /* Tag DAR */
470 mfspr r10, SPRN_SPRG_SCRATCH2
471 EXCEPTION_EPILOG_0
499 rfi 472 rfi
500 473
501/* This is an instruction TLB error on the MPC8xx. This could be due 474/* This is an instruction TLB error on the MPC8xx. This could be due
@@ -507,35 +480,18 @@ InstructionTLBError:
507 b InstructionAccess 480 b InstructionAccess
508 481
509/* This is the data TLB error on the MPC8xx. This could be due to 482/* This is the data TLB error on the MPC8xx. This could be due to
510 * many reasons, including a dirty update to a pte. We can catch that 483 * many reasons, including a dirty update to a pte. We bail out to
511 * one here, but anything else is an error. First, we track down the 484 * a higher level function that can handle it.
512 * Linux pte. If it is valid, write access is allowed, but the
513 * page dirty bit is not set, we will set it and reload the TLB. For
514 * any other case, we bail out to a higher level function that can
515 * handle it.
516 */ 485 */
517 . = 0x1400 486 . = 0x1400
518DataTLBError: 487DataTLBError:
519#ifdef CONFIG_8xx_CPU6 488 EXCEPTION_PROLOG_0
520 stw r3, 8(r0)
521#endif
522 DO_8xx_CPU6(0x3f80, r3)
523 mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
524 mfcr r10
525 stw r10, 0(r0)
526 stw r11, 4(r0)
527 489
528 mfspr r10, SPRN_DAR 490 mfspr r11, SPRN_DAR
529 cmpwi cr0, r10, 0x00f0 491 cmpwi cr0, r11, 0x00f0
530 beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ 492 beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
531DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */ 493DARFixed:/* Return from dcbx instruction bug workaround */
532 mfspr r10, SPRN_M_TW /* Restore registers */ 494 EXCEPTION_EPILOG_0
533 lwz r11, 0(r0)
534 mtcr r11
535 lwz r11, 4(r0)
536#ifdef CONFIG_8xx_CPU6
537 lwz r3, 8(r0)
538#endif
539 b DataAccess 495 b DataAccess
540 496
541 EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE) 497 EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
@@ -559,11 +515,15 @@ DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR
559 515
560/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions 516/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
561 * by decoding the registers used by the dcbx instruction and adding them. 517 * by decoding the registers used by the dcbx instruction and adding them.
562 * DAR is set to the calculated address and r10 also holds the EA on exit. 518 * DAR is set to the calculated address.
563 */ 519 */
564 /* define if you don't want to use self modifying code */ 520 /* define if you don't want to use self modifying code */
565#define NO_SELF_MODIFYING_CODE 521#define NO_SELF_MODIFYING_CODE
566FixupDAR:/* Entry point for dcbx workaround. */ 522FixupDAR:/* Entry point for dcbx workaround. */
523#ifdef CONFIG_8xx_CPU6
524 stw r3, 8(r0)
525#endif
526 mtspr SPRN_SPRG_SCRATCH2, r10
567 /* fetch instruction from memory. */ 527 /* fetch instruction from memory. */
568 mfspr r10, SPRN_SRR0 528 mfspr r10, SPRN_SRR0
569 andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ 529 andis. r11, r10, 0x8000 /* Address >= 0x80000000 */
@@ -579,16 +539,17 @@ FixupDAR:/* Entry point for dcbx workaround. */
579 mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ 539 mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
580 mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ 540 mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
581 lwz r11, 0(r11) /* Get the pte */ 541 lwz r11, 0(r11) /* Get the pte */
542#ifdef CONFIG_8xx_CPU6
543 lwz r3, 8(r0) /* restore r3 from memory */
544#endif
582 /* concat physical page address(r11) and page offset(r10) */ 545 /* concat physical page address(r11) and page offset(r10) */
583 rlwimi r11, r10, 0, 20, 31 546 rlwimi r11, r10, 0, 20, 31
584 lwz r11,0(r11) 547 lwz r11,0(r11)
585/* Check if it really is a dcbx instruction. */ 548/* Check if it really is a dcbx instruction. */
586/* dcbt and dcbtst does not generate DTLB Misses/Errors, 549/* dcbt and dcbtst does not generate DTLB Misses/Errors,
587 * no need to include them here */ 550 * no need to include them here */
588 srwi r10, r11, 26 /* check if major OP code is 31 */ 551 xoris r10, r11, 0x7c00 /* check if major OP code is 31 */
589 cmpwi cr0, r10, 31 552 rlwinm r10, r10, 0, 21, 5
590 bne- 141f
591 rlwinm r10, r11, 0, 21, 30
592 cmpwi cr0, r10, 2028 /* Is dcbz? */ 553 cmpwi cr0, r10, 2028 /* Is dcbz? */
593 beq+ 142f 554 beq+ 142f
594 cmpwi cr0, r10, 940 /* Is dcbi? */ 555 cmpwi cr0, r10, 940 /* Is dcbi? */
@@ -599,16 +560,13 @@ FixupDAR:/* Entry point for dcbx workaround. */
599 beq+ 142f 560 beq+ 142f
600 cmpwi cr0, r10, 1964 /* Is icbi? */ 561 cmpwi cr0, r10, 1964 /* Is icbi? */
601 beq+ 142f 562 beq+ 142f
602141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */ 563141: mfspr r10,SPRN_SPRG_SCRATCH2
603 b DARFixed /* Nope, go back to normal TLB processing */ 564 b DARFixed /* Nope, go back to normal TLB processing */
604 565
605144: mfspr r10, SPRN_DSISR 566144: mfspr r10, SPRN_DSISR
606 rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */ 567 rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */
607 mtspr SPRN_DSISR, r10 568 mtspr SPRN_DSISR, r10
608142: /* continue, it was a dcbx, dcbi instruction. */ 569142: /* continue, it was a dcbx, dcbi instruction. */
609#ifdef CONFIG_8xx_CPU6
610 lwz r3, 8(r0) /* restore r3 from memory */
611#endif
612#ifndef NO_SELF_MODIFYING_CODE 570#ifndef NO_SELF_MODIFYING_CODE
613 andis. r10,r11,0x1f /* test if reg RA is r0 */ 571 andis. r10,r11,0x1f /* test if reg RA is r0 */
614 li r10,modified_instr@l 572 li r10,modified_instr@l
@@ -619,14 +577,15 @@ FixupDAR:/* Entry point for dcbx workaround. */
619 stw r11,0(r10) /* store add/and instruction */ 577 stw r11,0(r10) /* store add/and instruction */
620 dcbf 0,r10 /* flush new instr. to memory. */ 578 dcbf 0,r10 /* flush new instr. to memory. */
621 icbi 0,r10 /* invalidate instr. cache line */ 579 icbi 0,r10 /* invalidate instr. cache line */
622 lwz r11, 4(r0) /* restore r11 from memory */ 580 mfspr r11, SPRN_SPRG_SCRATCH1 /* restore r11 */
623 mfspr r10, SPRN_M_TW /* restore r10 from M_TW */ 581 mfspr r10, SPRN_SPRG_SCRATCH0 /* restore r10 */
624 isync /* Wait until new instr is loaded from memory */ 582 isync /* Wait until new instr is loaded from memory */
625modified_instr: 583modified_instr:
626 .space 4 /* this is where the add instr. is stored */ 584 .space 4 /* this is where the add instr. is stored */
627 bne+ 143f 585 bne+ 143f
628 subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */ 586 subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */
629143: mtdar r10 /* store faulting EA in DAR */ 587143: mtdar r10 /* store faulting EA in DAR */
588 mfspr r10,SPRN_SPRG_SCRATCH2
630 b DARFixed /* Go back to normal TLB handling */ 589 b DARFixed /* Go back to normal TLB handling */
631#else 590#else
632 mfctr r10 591 mfctr r10
@@ -680,13 +639,16 @@ modified_instr:
680 mfdar r11 639 mfdar r11
681 mtctr r11 /* restore ctr reg from DAR */ 640 mtctr r11 /* restore ctr reg from DAR */
682 mtdar r10 /* save fault EA to DAR */ 641 mtdar r10 /* save fault EA to DAR */
642 mfspr r10,SPRN_SPRG_SCRATCH2
683 b DARFixed /* Go back to normal TLB handling */ 643 b DARFixed /* Go back to normal TLB handling */
684 644
685 /* special handling for r10,r11 since these are modified already */ 645 /* special handling for r10,r11 since these are modified already */
686153: lwz r11, 4(r0) /* load r11 from memory */ 646153: mfspr r11, SPRN_SPRG_SCRATCH1 /* load r11 from SPRN_SPRG_SCRATCH1 */
687 b 155f 647 add r10, r10, r11 /* add it */
688154: mfspr r11, SPRN_M_TW /* load r10 from M_TW */ 648 mfctr r11 /* restore r11 */
689155: add r10, r10, r11 /* add it */ 649 b 151b
650154: mfspr r11, SPRN_SPRG_SCRATCH0 /* load r10 from SPRN_SPRG_SCRATCH0 */
651 add r10, r10, r11 /* add it */
690 mfctr r11 /* restore r11 */ 652 mfctr r11 /* restore r11 */
691 b 151b 653 b 151b
692#endif 654#endif