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