This is an assembler version to fixup DAR not being set
by dcbX, icbi instructions. There are two versions, one
uses selfmodifing code, the other uses a
jump table but is much bigger(default).
---
 arch/powerpc/kernel/head_8xx.S |  146 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 145 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 093176c..9839e79 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -494,7 +494,8 @@ DataTLBError:
 
        mfspr   r10, SPRN_DAR
        cmpwi   cr0, r10, 0x00f0
-       beq-    2f      /* must be a buggy dcbX, icbi insn. */
+       beq-    FixDAR  /* must be a buggy dcbX, icbi insn. */
+DARFix:        /* Return from dcbx instruction bug workaround, r10 holds value 
of DAR */
 
        mfspr   r11, SPRN_DSISR
        andis.  r11, r11, 0x4800        /* !translation or protection */
@@ -604,6 +605,149 @@ DataTLBError:
 
        . = 0x2000
 
+/* This is the procedure to calculate the data EA for buggy dcbx,dcbi 
instructions
+ * by decoding the registers used by the dcbx instruction and adding them.
+ * DAR is set to the calculated address and r10 also holds the EA on exit.
+ */
+#define NO_SELF_MODIFYING_CODE /* define if you don't want to use self 
modifying code */
+       nop     /* A few nops to make the modified_instr: space below cache 
line aligned */
+       nop
+139:   /* fetch instruction from userspace memory */
+       DO_8xx_CPU6(0x3780, r3)
+       mtspr   SPRN_MD_EPN, r10
+       mfspr   r11, SPRN_M_TWB /* Get level 1 table entry address */
+       lwz     r11, 0(r11)     /* Get the level 1 entry */
+       tophys  (r11, r11)
+       DO_8xx_CPU6(0x3b80, r3)
+       mtspr   SPRN_MD_TWC, r11        /* Load pte table base address */
+       mfspr   r11, SPRN_MD_TWC        /* ....and get the pte address */
+       lwz     r11, 0(r11)     /* Get the pte */
+       /* concat physical page address(r11) and page offset(r10) */
+       rlwimi  r11, r10, 0, 20, 31
+       b       140f
+FixDAR:        /* Entry point for dcbx workaround. */
+       /* fetch instruction from memory. */
+       mfspr   r10, SPRN_SRR0
+       andis.  r11, r10, 0x8000
+       tophys  (r11, r10)
+       beq-    139b            /* Branch if user space address */
+140:   lwz     r11,0(r11)
+#ifdef CONFIG_8xx_CPU6
+       lwz     r3, 8(r0)       /* restore r3 from memory */
+#endif
+#ifndef NO_SELF_MODIFYING_CODE
+       andis.  r10,r11,0x1f    /* test if reg RA is r0 */
+       li      r10,modified_in...@l
+       dcbtst  r0,r10          /* touch for store */
+       rlwinm  r11,r11,0,0,20  /* Zero lower 10 bits */
+       oris    r11,r11,640     /* Transform instr. to a "add r10,RA,RB" */
+       ori     r11,r11,532
+       stw     r11,0(r10)      /* store add/and instruction */
+       dcbf    0,r10           /* flush new instr. to memory. */
+       icbi    0,r10           /* invalidate instr. cache line */
+       lwz     r11, 4(r0)      /* restore r11 from memory */
+       mfspr   r10, SPRN_M_TW  /* restore r10 from M_TW */
+       isync                   /* Wait until new instr is loaded from memory */
+modified_instr:
+       .space  4               /* this is where the add/and instr. is stored */
+       bne+    143f
+       subf    r10,r0,r10      /* r10=r10-r0, only if reg RA is r0 */
+143:   mtdar   r10             /* store faulting EA in DAR */
+       b       DARFix          /* Go back to normal TLB handling */
+#else
+       mfctr   r10
+       mtdar   r10                     /* save ctr reg in DAR */
+       rlwinm  r10, r11, 24, 24, 28    /* offset into jump table for reg RB */
+       addi    r10, r10, 1...@l        /* add start of table */
+       mtctr   r10                     /* load ctr with jump address */
+       xor     r10, r10, r10           /* sum starts at zero */
+       bctr                            /* jump into table */
+150:
+       add     r10, r10, r0
+       b       151f
+       add     r10, r10, r1
+       b       151f
+       add     r10, r10, r2
+       b       151f
+       add     r10, r10, r3
+       b       151f
+       add     r10, r10, r4
+       b       151f
+       add     r10, r10, r5
+       b       151f
+       add     r10, r10, r6
+       b       151f
+       add     r10, r10, r7
+       b       151f
+       add     r10, r10, r8
+       b       151f
+       add     r10, r10, r9
+       b       151f
+       add     r10, r10, r10
+       b       151f
+       add     r10, r10, r11
+       b       151f
+       add     r10, r10, r12
+       b       151f
+       add     r10, r10, r13
+       b       151f
+       add     r10, r10, r14
+       b       151f
+       add     r10, r10, r15
+       b       151f
+       add     r10, r10, r16
+       b       151f
+       add     r10, r10, r17
+       b       151f
+       add     r10, r10, r18
+       b       151f
+       add     r10, r10, r19
+       b       151f
+       mtctr   r11     /* r10 needs special handling */
+       b       154f
+       mtctr   r11     /* r11 needs special handling */
+       b       153f
+       add     r10, r10, r22
+       b       151f
+       add     r10, r10, r23
+       b       151f
+       add     r10, r10, r24
+       b       151f
+       add     r10, r10, r25
+       b       151f
+       add     r10, r10, r25
+       b       151f
+       add     r10, r10, r27
+       b       151f
+       add     r10, r10, r28
+       b       151f
+       add     r10, r10, r29
+       b       151f
+       add     r10, r10, r30
+       b       151f
+       add     r10, r10, r31
+151:
+       rlwinm. r11,r11,19,24,28        /* offset into jump table for reg RA */
+       beq     152f                    /* if reg RA is zero, don't add it */ 
+       addi    r11, r11, 1...@l        /* add start of table */
+       mtctr   r11                     /* load ctr with jump address */
+       rlwinm  r11,r11,0,16,10         /* make sure we don't execute this more 
than once */
+       bctr                            /* jump into table */
+152:
+       mfdar   r11
+       mtctr   r11                     /* restore ctr reg from DAR */
+       mtdar   r10                     /* save fault EA to DAR */
+       b       DARFix                  /* Go back to normal TLB handling */
+
+       /* special handling for r10,r11 since these are modified already */
+153:   lwz     r11, 4(r0)      /* load r11 from memory */
+       b       155f
+154:   mfspr   r11, SPRN_M_TW  /* load r10 from M_TW */
+155:   add     r10, r10, r11   /* add it */
+       mfctr   r11             /* restore r11 */
+       b       151b
+#endif
+
        .globl  giveup_fpu
 giveup_fpu:
        blr
-- 
1.6.4.4

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to