v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / arch / sparc64 / kernel / dtlb_backend.S
1 /* $Id: dtlb_backend.S,v 1.11 2001/08/08 08:01:28 davem Exp $
2  * dtlb_backend.S: Back end to DTLB miss replacement strategy.
3  *                 This is included directly into the trap table.
4  *
5  * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
6  * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
7  */
8
9 #define TAG_CONTEXT_BITS        0x3ff
10 #define VPTE_SHIFT              (PAGE_SHIFT - 3)
11 #define PMD_SHIFT               (23 - PAGE_SHIFT + 3)
12 #define PGD_SHIFT               (34 - PAGE_SHIFT + 3)
13 #define VPTE_BITS               (_PAGE_CP | _PAGE_CV | _PAGE_P)
14
15 /* Ways we can get here:
16  *
17  * 1) Nucleus loads and stores to/from PA-->VA direct mappings at tl>1.
18  * 2) Nucleus loads and stores to/from user/kernel window save areas.
19  * 3) VPTE misses from dtlb_base and itlb_base.
20  */
21
22 /* TLB1 ** ICACHE line 1: tl1 DTLB and quick VPTE miss  */
23         ldxa            [%g1 + %g1] ASI_DMMU, %g4       ! Get TAG_ACCESS
24         add             %g3, %g3, %g5                   ! Compute VPTE base
25         cmp             %g4, %g5                        ! VPTE miss?
26         blu,pn          %xcc, .-0x4004                  ! Fall to tl0 miss
27          andcc          %g4, TAG_CONTEXT_BITS, %g5      ! From Nucleus? (for tl0 miss)
28         sllx            %g6, VPTE_SHIFT, %g4            ! Position TAG_ACCESS
29         or              %g4, %g5, %g4                   ! Prepare TAG_ACCESS
30         mov             TSB_REG, %g1                    ! Grab TSB reg
31
32 /* TLB1 ** ICACHE line 2: Quick VPTE miss               */
33         ldxa            [%g1] ASI_DMMU, %g5             ! Doing PGD caching?
34         srlx            %g6, (PMD_SHIFT - 1), %g1       ! Position PMD offset
35         be,pn           %xcc, sparc64_vpte_nucleus      ! Is it from Nucleus?
36          and            %g1, 0xffe, %g1                 ! Mask PMD offset bits
37         brnz,pt         %g5, sparc64_vpte_continue      ! Yep, go like smoke
38          add            %g1, %g1, %g1                   ! Position PMD offset some more
39         srlx            %g6, (PGD_SHIFT - 2), %g5       ! Position PGD offset
40         and             %g5, 0xffc, %g5                 ! Mask PGD offset
41
42 /* TLB1 ** ICACHE line 3: Quick VPTE miss               */
43         lduwa           [%g7 + %g5] ASI_PHYS_USE_EC, %g5! Load PGD
44         brz,pn          %g5, vpte_noent                 ! Valid?
45 sparc64_kpte_continue:
46          sllx           %g5, 11, %g5                    ! Shift into place
47 sparc64_vpte_continue:
48         lduwa           [%g5 + %g1] ASI_PHYS_USE_EC, %g5! Load PMD
49         sllx            %g5, 11, %g5                    ! Shift into place
50         brz,pn          %g5, vpte_noent                 ! Valid?
51          sllx           %g2, 62, %g1                    ! Put _PAGE_VALID into %g1
52         or              %g5, VPTE_BITS, %g5             ! Prepare VPTE data
53
54 /* TLB1 ** ICACHE line 4: Quick VPTE miss               */
55         or              %g5, %g1, %g5                   ! ...
56         mov             TLB_SFSR, %g1                   ! Restore %g1 value
57         stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Load VPTE into TLB
58         stxa            %g4, [%g1 + %g1] ASI_DMMU       ! Restore previous TAG_ACCESS
59         retry                                           ! Load PTE once again
60 vpte_noent:
61         mov             TLB_SFSR, %g1                   ! Restore %g1 value
62         stxa            %g4, [%g1 + %g1] ASI_DMMU       ! Restore previous TAG_ACCESS
63         done                                            ! Slick trick
64
65 #undef TAG_CONTEXT_BITS
66 #undef VPTE_SHIFT
67 #undef PMD_SHIFT
68 #undef PGD_SHIFT
69 #undef VPTE_BITS