aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/head_8xx.S147
1 files changed, 143 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index a9f1ace484d5..c00120d56f8f 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -494,11 +494,16 @@ DataTLBError:
494 494
495 mfspr r10, SPRN_DAR 495 mfspr r10, SPRN_DAR
496 cmpwi cr0, r10, 0x00f0 496 cmpwi cr0, r10, 0x00f0
497 beq- 2f /* must be a buggy dcbX, icbi insn. */ 497 beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
498 498DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */
499 mfspr r11, SPRN_DSISR 499 mfspr r11, SPRN_DSISR
500 andis. r11, r11, 0x4800 /* !translation or protection */ 500 /* As the DAR fixup may clear store we may have all 3 states zero.
501 bne 2f /* branch if either is set */ 501 * Make sure only 0x0200(store) falls down into DIRTY handling
502 */
503 andis. r11, r11, 0x4a00 /* !translation, protection or store */
504 srwi r11, r11, 16
505 cmpwi cr0, r11, 0x0200 /* just store ? */
506 bne 2f
502 /* Only Change bit left now, do it here as it is faster 507 /* Only Change bit left now, do it here as it is faster
503 * than trapping to the C fault handler. 508 * than trapping to the C fault handler.
504 */ 509 */
@@ -604,6 +609,140 @@ DataTLBError:
604 609
605 . = 0x2000 610 . = 0x2000
606 611
612/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
613 * by decoding the registers used by the dcbx instruction and adding them.
614 * DAR is set to the calculated address and r10 also holds the EA on exit.
615 */
616 /* define if you don't want to use self modifying code */
617#define NO_SELF_MODIFYING_CODE
618FixupDAR:/* Entry point for dcbx workaround. */
619 /* fetch instruction from memory. */
620 mfspr r10, SPRN_SRR0
621 DO_8xx_CPU6(0x3780, r3)
622 mtspr SPRN_MD_EPN, r10
623 mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */
624 cmplwi cr0, r11, 0x0800
625 blt- 3f /* Branch if user space */
626 lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
627 ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
628 rlwimi r11, r10, 32-20, 0xffc /* r11 = r11&~0xffc|(r10>>20)&0xffc */
6293: lwz r11, 0(r11) /* Get the level 1 entry */
630 DO_8xx_CPU6(0x3b80, r3)
631 mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
632 mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
633 lwz r11, 0(r11) /* Get the pte */
634 /* concat physical page address(r11) and page offset(r10) */
635 rlwimi r11, r10, 0, 20, 31
636 lwz r11,0(r11)
637/* Check if it really is a dcbx instruction. */
638/* dcbt and dcbtst does not generate DTLB Misses/Errors,
639 * no need to include them here */
640 srwi r10, r11, 26 /* check if major OP code is 31 */
641 cmpwi cr0, r10, 31
642 bne- 141f
643 rlwinm r10, r11, 0, 21, 30
644 cmpwi cr0, r10, 2028 /* Is dcbz? */
645 beq+ 142f
646 cmpwi cr0, r10, 940 /* Is dcbi? */
647 beq+ 142f
648 cmpwi cr0, r10, 108 /* Is dcbst? */
649 beq+ 144f /* Fix up store bit! */
650 cmpwi cr0, r10, 172 /* Is dcbf? */
651 beq+ 142f
652 cmpwi cr0, r10, 1964 /* Is icbi? */
653 beq+ 142f
654141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */
655 b DARFixed /* Nope, go back to normal TLB processing */
656
657144: mfspr r10, SPRN_DSISR
658 rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */
659 mtspr SPRN_DSISR, r10
660142: /* continue, it was a dcbx, dcbi instruction. */
661#ifdef CONFIG_8xx_CPU6
662 lwz r3, 8(r0) /* restore r3 from memory */
663#endif
664#ifndef NO_SELF_MODIFYING_CODE
665 andis. r10,r11,0x1f /* test if reg RA is r0 */
666 li r10,modified_instr@l
667 dcbtst r0,r10 /* touch for store */
668 rlwinm r11,r11,0,0,20 /* Zero lower 10 bits */
669 oris r11,r11,640 /* Transform instr. to a "add r10,RA,RB" */
670 ori r11,r11,532
671 stw r11,0(r10) /* store add/and instruction */
672 dcbf 0,r10 /* flush new instr. to memory. */
673 icbi 0,r10 /* invalidate instr. cache line */
674 lwz r11, 4(r0) /* restore r11 from memory */
675 mfspr r10, SPRN_M_TW /* restore r10 from M_TW */
676 isync /* Wait until new instr is loaded from memory */
677modified_instr:
678 .space 4 /* this is where the add instr. is stored */
679 bne+ 143f
680 subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */
681143: mtdar r10 /* store faulting EA in DAR */
682 b DARFixed /* Go back to normal TLB handling */
683#else
684 mfctr r10
685 mtdar r10 /* save ctr reg in DAR */
686 rlwinm r10, r11, 24, 24, 28 /* offset into jump table for reg RB */
687 addi r10, r10, 150f@l /* add start of table */
688 mtctr r10 /* load ctr with jump address */
689 xor r10, r10, r10 /* sum starts at zero */
690 bctr /* jump into table */
691150:
692 add r10, r10, r0 ;b 151f
693 add r10, r10, r1 ;b 151f
694 add r10, r10, r2 ;b 151f
695 add r10, r10, r3 ;b 151f
696 add r10, r10, r4 ;b 151f
697 add r10, r10, r5 ;b 151f
698 add r10, r10, r6 ;b 151f
699 add r10, r10, r7 ;b 151f
700 add r10, r10, r8 ;b 151f
701 add r10, r10, r9 ;b 151f
702 mtctr r11 ;b 154f /* r10 needs special handling */
703 mtctr r11 ;b 153f /* r11 needs special handling */
704 add r10, r10, r12 ;b 151f
705 add r10, r10, r13 ;b 151f
706 add r10, r10, r14 ;b 151f
707 add r10, r10, r15 ;b 151f
708 add r10, r10, r16 ;b 151f
709 add r10, r10, r17 ;b 151f
710 add r10, r10, r18 ;b 151f
711 add r10, r10, r19 ;b 151f
712 add r10, r10, r20 ;b 151f
713 add r10, r10, r21 ;b 151f
714 add r10, r10, r22 ;b 151f
715 add r10, r10, r23 ;b 151f
716 add r10, r10, r24 ;b 151f
717 add r10, r10, r25 ;b 151f
718 add r10, r10, r26 ;b 151f
719 add r10, r10, r27 ;b 151f
720 add r10, r10, r28 ;b 151f
721 add r10, r10, r29 ;b 151f
722 add r10, r10, r30 ;b 151f
723 add r10, r10, r31
724151:
725 rlwinm. r11,r11,19,24,28 /* offset into jump table for reg RA */
726 beq 152f /* if reg RA is zero, don't add it */
727 addi r11, r11, 150b@l /* add start of table */
728 mtctr r11 /* load ctr with jump address */
729 rlwinm r11,r11,0,16,10 /* make sure we don't execute this more than once */
730 bctr /* jump into table */
731152:
732 mfdar r11
733 mtctr r11 /* restore ctr reg from DAR */
734 mtdar r10 /* save fault EA to DAR */
735 b DARFixed /* Go back to normal TLB handling */
736
737 /* special handling for r10,r11 since these are modified already */
738153: lwz r11, 4(r0) /* load r11 from memory */
739 b 155f
740154: mfspr r11, SPRN_M_TW /* load r10 from M_TW */
741155: add r10, r10, r11 /* add it */
742 mfctr r11 /* restore r11 */
743 b 151b
744#endif
745
607 .globl giveup_fpu 746 .globl giveup_fpu
608giveup_fpu: 747giveup_fpu:
609 blr 748 blr