f384565212fe071ab73f0dfda2128e0f4d831fe6
[linux-2.6.git] / include / asm-sparc64 / tsb.h
1 #ifndef _SPARC64_TSB_H
2 #define _SPARC64_TSB_H
3
4 /* The sparc64 TSB is similar to the powerpc hashtables.  It's a
5  * power-of-2 sized table of TAG/PTE pairs.  The cpu precomputes
6  * pointers into this table for 8K and 64K page sizes, and also a
7  * comparison TAG based upon the virtual address and context which
8  * faults.
9  *
10  * TLB miss trap handler software does the actual lookup via something
11  * of the form:
12  *
13  *      ldxa            [%g0] ASI_{D,I}MMU_TSB_8KB_PTR, %g1
14  *      ldxa            [%g0] ASI_{D,I}MMU, %g6
15  *      ldda            [%g1] ASI_NUCLEUS_QUAD_LDD, %g4
16  *      cmp             %g4, %g6
17  *      bne,pn  %xcc, tsb_miss_{d,i}tlb
18  *       mov            FAULT_CODE_{D,I}TLB, %g3
19  *      stxa            %g5, [%g0] ASI_{D,I}TLB_DATA_IN
20  *      retry
21  *
22  *
23  * Each 16-byte slot of the TSB is the 8-byte tag and then the 8-byte
24  * PTE.  The TAG is of the same layout as the TLB TAG TARGET mmu
25  * register which is:
26  *
27  * -------------------------------------------------
28  * |  -  |  CONTEXT |  -  |    VADDR bits 63:22    |
29  * -------------------------------------------------
30  *  63 61 60      48 47 42 41                     0
31  *
32  * Like the powerpc hashtables we need to use locking in order to
33  * synchronize while we update the entries.  PTE updates need locking
34  * as well.
35  *
36  * We need to carefully choose a lock bits for the TSB entry.  We
37  * choose to use bit 47 in the tag.  Also, since we never map anything
38  * at page zero in context zero, we use zero as an invalid tag entry.
39  * When the lock bit is set, this forces a tag comparison failure.
40  */
41
42 #define TSB_TAG_LOCK_BIT        47
43 #define TSB_TAG_LOCK_HIGH       (1 << (TSB_TAG_LOCK_BIT - 32))
44
45 #define TSB_MEMBAR      membar  #StoreStore
46
47 #define TSB_LOCK_TAG(TSB, REG1, REG2)   \
48 99:     lduwa   [TSB] ASI_N, REG1;      \
49         sethi   %hi(TSB_TAG_LOCK_HIGH), REG2;\
50         andcc   REG1, REG2, %g0;        \
51         bne,pn  %icc, 99b;              \
52          nop;                           \
53         casa    [TSB] ASI_N, REG1, REG2;\
54         cmp     REG1, REG2;             \
55         bne,pn  %icc, 99b;              \
56          nop;                           \
57         TSB_MEMBAR
58
59 #define TSB_WRITE(TSB, TTE, TAG)           \
60         stx             TTE, [TSB + 0x08]; \
61         TSB_MEMBAR;                        \
62         stx             TAG, [TSB + 0x00];
63
64         /* Do a kernel page table walk.  Leaves physical PTE pointer in
65          * REG1.  Jumps to FAIL_LABEL on early page table walk termination.
66          * VADDR will not be clobbered, but REG2 will.
67          */
68 #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL)        \
69         sethi           %hi(swapper_pg_dir), REG1; \
70         or              REG1, %lo(swapper_pg_dir), REG1; \
71         sllx            VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
72         srlx            REG2, 64 - PAGE_SHIFT, REG2; \
73         andn            REG2, 0x3, REG2; \
74         lduw            [REG1 + REG2], REG1; \
75         brz,pn          REG1, FAIL_LABEL; \
76          sllx           VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
77         srlx            REG2, 64 - PAGE_SHIFT, REG2; \
78         sllx            REG1, 11, REG1; \
79         andn            REG2, 0x3, REG2; \
80         lduwa           [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
81         brz,pn          REG1, FAIL_LABEL; \
82          sllx           VADDR, 64 - PMD_SHIFT, REG2; \
83         srlx            REG2, 64 - PAGE_SHIFT, REG2; \
84         sllx            REG1, 11, REG1; \
85         andn            REG2, 0x7, REG2; \
86         add             REG1, REG2, REG1;
87
88         /* Do a user page table walk in MMU globals.  Leaves physical PTE
89          * pointer in REG1.  Jumps to FAIL_LABEL on early page table walk
90          * termination.  Physical base of page tables is in PHYS_PGD which
91          * will not be modified.
92          *
93          * VADDR will not be clobbered, but REG1 and REG2 will.
94          */
95 #define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL)  \
96         sllx            VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
97         srlx            REG2, 64 - PAGE_SHIFT, REG2; \
98         andn            REG2, 0x3, REG2; \
99         lduwa           [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
100         brz,pn          REG1, FAIL_LABEL; \
101          sllx           VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
102         srlx            REG2, 64 - PAGE_SHIFT, REG2; \
103         sllx            REG1, 11, REG1; \
104         andn            REG2, 0x3, REG2; \
105         lduwa           [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
106         brz,pn          REG1, FAIL_LABEL; \
107          sllx           VADDR, 64 - PMD_SHIFT, REG2; \
108         srlx            REG2, 64 - PAGE_SHIFT, REG2; \
109         sllx            REG1, 11, REG1; \
110         andn            REG2, 0x7, REG2; \
111         add             REG1, REG2, REG1;
112
113 /* Lookup a OBP mapping on VADDR in the prom_trans[] table at TL>0.
114  * If no entry is found, FAIL_LABEL will be branched to.  On success
115  * the resulting PTE value will be left in REG1.  VADDR is preserved
116  * by this routine.
117  */
118 #define OBP_TRANS_LOOKUP(VADDR, REG1, REG2, REG3, FAIL_LABEL) \
119         sethi           %hi(prom_trans), REG1; \
120         or              REG1, %lo(prom_trans), REG1; \
121 97:     ldx             [REG1 + 0x00], REG2; \
122         brz,pn          REG2, FAIL_LABEL; \
123          nop; \
124         ldx             [REG1 + 0x08], REG3; \
125         add             REG2, REG3, REG3; \
126         cmp             REG2, VADDR; \
127         bgu,pt          %xcc, 98f; \
128          cmp            VADDR, REG3; \
129         bgeu,pt         %xcc, 98f; \
130          ldx            [REG1 + 0x10], REG3; \
131         sub             VADDR, REG2, REG2; \
132         ba,pt           %xcc, 99f; \
133          add            REG3, REG2, REG1; \
134 98:     ba,pt           %xcc, 97b; \
135          add            REG1, (3 * 8), REG1; \
136 99:
137
138         /* We use a 32K TSB for the whole kernel, this allows to
139          * handle about 16MB of modules and vmalloc mappings without
140          * incurring many hash conflicts.
141          */
142 #define KERNEL_TSB_SIZE_BYTES   (32 * 1024)
143 #define KERNEL_TSB_NENTRIES     \
144         (KERNEL_TSB_SIZE_BYTES / 16)
145
146         /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
147          * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
148          * and the found TTE will be left in REG1.  REG3 and REG4 must
149          * be an even/odd pair of registers.
150          *
151          * VADDR and TAG will be preserved and not clobbered by this macro.
152          */
153 #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
154         sethi           %hi(swapper_tsb), REG1; \
155         or              REG1, %lo(swapper_tsb), REG1; \
156         srlx            VADDR, PAGE_SHIFT, REG2; \
157         and             REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
158         sllx            REG2, 4, REG2; \
159         add             REG1, REG2, REG2; \
160         ldda            [REG2] ASI_NUCLEUS_QUAD_LDD, REG3; \
161         cmp             REG3, TAG; \
162         be,a,pt         %xcc, OK_LABEL; \
163          mov            REG4, REG1;
164
165 #endif /* !(_SPARC64_TSB_H) */