[SPARC64]: Fix userland FPU state corruption.
[deliverable/linux.git] / arch / sparc64 / kernel / entry.S
index cecdc0a7521f1d36fce506ab64e49ca41136d879..11a848402fb1a14f032fee7a434cdbe574b30467 100644 (file)
        .text
        .align          32
 
-       .globl          sparc64_vpte_patchme1
-       .globl          sparc64_vpte_patchme2
-/*
- * On a second level vpte miss, check whether the original fault is to the OBP 
- * range (note that this is only possible for instruction miss, data misses to
- * obp range do not use vpte). If so, go back directly to the faulting address.
- * This is because we want to read the tpc, otherwise we have no way of knowing
- * the 8k aligned faulting address if we are using >8k kernel pagesize. This
- * also ensures no vpte range addresses are dropped into tlb while obp is
- * executing (see inherit_locked_prom_mappings() rant).
- */
-sparc64_vpte_nucleus:
-       /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
-       mov             0xf, %g5
-       sllx            %g5, 28, %g5
-
-       /* Is addr >= LOW_OBP_ADDRESS?  */
-       cmp             %g4, %g5
-       blu,pn          %xcc, sparc64_vpte_patchme1
-        mov            0x1, %g5
-
-       /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
-       sllx            %g5, 32, %g5
-
-       /* Is addr < HI_OBP_ADDRESS?  */
-       cmp             %g4, %g5
-       blu,pn          %xcc, obp_iaddr_patch
-        nop
-
-       /* These two instructions are patched by paginig_init().  */
-sparc64_vpte_patchme1:
-       sethi           %hi(0), %g5
-sparc64_vpte_patchme2:
-       or              %g5, %lo(0), %g5
-
-       /* With kernel PGD in %g5, branch back into dtlb_backend.  */
-       ba,pt           %xcc, sparc64_kpte_continue
-        andn           %g1, 0x3, %g1   /* Finish PMD offset adjustment.  */
-
-vpte_noent:
-       /* Restore previous TAG_ACCESS, %g5 is zero, and we will
-        * skip over the trap instruction so that the top level
-        * TLB miss handler will thing this %g5 value is just an
-        * invalid PTE, thus branching to full fault processing.
-        */
-       mov             TLB_SFSR, %g1
-       stxa            %g4, [%g1 + %g1] ASI_DMMU
-       done
-
-       .globl          obp_iaddr_patch
-obp_iaddr_patch:
-       /* These two instructions patched by inherit_prom_mappings().  */
-       sethi           %hi(0), %g5
-       or              %g5, %lo(0), %g5
-
-       /* Behave as if we are at TL0.  */
-       wrpr            %g0, 1, %tl
-       rdpr            %tpc, %g4       /* Find original faulting iaddr */
-       srlx            %g4, 13, %g4    /* Throw out context bits */
-       sllx            %g4, 13, %g4    /* g4 has vpn + ctx0 now */
-
-       /* Restore previous TAG_ACCESS.  */
-       mov             TLB_SFSR, %g1
-       stxa            %g4, [%g1 + %g1] ASI_IMMU
-
-       /* Get PMD offset.  */
-       srlx            %g4, 23, %g6
-       and             %g6, 0x7ff, %g6
-       sllx            %g6, 2, %g6
-
-       /* Load PMD, is it valid?  */
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brz,pn          %g5, longpath
-        sllx           %g5, 11, %g5
-
-       /* Get PTE offset.  */
-       srlx            %g4, 13, %g6
-       and             %g6, 0x3ff, %g6
-       sllx            %g6, 3, %g6
-
-       /* Load PTE.  */
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brgez,pn        %g5, longpath
-        nop
-
-       /* TLB load and return from trap.  */
-       stxa            %g5, [%g0] ASI_ITLB_DATA_IN
-       retry
-
-       .globl          obp_daddr_patch
-obp_daddr_patch:
-       /* These two instructions patched by inherit_prom_mappings().  */
-       sethi           %hi(0), %g5
-       or              %g5, %lo(0), %g5
-
-       /* Get PMD offset.  */
-       srlx            %g4, 23, %g6
-       and             %g6, 0x7ff, %g6
-       sllx            %g6, 2, %g6
-
-       /* Load PMD, is it valid?  */
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brz,pn          %g5, longpath
-        sllx           %g5, 11, %g5
-
-       /* Get PTE offset.  */
-       srlx            %g4, 13, %g6
-       and             %g6, 0x3ff, %g6
-       sllx            %g6, 3, %g6
-
-       /* Load PTE.  */
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brgez,pn        %g5, longpath
-        nop
-
-       /* TLB load and return from trap.  */
-       stxa            %g5, [%g0] ASI_DTLB_DATA_IN
-       retry
-
-/*
- * On a first level data miss, check whether this is to the OBP range (note
- * that such accesses can be made by prom, as well as by kernel using
- * prom_getproperty on "address"), and if so, do not use vpte access ...
- * rather, use information saved during inherit_prom_mappings() using 8k
- * pagesize.
- */
-kvmap:
-       /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
-       mov             0xf, %g5
-       sllx            %g5, 28, %g5
-
-       /* Is addr >= LOW_OBP_ADDRESS?  */
-       cmp             %g4, %g5
-       blu,pn          %xcc, vmalloc_addr
-        mov            0x1, %g5
-
-       /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
-       sllx            %g5, 32, %g5
-
-       /* Is addr < HI_OBP_ADDRESS?  */
-       cmp             %g4, %g5
-       blu,pn          %xcc, obp_daddr_patch
-        nop
-
-vmalloc_addr:
-       /* If we get here, a vmalloc addr accessed, load kernel VPTE.  */
-       ldxa            [%g3 + %g6] ASI_N, %g5
-       brgez,pn        %g5, longpath
-        nop
-
-       /* PTE is valid, load into TLB and return from trap.  */
-       stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Reload TLB
-       retry
-
        /* This is trivial with the new code... */
        .globl          do_fpdis
 do_fpdis:
-       sethi           %hi(TSTATE_PEF), %g4                                    ! IEU0
+       sethi           %hi(TSTATE_PEF), %g4
        rdpr            %tstate, %g5
        andcc           %g5, %g4, %g0
        be,pt           %xcc, 1f
@@ -204,18 +50,18 @@ do_fpdis:
        add             %g0, %g0, %g0
        ba,a,pt         %xcc, rtrap_clr_l6
 
-1:     ldub            [%g6 + TI_FPSAVED], %g5                                 ! Load  Group
-       wr              %g0, FPRS_FEF, %fprs                                    ! LSU   Group+4bubbles
-       andcc           %g5, FPRS_FEF, %g0                                      ! IEU1  Group
-       be,a,pt         %icc, 1f                                                ! CTI
-        clr            %g7                                                     ! IEU0
-       ldx             [%g6 + TI_GSR], %g7                                     ! Load  Group
-1:     andcc           %g5, FPRS_DL, %g0                                       ! IEU1
-       bne,pn          %icc, 2f                                                ! CTI
-        fzero          %f0                                                     ! FPA
-       andcc           %g5, FPRS_DU, %g0                                       ! IEU1  Group
-       bne,pn          %icc, 1f                                                ! CTI
-        fzero          %f2                                                     ! FPA
+1:     ldub            [%g6 + TI_FPSAVED], %g5
+       wr              %g0, FPRS_FEF, %fprs
+       andcc           %g5, FPRS_FEF, %g0
+       be,a,pt         %icc, 1f
+        clr            %g7
+       ldx             [%g6 + TI_GSR], %g7
+1:     andcc           %g5, FPRS_DL, %g0
+       bne,pn          %icc, 2f
+        fzero          %f0
+       andcc           %g5, FPRS_DU, %g0
+       bne,pn          %icc, 1f
+        fzero          %f2
        faddd           %f0, %f2, %f4
        fmuld           %f0, %f2, %f6
        faddd           %f0, %f2, %f8
@@ -251,15 +97,17 @@ do_fpdis:
        faddd           %f0, %f2, %f4
        fmuld           %f0, %f2, %f6
        ldxa            [%g3] ASI_DMMU, %g5
-cplus_fptrap_insn_1:
-       sethi           %hi(0), %g2
+       sethi           %hi(sparc64_kern_sec_context), %g2
+       ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
        stxa            %g2, [%g3] ASI_DMMU
        membar          #Sync
        add             %g6, TI_FPREGS + 0xc0, %g2
        faddd           %f0, %f2, %f8
        fmuld           %f0, %f2, %f10
-       ldda            [%g1] ASI_BLK_S, %f32   ! grrr, where is ASI_BLK_NUCLEUS 8-(
+       membar          #Sync
+       ldda            [%g1] ASI_BLK_S, %f32
        ldda            [%g2] ASI_BLK_S, %f48
+       membar          #Sync
        faddd           %f0, %f2, %f12
        fmuld           %f0, %f2, %f14
        faddd           %f0, %f2, %f16
@@ -270,7 +118,6 @@ cplus_fptrap_insn_1:
        fmuld           %f0, %f2, %f26
        faddd           %f0, %f2, %f28
        fmuld           %f0, %f2, %f30
-       membar          #Sync
        b,pt            %xcc, fpdis_exit
         nop
 2:     andcc           %g5, FPRS_DU, %g0
@@ -280,15 +127,17 @@ cplus_fptrap_insn_1:
        fzero           %f34
        ldxa            [%g3] ASI_DMMU, %g5
        add             %g6, TI_FPREGS, %g1
-cplus_fptrap_insn_2:
-       sethi           %hi(0), %g2
+       sethi           %hi(sparc64_kern_sec_context), %g2
+       ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
        stxa            %g2, [%g3] ASI_DMMU
        membar          #Sync
        add             %g6, TI_FPREGS + 0x40, %g2
        faddd           %f32, %f34, %f36
        fmuld           %f32, %f34, %f38
-       ldda            [%g1] ASI_BLK_S, %f0    ! grrr, where is ASI_BLK_NUCLEUS 8-(
+       membar          #Sync
+       ldda            [%g1] ASI_BLK_S, %f0
        ldda            [%g2] ASI_BLK_S, %f16
+       membar          #Sync
        faddd           %f32, %f34, %f40
        fmuld           %f32, %f34, %f42
        faddd           %f32, %f34, %f44
@@ -301,18 +150,18 @@ cplus_fptrap_insn_2:
        fmuld           %f32, %f34, %f58
        faddd           %f32, %f34, %f60
        fmuld           %f32, %f34, %f62
-       membar          #Sync
        ba,pt           %xcc, fpdis_exit
         nop
 3:     mov             SECONDARY_CONTEXT, %g3
        add             %g6, TI_FPREGS, %g1
        ldxa            [%g3] ASI_DMMU, %g5
-cplus_fptrap_insn_3:
-       sethi           %hi(0), %g2
+       sethi           %hi(sparc64_kern_sec_context), %g2
+       ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
        stxa            %g2, [%g3] ASI_DMMU
        membar          #Sync
        mov             0x40, %g2
-       ldda            [%g1] ASI_BLK_S, %f0            ! grrr, where is ASI_BLK_NUCLEUS 8-(
+       membar          #Sync
+       ldda            [%g1] ASI_BLK_S, %f0
        ldda            [%g1 + %g2] ASI_BLK_S, %f16
        add             %g1, 0x80, %g1
        ldda            [%g1] ASI_BLK_S, %f32
@@ -473,8 +322,8 @@ do_fptrap_after_fsr:
        stx             %g3, [%g6 + TI_GSR]
        mov             SECONDARY_CONTEXT, %g3
        ldxa            [%g3] ASI_DMMU, %g5
-cplus_fptrap_insn_4:
-       sethi           %hi(0), %g2
+       sethi           %hi(sparc64_kern_sec_context), %g2
+       ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
        stxa            %g2, [%g3] ASI_DMMU
        membar          #Sync
        add             %g6, TI_FPREGS, %g2
@@ -495,45 +344,17 @@ cplus_fptrap_insn_4:
        ba,pt           %xcc, etrap
         wr             %g0, 0, %fprs
 
-cplus_fptrap_1:
-       sethi           %hi(CTX_CHEETAH_PLUS_CTX0), %g2
-
-       .globl          cheetah_plus_patch_fpdis
-cheetah_plus_patch_fpdis:
-       /* We configure the dTLB512_0 for 4MB pages and the
-        * dTLB512_1 for 8K pages when in context zero.
-        */
-       sethi                   %hi(cplus_fptrap_1), %o0
-       lduw                    [%o0 + %lo(cplus_fptrap_1)], %o1
-
-       set                     cplus_fptrap_insn_1, %o2
-       stw                     %o1, [%o2]
-       flush                   %o2
-       set                     cplus_fptrap_insn_2, %o2
-       stw                     %o1, [%o2]
-       flush                   %o2
-       set                     cplus_fptrap_insn_3, %o2
-       stw                     %o1, [%o2]
-       flush                   %o2
-       set                     cplus_fptrap_insn_4, %o2
-       stw                     %o1, [%o2]
-       flush                   %o2
-
-       retl
-        nop
-
        /* The registers for cross calls will be:
         *
         * DATA 0: [low 32-bits]  Address of function to call, jmp to this
         *         [high 32-bits] MMU Context Argument 0, place in %g5
-        * DATA 1: Address Argument 1, place in %g6
+        * DATA 1: Address Argument 1, place in %g1
         * DATA 2: Address Argument 2, place in %g7
         *
         * With this method we can do most of the cross-call tlb/cache
         * flushing very quickly.
         *
-        * Current CPU's IRQ worklist table is locked into %g1,
-        * don't touch.
+        * Current CPU's IRQ worklist table is locked into %g6, don't touch.
         */
        .text
        .align          32
@@ -927,139 +748,6 @@ __spitfire_insn_access_exception:
        ba,pt           %xcc, rtrap
         clr            %l6
 
-       /* Capture I/D/E-cache state into per-cpu error scoreboard.
-        *
-        * %g1:         (TL>=0) ? 1 : 0
-        * %g2:         scratch
-        * %g3:         scratch
-        * %g4:         AFSR
-        * %g5:         AFAR
-        * %g6:         current thread ptr
-        * %g7:         scratch
-        */
-#define CHEETAH_LOG_ERROR                                              \
-       /* Put "TL1" software bit into AFSR. */                         \
-       and             %g1, 0x1, %g1;                                  \
-       sllx            %g1, 63, %g2;                                   \
-       or              %g4, %g2, %g4;                                  \
-       /* Get log entry pointer for this cpu at this trap level. */    \
-       BRANCH_IF_JALAPENO(g2,g3,50f)                                   \
-       ldxa            [%g0] ASI_SAFARI_CONFIG, %g2;                   \
-       srlx            %g2, 17, %g2;                                   \
-       ba,pt           %xcc, 60f;                                      \
-        and            %g2, 0x3ff, %g2;                                \
-50:    ldxa            [%g0] ASI_JBUS_CONFIG, %g2;                     \
-       srlx            %g2, 17, %g2;                                   \
-       and             %g2, 0x1f, %g2;                                 \
-60:    sllx            %g2, 9, %g2;                                    \
-       sethi           %hi(cheetah_error_log), %g3;                    \
-       ldx             [%g3 + %lo(cheetah_error_log)], %g3;            \
-       brz,pn          %g3, 80f;                                       \
-        nop;                                                           \
-       add             %g3, %g2, %g3;                                  \
-       sllx            %g1, 8, %g1;                                    \
-       add             %g3, %g1, %g1;                                  \
-       /* %g1 holds pointer to the top of the logging scoreboard */    \
-       ldx             [%g1 + 0x0], %g7;                               \
-       cmp             %g7, -1;                                        \
-       bne,pn          %xcc, 80f;                                      \
-        nop;                                                           \
-       stx             %g4, [%g1 + 0x0];                               \
-       stx             %g5, [%g1 + 0x8];                               \
-       add             %g1, 0x10, %g1;                                 \
-       /* %g1 now points to D-cache logging area */                    \
-       set             0x3ff8, %g2;    /* DC_addr mask         */      \
-       and             %g5, %g2, %g2;  /* DC_addr bits of AFAR */      \
-       srlx            %g5, 12, %g3;                                   \
-       or              %g3, 1, %g3;    /* PHYS tag + valid     */      \
-10:    ldxa            [%g2] ASI_DCACHE_TAG, %g7;                      \
-       cmp             %g3, %g7;       /* TAG match?           */      \
-       bne,pt          %xcc, 13f;                                      \
-        nop;                                                           \
-       /* Yep, what we want, capture state. */                         \
-       stx             %g2, [%g1 + 0x20];                              \
-       stx             %g7, [%g1 + 0x28];                              \
-       /* A membar Sync is required before and after utag access. */   \
-       membar          #Sync;                                          \
-       ldxa            [%g2] ASI_DCACHE_UTAG, %g7;                     \
-       membar          #Sync;                                          \
-       stx             %g7, [%g1 + 0x30];                              \
-       ldxa            [%g2] ASI_DCACHE_SNOOP_TAG, %g7;                \
-       stx             %g7, [%g1 + 0x38];                              \
-       clr             %g3;                                            \
-12:    ldxa            [%g2 + %g3] ASI_DCACHE_DATA, %g7;               \
-       stx             %g7, [%g1];                                     \
-       add             %g3, (1 << 5), %g3;                             \
-       cmp             %g3, (4 << 5);                                  \
-       bl,pt           %xcc, 12b;                                      \
-        add            %g1, 0x8, %g1;                                  \
-       ba,pt           %xcc, 20f;                                      \
-        add            %g1, 0x20, %g1;                                 \
-13:    sethi           %hi(1 << 14), %g7;                              \
-       add             %g2, %g7, %g2;                                  \
-       srlx            %g2, 14, %g7;                                   \
-       cmp             %g7, 4;                                         \
-       bl,pt           %xcc, 10b;                                      \
-        nop;                                                           \
-       add             %g1, 0x40, %g1;                                 \
-20:    /* %g1 now points to I-cache logging area */                    \
-       set             0x1fe0, %g2;    /* IC_addr mask         */      \
-       and             %g5, %g2, %g2;  /* IC_addr bits of AFAR */      \
-       sllx            %g2, 1, %g2;    /* IC_addr[13:6]==VA[12:5] */   \
-       srlx            %g5, (13 - 8), %g3; /* Make PTAG */             \
-       andn            %g3, 0xff, %g3; /* Mask off undefined bits */   \
-21:    ldxa            [%g2] ASI_IC_TAG, %g7;                          \
-       andn            %g7, 0xff, %g7;                                 \
-       cmp             %g3, %g7;                                       \
-       bne,pt          %xcc, 23f;                                      \
-        nop;                                                           \
-       /* Yep, what we want, capture state. */                         \
-       stx             %g2, [%g1 + 0x40];                              \
-       stx             %g7, [%g1 + 0x48];                              \
-       add             %g2, (1 << 3), %g2;                             \
-       ldxa            [%g2] ASI_IC_TAG, %g7;                          \
-       add             %g2, (1 << 3), %g2;                             \
-       stx             %g7, [%g1 + 0x50];                              \
-       ldxa            [%g2] ASI_IC_TAG, %g7;                          \
-       add             %g2, (1 << 3), %g2;                             \
-       stx             %g7, [%g1 + 0x60];                              \
-       ldxa            [%g2] ASI_IC_TAG, %g7;                          \
-       stx             %g7, [%g1 + 0x68];                              \
-       sub             %g2, (3 << 3), %g2;                             \
-       ldxa            [%g2] ASI_IC_STAG, %g7;                         \
-       stx             %g7, [%g1 + 0x58];                              \
-       clr             %g3;                                            \
-       srlx            %g2, 2, %g2;                                    \
-22:    ldxa            [%g2 + %g3] ASI_IC_INSTR, %g7;                  \
-       stx             %g7, [%g1];                                     \
-       add             %g3, (1 << 3), %g3;                             \
-       cmp             %g3, (8 << 3);                                  \
-       bl,pt           %xcc, 22b;                                      \
-        add            %g1, 0x8, %g1;                                  \
-       ba,pt           %xcc, 30f;                                      \
-        add            %g1, 0x30, %g1;                                 \
-23:    sethi           %hi(1 << 14), %g7;                              \
-       add             %g2, %g7, %g2;                                  \
-       srlx            %g2, 14, %g7;                                   \
-       cmp             %g7, 4;                                         \
-       bl,pt           %xcc, 21b;                                      \
-        nop;                                                           \
-       add             %g1, 0x70, %g1;                                 \
-30:    /* %g1 now points to E-cache logging area */                    \
-       andn            %g5, (32 - 1), %g2;     /* E-cache subblock */  \
-       stx             %g2, [%g1 + 0x20];                              \
-       ldxa            [%g2] ASI_EC_TAG_DATA, %g7;                     \
-       stx             %g7, [%g1 + 0x28];                              \
-       ldxa            [%g2] ASI_EC_R, %g0;                            \
-       clr             %g3;                                            \
-31:    ldxa            [%g3] ASI_EC_DATA, %g7;                         \
-       stx             %g7, [%g1 + %g3];                               \
-       add             %g3, 0x8, %g3;                                  \
-       cmp             %g3, 0x20;                                      \
-       bl,pt           %xcc, 31b;                                      \
-        nop;                                                           \
-80:    /* DONE */
-
        /* These get patched into the trap table at boot time
         * once we know we have a cheetah processor.
         */
@@ -1140,13 +828,14 @@ cheetah_plus_dcpe_trap_vector:
        nop
 
 do_cheetah_plus_data_parity:
-       ba,pt           %xcc, etrap
+       rdpr            %pil, %g2
+       wrpr            %g0, 15, %pil
+       ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
        mov             0x0, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
-       ba,pt           %xcc, rtrap
-        clr            %l6
+       ba,a,pt         %xcc, rtrap_irq
 
 cheetah_plus_dcpe_trap_vector_tl1:
        membar          #Sync
@@ -1170,13 +859,14 @@ cheetah_plus_icpe_trap_vector:
        nop
 
 do_cheetah_plus_insn_parity:
-       ba,pt           %xcc, etrap
+       rdpr            %pil, %g2
+       wrpr            %g0, 15, %pil
+       ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
        mov             0x1, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
-       ba,pt           %xcc, rtrap
-        clr            %l6
+       ba,a,pt         %xcc, rtrap_irq
 
 cheetah_plus_icpe_trap_vector_tl1:
        membar          #Sync
@@ -1209,6 +899,10 @@ do_dcpe_tl1:
         nop
        wrpr            %g1, %tl                ! Restore original trap level
 do_dcpe_tl1_nonfatal:  /* Ok we may use interrupt globals safely. */
+       sethi           %hi(dcache_parity_tl1_occurred), %g2
+       lduw            [%g2 + %lo(dcache_parity_tl1_occurred)], %g1
+       add             %g1, 1, %g1
+       stw             %g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
        /* Reset D-cache parity */
        sethi           %hi(1 << 16), %g1       ! D-cache size
        mov             (1 << 5), %g2           ! D-cache line size
@@ -1255,6 +949,10 @@ do_icpe_tl1:
         nop
        wrpr            %g1, %tl                ! Restore original trap level
 do_icpe_tl1_nonfatal:  /* Ok we may use interrupt globals safely. */
+       sethi           %hi(icache_parity_tl1_occurred), %g2
+       lduw            [%g2 + %lo(icache_parity_tl1_occurred)], %g1
+       add             %g1, 1, %g1
+       stw             %g1, [%g2 + %lo(icache_parity_tl1_occurred)]
        /* Flush I-cache */
        sethi           %hi(1 << 15), %g1       ! I-cache size
        mov             (1 << 5), %g2           ! I-cache line size
@@ -1296,6 +994,170 @@ dcpe_icpe_tl1_common:
        membar          #Sync
        retry
 
+       /* Capture I/D/E-cache state into per-cpu error scoreboard.
+        *
+        * %g1:         (TL>=0) ? 1 : 0
+        * %g2:         scratch
+        * %g3:         scratch
+        * %g4:         AFSR
+        * %g5:         AFAR
+        * %g6:         current thread ptr
+        * %g7:         scratch
+        */
+__cheetah_log_error:
+       /* Put "TL1" software bit into AFSR. */
+       and             %g1, 0x1, %g1
+       sllx            %g1, 63, %g2
+       or              %g4, %g2, %g4
+
+       /* Get log entry pointer for this cpu at this trap level. */
+       BRANCH_IF_JALAPENO(g2,g3,50f)
+       ldxa            [%g0] ASI_SAFARI_CONFIG, %g2
+       srlx            %g2, 17, %g2
+       ba,pt           %xcc, 60f
+        and            %g2, 0x3ff, %g2
+
+50:    ldxa            [%g0] ASI_JBUS_CONFIG, %g2
+       srlx            %g2, 17, %g2
+       and             %g2, 0x1f, %g2
+
+60:    sllx            %g2, 9, %g2
+       sethi           %hi(cheetah_error_log), %g3
+       ldx             [%g3 + %lo(cheetah_error_log)], %g3
+       brz,pn          %g3, 80f
+        nop
+
+       add             %g3, %g2, %g3
+       sllx            %g1, 8, %g1
+       add             %g3, %g1, %g1
+
+       /* %g1 holds pointer to the top of the logging scoreboard */
+       ldx             [%g1 + 0x0], %g7
+       cmp             %g7, -1
+       bne,pn          %xcc, 80f
+        nop
+
+       stx             %g4, [%g1 + 0x0]
+       stx             %g5, [%g1 + 0x8]
+       add             %g1, 0x10, %g1
+
+       /* %g1 now points to D-cache logging area */
+       set             0x3ff8, %g2     /* DC_addr mask         */
+       and             %g5, %g2, %g2   /* DC_addr bits of AFAR */
+       srlx            %g5, 12, %g3
+       or              %g3, 1, %g3     /* PHYS tag + valid     */
+
+10:    ldxa            [%g2] ASI_DCACHE_TAG, %g7
+       cmp             %g3, %g7        /* TAG match?           */
+       bne,pt          %xcc, 13f
+        nop
+
+       /* Yep, what we want, capture state. */
+       stx             %g2, [%g1 + 0x20]
+       stx             %g7, [%g1 + 0x28]
+
+       /* A membar Sync is required before and after utag access. */
+       membar          #Sync
+       ldxa            [%g2] ASI_DCACHE_UTAG, %g7
+       membar          #Sync
+       stx             %g7, [%g1 + 0x30]
+       ldxa            [%g2] ASI_DCACHE_SNOOP_TAG, %g7
+       stx             %g7, [%g1 + 0x38]
+       clr             %g3
+
+12:    ldxa            [%g2 + %g3] ASI_DCACHE_DATA, %g7
+       stx             %g7, [%g1]
+       add             %g3, (1 << 5), %g3
+       cmp             %g3, (4 << 5)
+       bl,pt           %xcc, 12b
+        add            %g1, 0x8, %g1
+
+       ba,pt           %xcc, 20f
+        add            %g1, 0x20, %g1
+
+13:    sethi           %hi(1 << 14), %g7
+       add             %g2, %g7, %g2
+       srlx            %g2, 14, %g7
+       cmp             %g7, 4
+       bl,pt           %xcc, 10b
+        nop
+
+       add             %g1, 0x40, %g1
+
+       /* %g1 now points to I-cache logging area */
+20:    set             0x1fe0, %g2     /* IC_addr mask         */
+       and             %g5, %g2, %g2   /* IC_addr bits of AFAR */
+       sllx            %g2, 1, %g2     /* IC_addr[13:6]==VA[12:5] */
+       srlx            %g5, (13 - 8), %g3 /* Make PTAG */
+       andn            %g3, 0xff, %g3  /* Mask off undefined bits */
+
+21:    ldxa            [%g2] ASI_IC_TAG, %g7
+       andn            %g7, 0xff, %g7
+       cmp             %g3, %g7
+       bne,pt          %xcc, 23f
+        nop
+
+       /* Yep, what we want, capture state. */
+       stx             %g2, [%g1 + 0x40]
+       stx             %g7, [%g1 + 0x48]
+       add             %g2, (1 << 3), %g2
+       ldxa            [%g2] ASI_IC_TAG, %g7
+       add             %g2, (1 << 3), %g2
+       stx             %g7, [%g1 + 0x50]
+       ldxa            [%g2] ASI_IC_TAG, %g7
+       add             %g2, (1 << 3), %g2
+       stx             %g7, [%g1 + 0x60]
+       ldxa            [%g2] ASI_IC_TAG, %g7
+       stx             %g7, [%g1 + 0x68]
+       sub             %g2, (3 << 3), %g2
+       ldxa            [%g2] ASI_IC_STAG, %g7
+       stx             %g7, [%g1 + 0x58]
+       clr             %g3
+       srlx            %g2, 2, %g2
+
+22:    ldxa            [%g2 + %g3] ASI_IC_INSTR, %g7
+       stx             %g7, [%g1]
+       add             %g3, (1 << 3), %g3
+       cmp             %g3, (8 << 3)
+       bl,pt           %xcc, 22b
+        add            %g1, 0x8, %g1
+
+       ba,pt           %xcc, 30f
+        add            %g1, 0x30, %g1
+
+23:    sethi           %hi(1 << 14), %g7
+       add             %g2, %g7, %g2
+       srlx            %g2, 14, %g7
+       cmp             %g7, 4
+       bl,pt           %xcc, 21b
+        nop
+
+       add             %g1, 0x70, %g1
+
+       /* %g1 now points to E-cache logging area */
+30:    andn            %g5, (32 - 1), %g2
+       stx             %g2, [%g1 + 0x20]
+       ldxa            [%g2] ASI_EC_TAG_DATA, %g7
+       stx             %g7, [%g1 + 0x28]
+       ldxa            [%g2] ASI_EC_R, %g0
+       clr             %g3
+
+31:    ldxa            [%g3] ASI_EC_DATA, %g7
+       stx             %g7, [%g1 + %g3]
+       add             %g3, 0x8, %g3
+       cmp             %g3, 0x20
+
+       bl,pt           %xcc, 31b
+        nop
+80:
+       rdpr            %tt, %g2
+       cmp             %g2, 0x70
+       be              c_fast_ecc
+        cmp            %g2, 0x63
+       be              c_cee
+        nop
+       ba,pt           %xcc, c_deferred
+
        /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
         * in the trap table.  That code has done a memory barrier
         * and has disabled both the I-cache and D-cache in the DCU
@@ -1321,8 +1183,10 @@ cheetah_fast_ecc:
        stxa            %g4, [%g0] ASI_AFSR
        membar          #Sync
 
-       CHEETAH_LOG_ERROR
+       ba,pt           %xcc, __cheetah_log_error
+        nop
 
+c_fast_ecc:
        rdpr            %pil, %g2
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
@@ -1347,8 +1211,10 @@ cheetah_cee:
        stxa            %g4, [%g0] ASI_AFSR
        membar          #Sync
 
-       CHEETAH_LOG_ERROR
+       ba,pt           %xcc, __cheetah_log_error
+        nop
 
+c_cee:
        rdpr            %pil, %g2
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
@@ -1373,8 +1239,10 @@ cheetah_deferred_trap:
        stxa            %g4, [%g0] ASI_AFSR
        membar          #Sync
 
-       CHEETAH_LOG_ERROR
+       ba,pt           %xcc, __cheetah_log_error
+        nop
 
+c_deferred:
        rdpr            %pil, %g2
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
This page took 0.039963 seconds and 5 git commands to generate.