diff options
Diffstat (limited to 'arch/xtensa/include/asm/tlbflush.h')
-rw-r--r-- | arch/xtensa/include/asm/tlbflush.h | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/arch/xtensa/include/asm/tlbflush.h b/arch/xtensa/include/asm/tlbflush.h new file mode 100644 index 000000000000..46d240074f74 --- /dev/null +++ b/arch/xtensa/include/asm/tlbflush.h | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * include/asm-xtensa/tlbflush.h | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2001 - 2005 Tensilica Inc. | ||
9 | */ | ||
10 | |||
11 | #ifndef _XTENSA_TLBFLUSH_H | ||
12 | #define _XTENSA_TLBFLUSH_H | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | |||
16 | #include <linux/stringify.h> | ||
17 | #include <asm/processor.h> | ||
18 | |||
19 | #define DTLB_WAY_PGD 7 | ||
20 | |||
21 | #define ITLB_ARF_WAYS 4 | ||
22 | #define DTLB_ARF_WAYS 4 | ||
23 | |||
24 | #define ITLB_HIT_BIT 3 | ||
25 | #define DTLB_HIT_BIT 4 | ||
26 | |||
27 | #ifndef __ASSEMBLY__ | ||
28 | |||
29 | /* TLB flushing: | ||
30 | * | ||
31 | * - flush_tlb_all() flushes all processes TLB entries | ||
32 | * - flush_tlb_mm(mm) flushes the specified mm context TLB entries | ||
33 | * - flush_tlb_page(mm, vmaddr) flushes a single page | ||
34 | * - flush_tlb_range(mm, start, end) flushes a range of pages | ||
35 | */ | ||
36 | |||
37 | extern void flush_tlb_all(void); | ||
38 | extern void flush_tlb_mm(struct mm_struct*); | ||
39 | extern void flush_tlb_page(struct vm_area_struct*,unsigned long); | ||
40 | extern void flush_tlb_range(struct vm_area_struct*,unsigned long,unsigned long); | ||
41 | |||
42 | #define flush_tlb_kernel_range(start,end) flush_tlb_all() | ||
43 | |||
44 | /* TLB operations. */ | ||
45 | |||
46 | static inline unsigned long itlb_probe(unsigned long addr) | ||
47 | { | ||
48 | unsigned long tmp; | ||
49 | __asm__ __volatile__("pitlb %0, %1\n\t" : "=a" (tmp) : "a" (addr)); | ||
50 | return tmp; | ||
51 | } | ||
52 | |||
53 | static inline unsigned long dtlb_probe(unsigned long addr) | ||
54 | { | ||
55 | unsigned long tmp; | ||
56 | __asm__ __volatile__("pdtlb %0, %1\n\t" : "=a" (tmp) : "a" (addr)); | ||
57 | return tmp; | ||
58 | } | ||
59 | |||
60 | static inline void invalidate_itlb_entry (unsigned long probe) | ||
61 | { | ||
62 | __asm__ __volatile__("iitlb %0; isync\n\t" : : "a" (probe)); | ||
63 | } | ||
64 | |||
65 | static inline void invalidate_dtlb_entry (unsigned long probe) | ||
66 | { | ||
67 | __asm__ __volatile__("idtlb %0; dsync\n\t" : : "a" (probe)); | ||
68 | } | ||
69 | |||
70 | /* Use the .._no_isync functions with caution. Generally, these are | ||
71 | * handy for bulk invalidates followed by a single 'isync'. The | ||
72 | * caller must follow up with an 'isync', which can be relatively | ||
73 | * expensive on some Xtensa implementations. | ||
74 | */ | ||
75 | static inline void invalidate_itlb_entry_no_isync (unsigned entry) | ||
76 | { | ||
77 | /* Caller must follow up with 'isync'. */ | ||
78 | __asm__ __volatile__ ("iitlb %0\n" : : "a" (entry) ); | ||
79 | } | ||
80 | |||
81 | static inline void invalidate_dtlb_entry_no_isync (unsigned entry) | ||
82 | { | ||
83 | /* Caller must follow up with 'isync'. */ | ||
84 | __asm__ __volatile__ ("idtlb %0\n" : : "a" (entry) ); | ||
85 | } | ||
86 | |||
87 | static inline void set_itlbcfg_register (unsigned long val) | ||
88 | { | ||
89 | __asm__ __volatile__("wsr %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t" | ||
90 | : : "a" (val)); | ||
91 | } | ||
92 | |||
93 | static inline void set_dtlbcfg_register (unsigned long val) | ||
94 | { | ||
95 | __asm__ __volatile__("wsr %0, "__stringify(DTLBCFG)"; dsync\n\t" | ||
96 | : : "a" (val)); | ||
97 | } | ||
98 | |||
99 | static inline void set_ptevaddr_register (unsigned long val) | ||
100 | { | ||
101 | __asm__ __volatile__(" wsr %0, "__stringify(PTEVADDR)"; isync\n" | ||
102 | : : "a" (val)); | ||
103 | } | ||
104 | |||
105 | static inline unsigned long read_ptevaddr_register (void) | ||
106 | { | ||
107 | unsigned long tmp; | ||
108 | __asm__ __volatile__("rsr %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp)); | ||
109 | return tmp; | ||
110 | } | ||
111 | |||
112 | static inline void write_dtlb_entry (pte_t entry, int way) | ||
113 | { | ||
114 | __asm__ __volatile__("wdtlb %1, %0; dsync\n\t" | ||
115 | : : "r" (way), "r" (entry) ); | ||
116 | } | ||
117 | |||
118 | static inline void write_itlb_entry (pte_t entry, int way) | ||
119 | { | ||
120 | __asm__ __volatile__("witlb %1, %0; isync\n\t" | ||
121 | : : "r" (way), "r" (entry) ); | ||
122 | } | ||
123 | |||
124 | static inline void invalidate_page_directory (void) | ||
125 | { | ||
126 | invalidate_dtlb_entry (DTLB_WAY_PGD); | ||
127 | invalidate_dtlb_entry (DTLB_WAY_PGD+1); | ||
128 | invalidate_dtlb_entry (DTLB_WAY_PGD+2); | ||
129 | } | ||
130 | |||
131 | static inline void invalidate_itlb_mapping (unsigned address) | ||
132 | { | ||
133 | unsigned long tlb_entry; | ||
134 | if (((tlb_entry = itlb_probe(address)) & (1 << ITLB_HIT_BIT)) != 0) | ||
135 | invalidate_itlb_entry(tlb_entry); | ||
136 | } | ||
137 | |||
138 | static inline void invalidate_dtlb_mapping (unsigned address) | ||
139 | { | ||
140 | unsigned long tlb_entry; | ||
141 | if (((tlb_entry = dtlb_probe(address)) & (1 << DTLB_HIT_BIT)) != 0) | ||
142 | invalidate_dtlb_entry(tlb_entry); | ||
143 | } | ||
144 | |||
145 | #define check_pgt_cache() do { } while (0) | ||
146 | |||
147 | |||
148 | /* | ||
149 | * DO NOT USE THESE FUNCTIONS. These instructions aren't part of the Xtensa | ||
150 | * ISA and exist only for test purposes.. | ||
151 | * You may find it helpful for MMU debugging, however. | ||
152 | * | ||
153 | * 'at' is the unmodified input register | ||
154 | * 'as' is the output register, as follows (specific to the Linux config): | ||
155 | * | ||
156 | * as[31..12] contain the virtual address | ||
157 | * as[11..08] are meaningless | ||
158 | * as[07..00] contain the asid | ||
159 | */ | ||
160 | |||
161 | static inline unsigned long read_dtlb_virtual (int way) | ||
162 | { | ||
163 | unsigned long tmp; | ||
164 | __asm__ __volatile__("rdtlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way)); | ||
165 | return tmp; | ||
166 | } | ||
167 | |||
168 | static inline unsigned long read_dtlb_translation (int way) | ||
169 | { | ||
170 | unsigned long tmp; | ||
171 | __asm__ __volatile__("rdtlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way)); | ||
172 | return tmp; | ||
173 | } | ||
174 | |||
175 | static inline unsigned long read_itlb_virtual (int way) | ||
176 | { | ||
177 | unsigned long tmp; | ||
178 | __asm__ __volatile__("ritlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way)); | ||
179 | return tmp; | ||
180 | } | ||
181 | |||
182 | static inline unsigned long read_itlb_translation (int way) | ||
183 | { | ||
184 | unsigned long tmp; | ||
185 | __asm__ __volatile__("ritlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way)); | ||
186 | return tmp; | ||
187 | } | ||
188 | |||
189 | #endif /* __ASSEMBLY__ */ | ||
190 | #endif /* __KERNEL__ */ | ||
191 | #endif /* _XTENSA_TLBFLUSH_H */ | ||