Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[cascardo/linux.git] / arch / powerpc / kernel / head_8xx.S
index 38efa86..d99aac0 100644 (file)
 
 /* Macro to make the code more readable. */
 #ifdef CONFIG_8xx_CPU6
-#define DO_8xx_CPU6(val, reg)  \
-       li      reg, val;       \
-       stw     reg, 12(r0);    \
-       lwz     reg, 12(r0);
+#define SPRN_MI_TWC_ADDR       0x2b80
+#define SPRN_MI_RPN_ADDR       0x2d80
+#define SPRN_MD_TWC_ADDR       0x3b80
+#define SPRN_MD_RPN_ADDR       0x3d80
+
+#define MTSPR_CPU6(spr, reg, treg)     \
+       li      treg, spr##_ADDR;       \
+       stw     treg, 12(r0);           \
+       lwz     treg, 12(r0);           \
+       mtspr   spr, reg
 #else
-#define DO_8xx_CPU6(val, reg)
+#define MTSPR_CPU6(spr, reg, treg)     \
+       mtspr   spr, reg
 #endif
 
 /*
  * Value for the bits that have fixed value in RPN entries.
  * Also used for tagging DAR for DTLBerror.
  */
+#ifdef CONFIG_PPC_16K_PAGES
+#define RPN_PATTERN    (0x00f0 | MD_SPS16K)
+#else
 #define RPN_PATTERN    0x00f0
+#endif
 
        __HEAD
 _ENTRY(_stext);
@@ -72,13 +83,6 @@ _ENTRY(_start);
  * 8M 1:1.  I also mapped an additional I/O space 1:1 so we can get to
  * the "internal" processor registers before MMU_init is called.
  *
- * The TLB code currently contains a major hack.  Since I use the condition
- * code register, I have to save and restore it.  I am out of registers, so
- * I just store it in memory location 0 (the TLB handlers are not reentrant).
- * To avoid making any decisions, I need to use the "segment" valid bit
- * in the first level table, but that would require many changes to the
- * Linux page directory/table functions that I don't want to do right now.
- *
  *     -- Dan
  */
        .globl  __start
@@ -295,7 +299,7 @@ SystemCall:
  */
 InstructionTLBMiss:
 #ifdef CONFIG_8xx_CPU6
-       stw     r3, 8(r0)
+       mtspr   SPRN_DAR, r3
 #endif
        EXCEPTION_PROLOG_0
        mtspr   SPRN_SPRG_SCRATCH2, r10
@@ -331,9 +335,7 @@ InstructionTLBMiss:
        /* We have a pte table, so load the MI_TWC with the attributes
         * for this "segment."
         */
-       ori     r11,r11,1               /* Set valid bit */
-       DO_8xx_CPU6(0x2b80, r3)
-       mtspr   SPRN_MI_TWC, r11        /* Set segment attributes */
+       MTSPR_CPU6(SPRN_MI_TWC, r11, r3)        /* Set segment attributes */
        mfspr   r11, SPRN_SRR0  /* Get effective address of fault */
        /* Extract level 2 index */
        rlwinm  r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
@@ -342,7 +344,10 @@ InstructionTLBMiss:
 #ifdef CONFIG_SWAP
        andi.   r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT
        cmpwi   cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT
+       li      r11, RPN_PATTERN
        bne-    cr0, 2f
+#else
+       li      r11, RPN_PATTERN
 #endif
        /* The Linux PTE won't go exactly into the MMU TLB.
         * Software indicator bits 21 and 28 must be clear.
@@ -350,38 +355,37 @@ InstructionTLBMiss:
         * set.  All other Linux PTE bits control the behavior
         * of the MMU.
         */
-       li      r11, RPN_PATTERN
        rlwimi  r10, r11, 0, 0x07f8     /* Set 24-27, clear 21-23,28 */
-       DO_8xx_CPU6(0x2d80, r3)
-       mtspr   SPRN_MI_RPN, r10        /* Update TLB entry */
+       MTSPR_CPU6(SPRN_MI_RPN, r10, r3)        /* Update TLB entry */
 
        /* Restore registers */
 #ifdef CONFIG_8xx_CPU6
-       lwz     r3, 8(r0)
+       mfspr   r3, SPRN_DAR
+       mtspr   SPRN_DAR, r11   /* Tag DAR */
 #endif
        mfspr   r10, SPRN_SPRG_SCRATCH2
        EXCEPTION_EPILOG_0
        rfi
 2:
-       mfspr   r11, SPRN_SRR1
+       mfspr   r10, SPRN_SRR1
        /* clear all error bits as TLB Miss
         * sets a few unconditionally
        */
-       rlwinm  r11, r11, 0, 0xffff
-       mtspr   SPRN_SRR1, r11
+       rlwinm  r10, r10, 0, 0xffff
+       mtspr   SPRN_SRR1, r10
 
        /* Restore registers */
 #ifdef CONFIG_8xx_CPU6
-       lwz     r3, 8(r0)
+       mfspr   r3, SPRN_DAR
+       mtspr   SPRN_DAR, r11   /* Tag DAR */
 #endif
        mfspr   r10, SPRN_SPRG_SCRATCH2
-       EXCEPTION_EPILOG_0
-       b       InstructionTLBError
+       b       InstructionTLBError1
 
        . = 0x1200
 DataStoreTLBMiss:
 #ifdef CONFIG_8xx_CPU6
-       stw     r3, 8(r0)
+       mtspr   SPRN_DAR, r3
 #endif
        EXCEPTION_PROLOG_0
        mtspr   SPRN_SPRG_SCRATCH2, r10
@@ -410,7 +414,6 @@ DataStoreTLBMiss:
        rlwimi  r10, r11, 0, 0, 32 - PAGE_SHIFT - 1     /* Add level 2 base */
        lwz     r10, 0(r10)     /* Get the pte */
 
-       ori     r11, r11, 1     /* Set valid bit in physical L2 page */
        /* Insert the Guarded flag into the TWC from the Linux PTE.
         * It is bit 27 of both the Linux PTE and the TWC (at least
         * I got that right :-).  It will be better when we can put
@@ -422,8 +425,7 @@ DataStoreTLBMiss:
         * It is bit 25 in the Linux PTE and bit 30 in the TWC
         */
        rlwimi  r11, r10, 32-5, 30, 30
-       DO_8xx_CPU6(0x3b80, r3)
-       mtspr   SPRN_MD_TWC, r11
+       MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
 
        /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
         * We also need to know if the insn is a load/store, so:
@@ -439,14 +441,8 @@ DataStoreTLBMiss:
        and     r11, r11, r10
        rlwimi  r10, r11, 0, _PAGE_PRESENT
 #endif
-       /* Honour kernel RO, User NA */
-       /* 0x200 == Extended encoding, bit 22 */
-       rlwimi  r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */
-       /* r11 =  (r10 & _PAGE_RW) >> 1 */
-       rlwinm  r11, r10, 32-1, 0x200
-       or      r10, r11, r10
-       /* invert RW and 0x200 bits */
-       xori    r10, r10, _PAGE_RW | 0x200
+       /* invert RW */
+       xori    r10, r10, _PAGE_RW
 
        /* The Linux PTE won't go exactly into the MMU TLB.
         * Software indicator bits 22 and 28 must be clear.
@@ -456,12 +452,11 @@ DataStoreTLBMiss:
         */
 2:     li      r11, RPN_PATTERN
        rlwimi  r10, r11, 0, 24, 28     /* Set 24-27, clear 28 */
-       DO_8xx_CPU6(0x3d80, r3)
-       mtspr   SPRN_MD_RPN, r10        /* Update TLB entry */
+       MTSPR_CPU6(SPRN_MD_RPN, r10, r3)        /* Update TLB entry */
 
        /* Restore registers */
 #ifdef CONFIG_8xx_CPU6
-       lwz     r3, 8(r0)
+       mfspr   r3, SPRN_DAR
 #endif
        mtspr   SPRN_DAR, r11   /* Tag DAR */
        mfspr   r10, SPRN_SPRG_SCRATCH2
@@ -474,11 +469,17 @@ DataStoreTLBMiss:
  */
        . = 0x1300
 InstructionTLBError:
-       EXCEPTION_PROLOG
+       EXCEPTION_PROLOG_0
+InstructionTLBError1:
+       EXCEPTION_PROLOG_1
+       EXCEPTION_PROLOG_2
        mr      r4,r12
        mr      r5,r9
+       andis.  r10,r5,0x4000
+       beq+    1f
+       tlbie   r4
        /* 0x400 is InstructionAccess exception, needed by bad_page_fault() */
-       EXC_XFER_LITE(0x400, handle_page_fault)
+1:     EXC_XFER_LITE(0x400, handle_page_fault)
 
 /* This is the data TLB error on the MPC8xx.  This could be due to
  * many reasons, including a dirty update to a pte.  We bail out to
@@ -494,11 +495,13 @@ DataTLBError:
 DARFixed:/* Return from dcbx instruction bug workaround */
        EXCEPTION_PROLOG_1
        EXCEPTION_PROLOG_2
-       mfspr   r10,SPRN_DSISR
-       stw     r10,_DSISR(r11)
-       mr      r5,r10
+       mfspr   r5,SPRN_DSISR
+       stw     r5,_DSISR(r11)
        mfspr   r4,SPRN_DAR
-       li      r10,RPN_PATTERN
+       andis.  r10,r5,0x4000
+       beq+    1f
+       tlbie   r4
+1:     li      r10,RPN_PATTERN
        mtspr   SPRN_DAR,r10    /* Tag DAR, to be used in DTLB Error */
        /* 0x300 is DataAccess exception, needed by bad_page_fault() */
        EXC_XFER_LITE(0x300, handle_page_fault)
@@ -530,7 +533,7 @@ DARFixed:/* Return from dcbx instruction bug workaround */
 #define NO_SELF_MODIFYING_CODE
 FixupDAR:/* Entry point for dcbx workaround. */
 #ifdef CONFIG_8xx_CPU6
-       stw     r3, 8(r0)
+       mtspr   SPRN_DAR, r3
 #endif
        mtspr   SPRN_SPRG_SCRATCH2, r10
        /* fetch instruction from memory. */
@@ -549,7 +552,7 @@ FixupDAR:/* Entry point for dcbx workaround. */
        rlwinm  r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
        lwzx    r11, r10, r11   /* Get the pte */
 #ifdef CONFIG_8xx_CPU6
-       lwz     r3, 8(r0)       /* restore r3 from memory */
+       mfspr   r3, SPRN_DAR
 #endif
        /* concat physical page address(r11) and page offset(r10) */
        mfspr   r10, SPRN_SRR0