Import 2.3.18pre1
[davej-history.git] / arch / sparc64 / kernel / dtlb_backend.S
blob9fe613a5182454ddfe963ec39a962c2c2b9fab95
1 /* $Id: dtlb_backend.S,v 1.7 1998/12/16 04:33: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@dm.cobaltmicro.com)
6  * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
7  */
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_P | _PAGE_W)
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, dtlb_prot, and itlb_base.  But this only
20  *    happens for non-nucleus contexts.  Nucleus VPTE's cannot work because
21  *    of how OBP uses the same part of the address space in ctx 0.
22  */
24 /* TLB1 ** ICACHE line 1: tl1 DTLB and quick VPTE miss  */
25         ldxa            [%g1 + %g1] ASI_DMMU, %g4       ! Get TAG_ACCESS
26         add             %g3, %g3, %g5                   ! Compute VPTE base
27         cmp             %g4, %g5                        ! VPTE miss?
28         blu,pn          %xcc, .-0x4004                  ! Fall to tl0 miss
29          andcc          %g4, TAG_CONTEXT_BITS, %g5      ! From Nucleus? (for tl0 miss)
30         sllx            %g6, VPTE_SHIFT, %g4            ! Position TAG_ACCESS
31         or              %g4, %g5, %g4                   ! Prepare TAG_ACCESS
32         mov             TSB_REG, %g1                    ! Grab TSB reg
34 /* TLB1 ** ICACHE line 2: Quick VPTE miss               */
35         ldxa            [%g1] ASI_DMMU, %g5             ! Doing PGD caching?
36         srlx            %g6, (PMD_SHIFT - 1), %g1       ! Position PMD offset
37         be,pn           %xcc, sparc64_vpte_nucleus      ! Is it from Nucleus?
38          and            %g1, 0xffe, %g1                 ! Mask PMD offset bits
39         brnz,pt         %g5, sparc64_vpte_continue      ! Yep, go like smoke
40          add            %g1, %g1, %g1                   ! Position PMD offset some more
41         srlx            %g6, (PGD_SHIFT - 2), %g5       ! Position PGD offset
42         and             %g5, 0xffc, %g5                 ! Mask PGD offset
44 /* TLB1 ** ICACHE line 3: Quick VPTE miss               */
45         lduwa           [%g7 + %g5] ASI_PHYS_USE_EC, %g5! Load PGD
46         brz,pn          %g5, vpte_noent                 ! Valid?
47 sparc64_kpte_continue:
48          sllx           %g5, 11, %g5                    ! Shift into place
49 sparc64_vpte_continue:
50         lduwa           [%g5 + %g1] ASI_PHYS_USE_EC, %g5! Load PMD
51         sllx            %g5, 11, %g5                    ! Shift into place
52         brz,pn          %g5, vpte_noent                 ! Valid?
53          sllx           %g2, 62, %g1                    ! Put _PAGE_VALID into %g1
54         or              %g5, VPTE_BITS, %g5             ! Prepare VPTE data
56 /* TLB1 ** ICACHE line 4: Quick VPTE miss               */
57         or              %g5, %g1, %g5                   ! ...
58         mov             TLB_SFSR, %g1                   ! Restore %g1 value
59         stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Load VPTE into TLB
60         stxa            %g4, [%g1 + %g1] ASI_DMMU       ! Restore previous TAG_ACCESS
61         retry                                           ! Load PTE once again
62 vpte_noent:
63         mov             TLB_SFSR, %g1                   ! Restore %g1 value
64         stxa            %g4, [%g1 + %g1] ASI_DMMU       ! Restore previous TAG_ACCESS
65         done                                            ! Slick trick
67 #undef TAG_CONTEXT_BITS
68 #undef VPTE_SHIFT
69 #undef PMD_SHIFT
70 #undef PGD_SHIFT
71 #undef VPTE_BITS