vserver 2.0 rc7
[linux-2.6.git] / arch / sparc64 / kernel / entry.S
index c4b705d..a47f2d0 100644 (file)
  * 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).
+ * 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                    ! Load 0xf0000000
-       cmp             %g4, %g5                        ! Is addr >= LOW_OBP_ADDRESS?
+       sllx            %g5, 28, %g5
+
+       /* Is addr >= LOW_OBP_ADDRESS?  */
+       cmp             %g4, %g5
        blu,pn          %xcc, sparc64_vpte_patchme1
         mov            0x1, %g5
-       sllx            %g5, 32, %g5                    ! Load 0x100000000
-       cmp             %g4, %g5                        ! Is addr < HI_OBP_ADDRESS?
+
+       /* 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                     ! This has to be patched
+       sethi           %hi(0), %g5
 sparc64_vpte_patchme2:
-       or              %g5, %lo(0), %g5                ! This is patched too
-       ba,pt           %xcc, sparc64_kpte_continue     ! Part of dtlb_backend
-        add            %g1, %g1, %g1                   ! Finish PMD offset adjustment
+       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:
-       mov             TLB_SFSR, %g1                   ! Restore %g1 value
-       stxa            %g4, [%g1 + %g1] ASI_DMMU       ! Restore previous TAG_ACCESS
-       done                                            ! Slick trick
+       /* 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
-       .globl          obp_daddr_patch
-
 obp_iaddr_patch:
-       sethi           %hi(0), %g5                     ! This and following is patched
-       or              %g5, %lo(0), %g5                ! g5 now holds obp pmd base physaddr
-       wrpr            %g0, 1, %tl                     ! Behave as if we are at TL0
-       rdpr            %tpc, %g4                       ! Find original faulting iaddr
-       srlx            %g4, 13, %g4                    ! Throw out context bits
-       sllx            %g4, 13, %g4                    ! g4 has vpn + ctx0 now
-       mov             TLB_SFSR, %g1                   ! Restore %g1 value
-       stxa            %g4, [%g1 + %g1] ASI_IMMU       ! Restore previous TAG_ACCESS
-       srlx            %g4, 23, %g6                    ! Find pmd number
-       and             %g6, 0x7ff, %g6                 ! Find pmd number
-       sllx            %g6, 2, %g6                     ! Find pmd offset
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pmd, ie pagetable physaddr
-       brz,pn          %g5, longpath                   ! Kill the PROM ? :-)
-        sllx           %g5, 11, %g5                    ! Shift into place
-       srlx            %g4, 13, %g6                    ! find pte number in pagetable
-       and             %g6, 0x3ff, %g6                 ! find pte number in pagetable
-       sllx            %g6, 3, %g6                     ! find pte offset in pagetable
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pte
-       brgez,pn        %g5, longpath                   ! Kill the PROM ? :-)
+       /* 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
-       stxa            %g5, [%g0] ASI_ITLB_DATA_IN     ! put into tlb
-       retry                                           ! go back to original fault
 
+       /* TLB load and return from trap.  */
+       stxa            %g5, [%g0] ASI_ITLB_DATA_IN
+       retry
+
+       .globl          obp_daddr_patch
 obp_daddr_patch:
-       sethi           %hi(0), %g5                     ! This and following is patched
-       or              %g5, %lo(0), %g5                ! g5 now holds obp pmd base physaddr
-       srlx            %g4, 23, %g6                    ! Find pmd number
-       and             %g6, 0x7ff, %g6                 ! Find pmd number
-       sllx            %g6, 2, %g6                     ! Find pmd offset
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pmd, ie pagetable physaddr
+       /* 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                    ! Shift into place
-       srlx            %g4, 13, %g6                    ! find pte number in pagetable
-       and             %g6, 0x3ff, %g6                 ! find pte number in pagetable
-       sllx            %g6, 3, %g6                     ! find pte offset in pagetable
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pte
+        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
-       stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! put into tlb
+
+       /* 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.
+ * 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                    ! Load 0xf0000000
-       cmp             %g4, %g5                        ! Is addr >= LOW_OBP_ADDRESS?
+       sllx            %g5, 28, %g5
+
+       /* Is addr >= LOW_OBP_ADDRESS?  */
+       cmp             %g4, %g5
        blu,pn          %xcc, vmalloc_addr
         mov            0x1, %g5
-       sllx            %g5, 32, %g5                    ! Load 0x100000000
-       cmp             %g4, %g5                        ! Is addr < HI_OBP_ADDRESS?
+
+       /* 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:                                          ! vmalloc addr accessed
-       ldxa            [%g3 + %g6] ASI_N, %g5          ! Yep, load k-vpte
-       brgez,pn        %g5, longpath                   ! Valid, load into TLB
+
+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
 
@@ -199,9 +252,11 @@ do_fpdis:
        faddd           %f0, %f2, %f4
        fmuld           %f0, %f2, %f6
        ldxa            [%g3] ASI_DMMU, %g5
-       add             %g6, TI_FPREGS + 0xc0, %g2
-       stxa            %g0, [%g3] ASI_DMMU
+cplus_fptrap_insn_1:
+       sethi           %hi(0), %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-(
@@ -225,7 +280,9 @@ do_fpdis:
        fzero           %f34
        ldxa            [%g3] ASI_DMMU, %g5
        add             %g6, TI_FPREGS, %g1
-       stxa            %g0, [%g3] ASI_DMMU
+cplus_fptrap_insn_2:
+       sethi           %hi(0), %g2
+       stxa            %g2, [%g3] ASI_DMMU
        membar          #Sync
        add             %g6, TI_FPREGS + 0x40, %g2
        faddd           %f32, %f34, %f36
@@ -249,9 +306,11 @@ do_fpdis:
 3:     mov             SECONDARY_CONTEXT, %g3
        add             %g6, TI_FPREGS, %g1
        ldxa            [%g3] ASI_DMMU, %g5
-       mov             0x40, %g2
-       stxa            %g0, [%g3] ASI_DMMU
+cplus_fptrap_insn_3:
+       sethi           %hi(0), %g2
+       stxa            %g2, [%g3] ASI_DMMU
        membar          #Sync
+       mov             0x40, %g2
        ldda            [%g1] ASI_BLK_S, %f0            ! grrr, where is ASI_BLK_NUCLEUS 8-(
        ldda            [%g1 + %g2] ASI_BLK_S, %f16
        add             %g1, 0x80, %g1
@@ -412,10 +471,12 @@ do_fptrap_after_fsr:
        rd              %gsr, %g3
        stx             %g3, [%g6 + TI_GSR]
        mov             SECONDARY_CONTEXT, %g3
-       add             %g6, TI_FPREGS, %g2
        ldxa            [%g3] ASI_DMMU, %g5
-       stxa            %g0, [%g3] ASI_DMMU
+cplus_fptrap_insn_4:
+       sethi           %hi(0), %g2
+       stxa            %g2, [%g3] ASI_DMMU
        membar          #Sync
+       add             %g6, TI_FPREGS, %g2
        andcc           %g1, FPRS_DL, %g0
        be,pn           %icc, 4f
         mov            0x40, %g3
@@ -433,6 +494,33 @@ do_fptrap_after_fsr:
        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
@@ -1642,7 +1730,7 @@ ret_from_syscall:
                andn            %o7, _TIF_NEWCHILD, %l0
                stx             %l0, [%g6 + TI_FLAGS]
                call            schedule_tail
-                mov            %g5, %o0
+                mov            %g7, %o0
                andcc           %l0, _TIF_PERFCTR, %g0
                be,pt           %icc, 1f
                 nop