[PATCH] missing helper - task_stack_page()
[linux-2.6] / include / asm-sparc64 / spitfire.h
1 /* $Id: spitfire.h,v 1.18 2001/11/29 16:42:10 kanoj Exp $
2  * spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
3  *
4  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5  */
6
7 #ifndef _SPARC64_SPITFIRE_H
8 #define _SPARC64_SPITFIRE_H
9
10 #include <asm/asi.h>
11
12 /* The following register addresses are accessible via ASI_DMMU
13  * and ASI_IMMU, that is there is a distinct and unique copy of
14  * each these registers for each TLB.
15  */
16 #define TSB_TAG_TARGET          0x0000000000000000 /* All chips                         */
17 #define TLB_SFSR                0x0000000000000018 /* All chips                         */
18 #define TSB_REG                 0x0000000000000028 /* All chips                         */
19 #define TLB_TAG_ACCESS          0x0000000000000030 /* All chips                         */
20 #define VIRT_WATCHPOINT         0x0000000000000038 /* All chips                         */
21 #define PHYS_WATCHPOINT         0x0000000000000040 /* All chips                         */
22 #define TSB_EXTENSION_P         0x0000000000000048 /* Ultra-III and later               */
23 #define TSB_EXTENSION_S         0x0000000000000050 /* Ultra-III and later, D-TLB only   */
24 #define TSB_EXTENSION_N         0x0000000000000058 /* Ultra-III and later               */
25 #define TLB_TAG_ACCESS_EXT      0x0000000000000060 /* Ultra-III+ and later              */
26
27 /* These registers only exist as one entity, and are accessed
28  * via ASI_DMMU only.
29  */
30 #define PRIMARY_CONTEXT         0x0000000000000008
31 #define SECONDARY_CONTEXT       0x0000000000000010
32 #define DMMU_SFAR               0x0000000000000020
33 #define VIRT_WATCHPOINT         0x0000000000000038
34 #define PHYS_WATCHPOINT         0x0000000000000040
35
36 #define SPITFIRE_HIGHEST_LOCKED_TLBENT  (64 - 1)
37 #define CHEETAH_HIGHEST_LOCKED_TLBENT   (16 - 1)
38
39 #define L1DCACHE_SIZE           0x4000
40
41 #ifndef __ASSEMBLY__
42
43 enum ultra_tlb_layout {
44         spitfire = 0,
45         cheetah = 1,
46         cheetah_plus = 2,
47 };
48
49 extern enum ultra_tlb_layout tlb_type;
50
51 extern int cheetah_pcache_forced_on;
52 extern void cheetah_enable_pcache(void);
53
54 #define sparc64_highest_locked_tlbent() \
55         (tlb_type == spitfire ? \
56          SPITFIRE_HIGHEST_LOCKED_TLBENT : \
57          CHEETAH_HIGHEST_LOCKED_TLBENT)
58
59 /* The data cache is write through, so this just invalidates the
60  * specified line.
61  */
62 static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
63 {
64         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
65                              "membar    #Sync"
66                              : /* No outputs */
67                              : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
68 }
69
70 /* The instruction cache lines are flushed with this, but note that
71  * this does not flush the pipeline.  It is possible for a line to
72  * get flushed but stale instructions to still be in the pipeline,
73  * a flush instruction (to any address) is sufficient to handle
74  * this issue after the line is invalidated.
75  */
76 static __inline__ void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
77 {
78         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
79                              "membar    #Sync"
80                              : /* No outputs */
81                              : "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
82 }
83
84 static __inline__ unsigned long spitfire_get_dtlb_data(int entry)
85 {
86         unsigned long data;
87
88         __asm__ __volatile__("ldxa      [%1] %2, %0"
89                              : "=r" (data)
90                              : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
91
92         /* Clear TTE diag bits. */
93         data &= ~0x0003fe0000000000UL;
94
95         return data;
96 }
97
98 static __inline__ unsigned long spitfire_get_dtlb_tag(int entry)
99 {
100         unsigned long tag;
101
102         __asm__ __volatile__("ldxa      [%1] %2, %0"
103                              : "=r" (tag)
104                              : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
105         return tag;
106 }
107
108 static __inline__ void spitfire_put_dtlb_data(int entry, unsigned long data)
109 {
110         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
111                              "membar    #Sync"
112                              : /* No outputs */
113                              : "r" (data), "r" (entry << 3),
114                                "i" (ASI_DTLB_DATA_ACCESS));
115 }
116
117 static __inline__ unsigned long spitfire_get_itlb_data(int entry)
118 {
119         unsigned long data;
120
121         __asm__ __volatile__("ldxa      [%1] %2, %0"
122                              : "=r" (data)
123                              : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
124
125         /* Clear TTE diag bits. */
126         data &= ~0x0003fe0000000000UL;
127
128         return data;
129 }
130
131 static __inline__ unsigned long spitfire_get_itlb_tag(int entry)
132 {
133         unsigned long tag;
134
135         __asm__ __volatile__("ldxa      [%1] %2, %0"
136                              : "=r" (tag)
137                              : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
138         return tag;
139 }
140
141 static __inline__ void spitfire_put_itlb_data(int entry, unsigned long data)
142 {
143         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
144                              "membar    #Sync"
145                              : /* No outputs */
146                              : "r" (data), "r" (entry << 3),
147                                "i" (ASI_ITLB_DATA_ACCESS));
148 }
149
150 static __inline__ void spitfire_flush_dtlb_nucleus_page(unsigned long page)
151 {
152         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
153                              "membar    #Sync"
154                              : /* No outputs */
155                              : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
156 }
157
158 static __inline__ void spitfire_flush_itlb_nucleus_page(unsigned long page)
159 {
160         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
161                              "membar    #Sync"
162                              : /* No outputs */
163                              : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
164 }
165
166 /* Cheetah has "all non-locked" tlb flushes. */
167 static __inline__ void cheetah_flush_dtlb_all(void)
168 {
169         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
170                              "membar    #Sync"
171                              : /* No outputs */
172                              : "r" (0x80), "i" (ASI_DMMU_DEMAP));
173 }
174
175 static __inline__ void cheetah_flush_itlb_all(void)
176 {
177         __asm__ __volatile__("stxa      %%g0, [%0] %1\n\t"
178                              "membar    #Sync"
179                              : /* No outputs */
180                              : "r" (0x80), "i" (ASI_IMMU_DEMAP));
181 }
182
183 /* Cheetah has a 4-tlb layout so direct access is a bit different.
184  * The first two TLBs are fully assosciative, hold 16 entries, and are
185  * used only for locked and >8K sized translations.  One exists for
186  * data accesses and one for instruction accesses.
187  *
188  * The third TLB is for data accesses to 8K non-locked translations, is
189  * 2 way assosciative, and holds 512 entries.  The fourth TLB is for
190  * instruction accesses to 8K non-locked translations, is 2 way
191  * assosciative, and holds 128 entries.
192  *
193  * Cheetah has some bug where bogus data can be returned from
194  * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
195  * the problem for me. -DaveM
196  */
197 static __inline__ unsigned long cheetah_get_ldtlb_data(int entry)
198 {
199         unsigned long data;
200
201         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
202                              "ldxa      [%1] %2, %0"
203                              : "=r" (data)
204                              : "r" ((0 << 16) | (entry << 3)),
205                              "i" (ASI_DTLB_DATA_ACCESS));
206
207         return data;
208 }
209
210 static __inline__ unsigned long cheetah_get_litlb_data(int entry)
211 {
212         unsigned long data;
213
214         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
215                              "ldxa      [%1] %2, %0"
216                              : "=r" (data)
217                              : "r" ((0 << 16) | (entry << 3)),
218                              "i" (ASI_ITLB_DATA_ACCESS));
219
220         return data;
221 }
222
223 static __inline__ unsigned long cheetah_get_ldtlb_tag(int entry)
224 {
225         unsigned long tag;
226
227         __asm__ __volatile__("ldxa      [%1] %2, %0"
228                              : "=r" (tag)
229                              : "r" ((0 << 16) | (entry << 3)),
230                              "i" (ASI_DTLB_TAG_READ));
231
232         return tag;
233 }
234
235 static __inline__ unsigned long cheetah_get_litlb_tag(int entry)
236 {
237         unsigned long tag;
238
239         __asm__ __volatile__("ldxa      [%1] %2, %0"
240                              : "=r" (tag)
241                              : "r" ((0 << 16) | (entry << 3)),
242                              "i" (ASI_ITLB_TAG_READ));
243
244         return tag;
245 }
246
247 static __inline__ void cheetah_put_ldtlb_data(int entry, unsigned long data)
248 {
249         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
250                              "membar    #Sync"
251                              : /* No outputs */
252                              : "r" (data),
253                                "r" ((0 << 16) | (entry << 3)),
254                                "i" (ASI_DTLB_DATA_ACCESS));
255 }
256
257 static __inline__ void cheetah_put_litlb_data(int entry, unsigned long data)
258 {
259         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
260                              "membar    #Sync"
261                              : /* No outputs */
262                              : "r" (data),
263                                "r" ((0 << 16) | (entry << 3)),
264                                "i" (ASI_ITLB_DATA_ACCESS));
265 }
266
267 static __inline__ unsigned long cheetah_get_dtlb_data(int entry, int tlb)
268 {
269         unsigned long data;
270
271         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
272                              "ldxa      [%1] %2, %0"
273                              : "=r" (data)
274                              : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
275
276         return data;
277 }
278
279 static __inline__ unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
280 {
281         unsigned long tag;
282
283         __asm__ __volatile__("ldxa      [%1] %2, %0"
284                              : "=r" (tag)
285                              : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
286         return tag;
287 }
288
289 static __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
290 {
291         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
292                              "membar    #Sync"
293                              : /* No outputs */
294                              : "r" (data),
295                                "r" ((tlb << 16) | (entry << 3)),
296                                "i" (ASI_DTLB_DATA_ACCESS));
297 }
298
299 static __inline__ unsigned long cheetah_get_itlb_data(int entry)
300 {
301         unsigned long data;
302
303         __asm__ __volatile__("ldxa      [%1] %2, %%g0\n\t"
304                              "ldxa      [%1] %2, %0"
305                              : "=r" (data)
306                              : "r" ((2 << 16) | (entry << 3)),
307                                "i" (ASI_ITLB_DATA_ACCESS));
308
309         return data;
310 }
311
312 static __inline__ unsigned long cheetah_get_itlb_tag(int entry)
313 {
314         unsigned long tag;
315
316         __asm__ __volatile__("ldxa      [%1] %2, %0"
317                              : "=r" (tag)
318                              : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
319         return tag;
320 }
321
322 static __inline__ void cheetah_put_itlb_data(int entry, unsigned long data)
323 {
324         __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
325                              "membar    #Sync"
326                              : /* No outputs */
327                              : "r" (data), "r" ((2 << 16) | (entry << 3)),
328                                "i" (ASI_ITLB_DATA_ACCESS));
329 }
330
331 #endif /* !(__ASSEMBLY__) */
332
333 #endif /* !(_SPARC64_SPITFIRE_H) */