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