b330741a7d86b28b5c33c6fd3a9264e038063d96
[linux-flexiantxendom0-3.2.10.git] / include / asm-sparc64 / spitfire.h
1 /* $Id: spitfire.h,v 1.11 2001/03/03 10:34:45 davem 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
17 #define TLB_SFSR                0x0000000000000018
18 #define TSB_REG                 0x0000000000000028
19 #define TLB_TAG_ACCESS          0x0000000000000030
20
21 /* These registers only exist as one entity, and are accessed
22  * via ASI_DMMU only.
23  */
24 #define PRIMARY_CONTEXT         0x0000000000000008
25 #define SECONDARY_CONTEXT       0x0000000000000010
26 #define DMMU_SFAR               0x0000000000000020
27 #define VIRT_WATCHPOINT         0x0000000000000038
28 #define PHYS_WATCHPOINT         0x0000000000000040
29
30 #ifndef __ASSEMBLY__
31
32 enum ultra_tlb_layout {
33         spitfire = 0,
34         cheetah = 1
35 };
36
37 extern enum ultra_tlb_layout tlb_type;
38
39 #define SPITFIRE_HIGHEST_LOCKED_TLBENT  (64 - 1)
40 #define CHEETAH_HIGHEST_LOCKED_TLBENT   (16 - 1)
41
42 #define sparc64_highest_locked_tlbent() \
43         (tlb_type == spitfire ? \
44          SPITFIRE_HIGHEST_LOCKED_TLBENT : \
45          CHEETAH_HIGHEST_LOCKED_TLBENT)
46
47 extern __inline__ unsigned long spitfire_get_isfsr(void)
48 {
49         unsigned long ret;
50
51         __asm__ __volatile__("ldxa      [%1] %2, %0"
52                              : "=r" (ret)
53                              : "r" (TLB_SFSR), "i" (ASI_IMMU));
54         return ret;
55 }
56
57 extern __inline__ unsigned long spitfire_get_dsfsr(void)
58 {
59         unsigned long ret;
60
61         __asm__ __volatile__("ldxa      [%1] %2, %0"
62                              : "=r" (ret)
63                              : "r" (TLB_SFSR), "i" (ASI_DMMU));
64         return ret;
65 }
66
67 extern __inline__ unsigned long spitfire_get_sfar(void)
68 {
69         unsigned long ret;
70
71         __asm__ __volatile__("ldxa      [%1] %2, %0"
72                              : "=r" (ret)
73                              : "r" (DMMU_SFAR), "i" (ASI_DMMU));
74         return ret;
75 }
76
77 extern __inline__ void spitfire_put_isfsr(unsigned long sfsr)
78 {
79         __asm__ __volatile__("stxa      %0, [%1] %2" :
80                              : "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_IMMU));
81 }
82
83 extern __inline__ void spitfire_put_dsfsr(unsigned long sfsr)
84 {
85         __asm__ __volatile__("stxa      %0, [%1] %2" :
86                              : "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_DMMU));
87 }
88
89 extern __inline__ unsigned long spitfire_get_primary_context(void)
90 {
91         unsigned long ctx;
92
93         __asm__ __volatile__("ldxa      [%1] %2, %0"
94                              : "=r" (ctx)
95                              : "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
96         return ctx;
97 }
98
99 extern __inline__ void spitfire_set_primary_context(unsigned long ctx)
100 {
101         __asm__ __volatile__("stxa      %0, [%1] %2"
102                              : /* No outputs */
103                              : "r" (ctx & 0x3ff),
104                                "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
105         membar("#Sync");
106 }
107
108 extern __inline__ unsigned long spitfire_get_secondary_context(void)
109 {
110         unsigned long ctx;
111
112         __asm__ __volatile__("ldxa      [%1] %2, %0"
113                              : "=r" (ctx)
114                              : "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU));
115         return ctx;
116 }
117
118 extern __inline__ void spitfire_set_secondary_context(unsigned long ctx)
119 {
120         __asm__ __volatile__("stxa      %0, [%1] %2"
121                              : /* No outputs */
122                              : "r" (ctx & 0x3ff),
123                                "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU));
124         membar("#Sync");
125 }
126
127 /* The data cache is write through, so this just invalidates the
128  * specified line.
129  */
130 extern __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
131 {
132         __asm__ __volatile__("stxa      %0, [%1] %2"
133                              : /* No outputs */
134                              : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
135         membar("#Sync");
136 }
137
138 /* The instruction cache lines are flushed with this, but note that
139  * this does not flush the pipeline.  It is possible for a line to
140  * get flushed but stale instructions to still be in the pipeline,
141  * a flush instruction (to any address) is sufficient to handle
142  * this issue after the line is invalidated.
143  */
144 extern __inline__ void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
145 {
146         __asm__ __volatile__("stxa      %0, [%1] %2"
147                              : /* No outputs */
148                              : "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
149 }
150
151 extern __inline__ unsigned long spitfire_get_dtlb_data(int entry)
152 {
153         unsigned long data;
154
155         __asm__ __volatile__("ldxa      [%1] %2, %0"
156                              : "=r" (data)
157                              : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
158
159         /* Clear TTE diag bits. */
160         data &= ~0x0003fe0000000000UL;
161
162         return data;
163 }
164
165 extern __inline__ unsigned long spitfire_get_dtlb_tag(int entry)
166 {
167         unsigned long tag;
168
169         __asm__ __volatile__("ldxa      [%1] %2, %0"
170                              : "=r" (tag)
171                              : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
172         return tag;
173 }
174
175 extern __inline__ void spitfire_put_dtlb_data(int entry, unsigned long data)
176 {
177         __asm__ __volatile__("stxa      %0, [%1] %2"
178                              : /* No outputs */
179                              : "r" (data), "r" (entry << 3),
180                                "i" (ASI_DTLB_DATA_ACCESS));
181 }
182
183 extern __inline__ unsigned long spitfire_get_itlb_data(int entry)
184 {
185         unsigned long data;
186
187         __asm__ __volatile__("ldxa      [%1] %2, %0"
188                              : "=r" (data)
189                              : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
190
191         /* Clear TTE diag bits. */
192         data &= ~0x0003fe0000000000UL;
193
194         return data;
195 }
196
197 extern __inline__ unsigned long spitfire_get_itlb_tag(int entry)
198 {
199         unsigned long tag;
200
201         __asm__ __volatile__("ldxa      [%1] %2, %0"
202                              : "=r" (tag)
203                              : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
204         return tag;
205 }
206
207 extern __inline__ void spitfire_put_itlb_data(int entry, unsigned long data)
208 {
209         __asm__ __volatile__("stxa      %0, [%1] %2"
210                              : /* No outputs */
211                              : "r" (data), "r" (entry << 3),
212                                "i" (ASI_ITLB_DATA_ACCESS));
213 }
214
215 /* Spitfire hardware assisted TLB flushes. */
216
217 /* Context level flushes. */
218 extern __inline__ void spitfire_flush_dtlb_primary_context(void)
219 {
220         __asm__ __volatile__("stxa      %%g0, [%0] %1"
221                              : /* No outputs */
222                              : "r" (0x40), "i" (ASI_DMMU_DEMAP));
223 }
224
225 extern __inline__ void spitfire_flush_itlb_primary_context(void)
226 {
227         __asm__ __volatile__("stxa      %%g0, [%0] %1"
228                              : /* No outputs */
229                              : "r" (0x40), "i" (ASI_IMMU_DEMAP));
230 }
231
232 extern __inline__ void spitfire_flush_dtlb_secondary_context(void)
233 {
234         __asm__ __volatile__("stxa      %%g0, [%0] %1"
235                              : /* No outputs */
236                              : "r" (0x50), "i" (ASI_DMMU_DEMAP));
237 }
238
239 extern __inline__ void spitfire_flush_itlb_secondary_context(void)
240 {
241         __asm__ __volatile__("stxa      %%g0, [%0] %1"
242                              : /* No outputs */
243                              : "r" (0x50), "i" (ASI_IMMU_DEMAP));
244 }
245
246 extern __inline__ void spitfire_flush_dtlb_nucleus_context(void)
247 {
248         __asm__ __volatile__("stxa      %%g0, [%0] %1"
249                              : /* No outputs */
250                              : "r" (0x60), "i" (ASI_DMMU_DEMAP));
251 }
252
253 extern __inline__ void spitfire_flush_itlb_nucleus_context(void)
254 {
255         __asm__ __volatile__("stxa      %%g0, [%0] %1"
256                              : /* No outputs */
257                              : "r" (0x60), "i" (ASI_IMMU_DEMAP));
258 }
259
260 /* Page level flushes. */
261 extern __inline__ void spitfire_flush_dtlb_primary_page(unsigned long page)
262 {
263         __asm__ __volatile__("stxa      %%g0, [%0] %1"
264                              : /* No outputs */
265                              : "r" (page), "i" (ASI_DMMU_DEMAP));
266 }
267
268 extern __inline__ void spitfire_flush_itlb_primary_page(unsigned long page)
269 {
270         __asm__ __volatile__("stxa      %%g0, [%0] %1"
271                              : /* No outputs */
272                              : "r" (page), "i" (ASI_IMMU_DEMAP));
273 }
274
275 extern __inline__ void spitfire_flush_dtlb_secondary_page(unsigned long page)
276 {
277         __asm__ __volatile__("stxa      %%g0, [%0] %1"
278                              : /* No outputs */
279                              : "r" (page | 0x10), "i" (ASI_DMMU_DEMAP));
280 }
281
282 extern __inline__ void spitfire_flush_itlb_secondary_page(unsigned long page)
283 {
284         __asm__ __volatile__("stxa      %%g0, [%0] %1"
285                              : /* No outputs */
286                              : "r" (page | 0x10), "i" (ASI_IMMU_DEMAP));
287 }
288
289 extern __inline__ void spitfire_flush_dtlb_nucleus_page(unsigned long page)
290 {
291         __asm__ __volatile__("stxa      %%g0, [%0] %1"
292                              : /* No outputs */
293                              : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
294 }
295
296 extern __inline__ void spitfire_flush_itlb_nucleus_page(unsigned long page)
297 {
298         __asm__ __volatile__("stxa      %%g0, [%0] %1"
299                              : /* No outputs */
300                              : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
301 }
302
303 /* Cheetah has "all non-locked" tlb flushes. */
304 extern __inline__ void cheetah_flush_dtlb_all(void)
305 {
306         __asm__ __volatile__("stxa      %%g0, [%0] %1"
307                              : /* No outputs */
308                              : "r" (0x80), "i" (ASI_DMMU_DEMAP));
309 }
310
311 extern __inline__ void cheetah_flush_itlb_all(void)
312 {
313         __asm__ __volatile__("stxa      %%g0, [%0] %1"
314                              : /* No outputs */
315                              : "r" (0x80), "i" (ASI_IMMU_DEMAP));
316 }
317
318 /* Cheetah has a 4-tlb layout so direct access is a bit different.
319  * The first two TLBs are fully assosciative, hold 16 entries, and are
320  * used only for locked and >8K sized translations.  One exists for
321  * data accesses and one for instruction accesses.
322  *
323  * The third TLB is for data accesses to 8K non-locked translations, is
324  * 2 way assosciative, and holds 512 entries.  The fourth TLB is for
325  * instruction accesses to 8K non-locked translations, is 2 way
326  * assosciative, and holds 128 entries.
327  */
328 extern __inline__ unsigned long cheetah_get_ldtlb_data(int entry)
329 {
330         unsigned long data;
331
332         __asm__ __volatile__("ldxa      [%1] %2, %0"
333                              : "=r" (data)
334                              : "r" ((0 << 16) | (entry << 3)),
335                              "i" (ASI_DTLB_DATA_ACCESS));
336
337         return data;
338 }
339
340 extern __inline__ unsigned long cheetah_get_litlb_data(int entry)
341 {
342         unsigned long data;
343
344         __asm__ __volatile__("ldxa      [%1] %2, %0"
345                              : "=r" (data)
346                              : "r" ((0 << 16) | (entry << 3)),
347                              "i" (ASI_ITLB_DATA_ACCESS));
348
349         return data;
350 }
351
352 extern __inline__ unsigned long cheetah_get_ldtlb_tag(int entry)
353 {
354         unsigned long tag;
355
356         __asm__ __volatile__("ldxa      [%1] %2, %0"
357                              : "=r" (tag)
358                              : "r" ((0 << 16) | (entry << 3)),
359                              "i" (ASI_DTLB_TAG_READ));
360
361         return tag;
362 }
363
364 extern __inline__ unsigned long cheetah_get_litlb_tag(int entry)
365 {
366         unsigned long tag;
367
368         __asm__ __volatile__("ldxa      [%1] %2, %0"
369                              : "=r" (tag)
370                              : "r" ((0 << 16) | (entry << 3)),
371                              "i" (ASI_ITLB_TAG_READ));
372
373         return tag;
374 }
375
376 extern __inline__ void cheetah_put_ldtlb_data(int entry, unsigned long data)
377 {
378         __asm__ __volatile__("stxa      %0, [%1] %2"
379                              : /* No outputs */
380                              : "r" (data),
381                                "r" ((0 << 16) | (entry << 3)),
382                                "i" (ASI_DTLB_DATA_ACCESS));
383 }
384
385 extern __inline__ void cheetah_put_litlb_data(int entry, unsigned long data)
386 {
387         __asm__ __volatile__("stxa      %0, [%1] %2"
388                              : /* No outputs */
389                              : "r" (data),
390                                "r" ((0 << 16) | (entry << 3)),
391                                "i" (ASI_ITLB_DATA_ACCESS));
392 }
393
394 extern __inline__ unsigned long cheetah_get_dtlb_data(int entry)
395 {
396         unsigned long data;
397
398         __asm__ __volatile__("ldxa      [%1] %2, %0"
399                              : "=r" (data)
400                              : "r" ((2 << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
401
402         return data;
403 }
404
405 extern __inline__ unsigned long cheetah_get_dtlb_tag(int entry)
406 {
407         unsigned long tag;
408
409         __asm__ __volatile__("ldxa      [%1] %2, %0"
410                              : "=r" (tag)
411                              : "r" ((2 << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
412         return tag;
413 }
414
415 extern __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data)
416 {
417         __asm__ __volatile__("stxa      %0, [%1] %2"
418                              : /* No outputs */
419                              : "r" (data),
420                                "r" ((2 << 16) | (entry << 3)),
421                                "i" (ASI_DTLB_DATA_ACCESS));
422 }
423
424 extern __inline__ unsigned long cheetah_get_itlb_data(int entry)
425 {
426         unsigned long data;
427
428         __asm__ __volatile__("ldxa      [%1] %2, %0"
429                              : "=r" (data)
430                              : "r" ((2 << 16) | (entry << 3)),
431                                "i" (ASI_ITLB_DATA_ACCESS));
432
433         return data;
434 }
435
436 extern __inline__ unsigned long cheetah_get_itlb_tag(int entry)
437 {
438         unsigned long tag;
439
440         __asm__ __volatile__("ldxa      [%1] %2, %0"
441                              : "=r" (tag)
442                              : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
443         return tag;
444 }
445
446 extern __inline__ void cheetah_put_itlb_data(int entry, unsigned long data)
447 {
448         __asm__ __volatile__("stxa      %0, [%1] %2"
449                              : /* No outputs */
450                              : "r" (data), "r" ((2 << 16) | (entry << 3)),
451                                "i" (ASI_ITLB_DATA_ACCESS));
452 }
453
454 #endif /* !(__ASSEMBLY__) */
455
456 #endif /* !(_SPARC64_SPITFIRE_H) */