]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/powerpc/kernel/exceptions-64e.S
powerpc/book3e-64: Remove duplicated #include
[mv-sheeva.git] / arch / powerpc / kernel / exceptions-64e.S
index 695d4847d22829bfb7e9e61c360150481deb1b32..24dcc0ecf24628f47825c43aa3a251cf8575dcda 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/cputable.h>
 #include <asm/setup.h>
 #include <asm/thread_info.h>
-#include <asm/reg.h>
 #include <asm/exception-64e.h>
 #include <asm/bug.h>
 #include <asm/irqflags.h>
@@ -616,18 +615,214 @@ bad_stack_book3e:
  * Setup the initial TLB for a core. This current implementation
  * assume that whatever we are running off will not conflict with
  * the new mapping at PAGE_OFFSET.
- * We also make various assumptions about the processor we run on,
- * this might have to be made more flexible based on the content
- * of MMUCFG and friends.
  */
 _GLOBAL(initial_tlb_book3e)
 
+       /* Look for the first TLB with IPROT set */
+       mfspr   r4,SPRN_TLB0CFG
+       andi.   r3,r4,TLBnCFG_IPROT
+       lis     r3,MAS0_TLBSEL(0)@h
+       bne     found_iprot
+
+       mfspr   r4,SPRN_TLB1CFG
+       andi.   r3,r4,TLBnCFG_IPROT
+       lis     r3,MAS0_TLBSEL(1)@h
+       bne     found_iprot
+
+       mfspr   r4,SPRN_TLB2CFG
+       andi.   r3,r4,TLBnCFG_IPROT
+       lis     r3,MAS0_TLBSEL(2)@h
+       bne     found_iprot
+
+       lis     r3,MAS0_TLBSEL(3)@h
+       mfspr   r4,SPRN_TLB3CFG
+       /* fall through */
+
+found_iprot:
+       andi.   r5,r4,TLBnCFG_HES
+       bne     have_hes
+
+       mflr    r8                              /* save LR */
+/* 1. Find the index of the entry we're executing in
+ *
+ * r3 = MAS0_TLBSEL (for the iprot array)
+ * r4 = SPRN_TLBnCFG
+ */
+       bl      invstr                          /* Find our address */
+invstr:        mflr    r6                              /* Make it accessible */
+       mfmsr   r7
+       rlwinm  r5,r7,27,31,31                  /* extract MSR[IS] */
+       mfspr   r7,SPRN_PID
+       slwi    r7,r7,16
+       or      r7,r7,r5
+       mtspr   SPRN_MAS6,r7
+       tlbsx   0,r6                            /* search MSR[IS], SPID=PID */
+
+       mfspr   r3,SPRN_MAS0
+       rlwinm  r5,r3,16,20,31                  /* Extract MAS0(Entry) */
+
+       mfspr   r7,SPRN_MAS1                    /* Insure IPROT set */
+       oris    r7,r7,MAS1_IPROT@h
+       mtspr   SPRN_MAS1,r7
+       tlbwe
+
+/* 2. Invalidate all entries except the entry we're executing in
+ *
+ * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in
+ * r4 = SPRN_TLBnCFG
+ * r5 = ESEL of entry we are running in
+ */
+       andi.   r4,r4,TLBnCFG_N_ENTRY           /* Extract # entries */
+       li      r6,0                            /* Set Entry counter to 0 */
+1:     mr      r7,r3                           /* Set MAS0(TLBSEL) */
+       rlwimi  r7,r6,16,4,15                   /* Setup MAS0 = TLBSEL | ESEL(r6) */
+       mtspr   SPRN_MAS0,r7
+       tlbre
+       mfspr   r7,SPRN_MAS1
+       rlwinm  r7,r7,0,2,31                    /* Clear MAS1 Valid and IPROT */
+       cmpw    r5,r6
+       beq     skpinv                          /* Dont update the current execution TLB */
+       mtspr   SPRN_MAS1,r7
+       tlbwe
+       isync
+skpinv:        addi    r6,r6,1                         /* Increment */
+       cmpw    r6,r4                           /* Are we done? */
+       bne     1b                              /* If not, repeat */
+
+       /* Invalidate all TLBs */
+       PPC_TLBILX_ALL(0,0)
+       sync
+       isync
+
+/* 3. Setup a temp mapping and jump to it
+ *
+ * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in
+ * r5 = ESEL of entry we are running in
+ */
+       andi.   r7,r5,0x1       /* Find an entry not used and is non-zero */
+       addi    r7,r7,0x1
+       mr      r4,r3           /* Set MAS0(TLBSEL) = 1 */
+       mtspr   SPRN_MAS0,r4
+       tlbre
+
+       rlwimi  r4,r7,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r7) */
+       mtspr   SPRN_MAS0,r4
+
+       mfspr   r7,SPRN_MAS1
+       xori    r6,r7,MAS1_TS           /* Setup TMP mapping in the other Address space */
+       mtspr   SPRN_MAS1,r6
+
+       tlbwe
+
+       mfmsr   r6
+       xori    r6,r6,MSR_IS
+       mtspr   SPRN_SRR1,r6
+       bl      1f              /* Find our address */
+1:     mflr    r6
+       addi    r6,r6,(2f - 1b)
+       mtspr   SPRN_SRR0,r6
+       rfi
+2:
+
+/* 4. Clear out PIDs & Search info
+ *
+ * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
+ * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
+ * r5 = MAS3
+ */
+       li      r6,0
+       mtspr   SPRN_MAS6,r6
+       mtspr   SPRN_PID,r6
+
+/* 5. Invalidate mapping we started in
+ *
+ * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
+ * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
+ * r5 = MAS3
+ */
+       mtspr   SPRN_MAS0,r3
+       tlbre
+       mfspr   r6,SPRN_MAS1
+       rlwinm  r6,r6,0,2,0     /* clear IPROT */
+       mtspr   SPRN_MAS1,r6
+       tlbwe
+
+       /* Invalidate TLB1 */
+       PPC_TLBILX_ALL(0,0)
+       sync
+       isync
+
+/* The mapping only needs to be cache-coherent on SMP */
+#ifdef CONFIG_SMP
+#define M_IF_SMP       MAS2_M
+#else
+#define M_IF_SMP       0
+#endif
+
+/* 6. Setup KERNELBASE mapping in TLB[0]
+ *
+ * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
+ * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
+ * r5 = MAS3
+ */
+       rlwinm  r3,r3,0,16,3    /* clear ESEL */
+       mtspr   SPRN_MAS0,r3
+       lis     r6,(MAS1_VALID|MAS1_IPROT)@h
+       ori     r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l
+       mtspr   SPRN_MAS1,r6
+
+       LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET | M_IF_SMP)
+       mtspr   SPRN_MAS2,r6
+
+       rlwinm  r5,r5,0,0,25
+       ori     r5,r5,MAS3_SR | MAS3_SW | MAS3_SX
+       mtspr   SPRN_MAS3,r5
+       li      r5,-1
+       rlwinm  r5,r5,0,0,25
+
+       tlbwe
+
+/* 7. Jump to KERNELBASE mapping
+ *
+ * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
+ */
+       /* Now we branch the new virtual address mapped by this entry */
+       LOAD_REG_IMMEDIATE(r6,2f)
+       lis     r7,MSR_KERNEL@h
+       ori     r7,r7,MSR_KERNEL@l
+       mtspr   SPRN_SRR0,r6
+       mtspr   SPRN_SRR1,r7
+       rfi                             /* start execution out of TLB1[0] entry */
+2:
+
+/* 8. Clear out the temp mapping
+ *
+ * r4 = MAS0 w/TLBSEL & ESEL for the entry we are running in
+ */
+       mtspr   SPRN_MAS0,r4
+       tlbre
+       mfspr   r5,SPRN_MAS1
+       rlwinm  r5,r5,0,2,0     /* clear IPROT */
+       mtspr   SPRN_MAS1,r5
+       tlbwe
+
+       /* Invalidate TLB1 */
+       PPC_TLBILX_ALL(0,0)
+       sync
+       isync
+
+       /* We translate LR and return */
+       tovirt(r8,r8)
+       mtlr    r8
+       blr
+
+have_hes:
        /* Setup MAS 0,1,2,3 and 7 for tlbwe of a 1G entry that maps the
         * kernel linear mapping. We also set MAS8 once for all here though
         * that will have to be made dependent on whether we are running under
         * a hypervisor I suppose.
         */
-       li      r3,MAS0_HES | MAS0_WQ_ALLWAYS
+       ori     r3,r3,MAS0_HES | MAS0_WQ_ALLWAYS
        mtspr   SPRN_MAS0,r3
        lis     r3,(MAS1_VALID | MAS1_IPROT)@h
        ori     r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT
@@ -774,11 +969,32 @@ _STATIC(init_thread_book3e)
        /* Make sure interrupts are off */
        wrteei  0
 
-       /* disable watchdog and FIT and enable DEC interrupts */
-       lis     r3,TCR_DIE@h
+       /* disable all timers and clear out status */
+       li      r3,0
        mtspr   SPRN_TCR,r3
+       mfspr   r3,SPRN_TSR
+       mtspr   SPRN_TSR,r3
 
        blr
 
+_GLOBAL(__setup_base_ivors)
+       SET_IVOR(0, 0x020) /* Critical Input */
+       SET_IVOR(1, 0x000) /* Machine Check */
+       SET_IVOR(2, 0x060) /* Data Storage */ 
+       SET_IVOR(3, 0x080) /* Instruction Storage */
+       SET_IVOR(4, 0x0a0) /* External Input */ 
+       SET_IVOR(5, 0x0c0) /* Alignment */ 
+       SET_IVOR(6, 0x0e0) /* Program */ 
+       SET_IVOR(7, 0x100) /* FP Unavailable */ 
+       SET_IVOR(8, 0x120) /* System Call */ 
+       SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */ 
+       SET_IVOR(10, 0x160) /* Decrementer */ 
+       SET_IVOR(11, 0x180) /* Fixed Interval Timer */ 
+       SET_IVOR(12, 0x1a0) /* Watchdog Timer */ 
+       SET_IVOR(13, 0x1c0) /* Data TLB Error */ 
+       SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
+       SET_IVOR(15, 0x040) /* Debug */
 
+       sync
 
+       blr