1 /*
2  * xtensa/cacheattrasm.h -- assembler-specific CACHEATTR register related definitions
3  *			that depend on CORE configuration
4  *
5  *  This file is logically part of xtensa/coreasm.h (or perhaps xtensa/cacheasm.h),
6  *  but is kept separate for modularity / compilation-performance.
7  */
8 
9 /*
10  * Copyright (c) 2001-2009 Tensilica Inc.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining
13  * a copy of this software and associated documentation files (the
14  * "Software"), to deal in the Software without restriction, including
15  * without limitation the rights to use, copy, modify, merge, publish,
16  * distribute, sublicense, and/or sell copies of the Software, and to
17  * permit persons to whom the Software is furnished to do so, subject to
18  * the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included
21  * in all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  */
31 
32 #ifndef XTENSA_CACHEATTRASM_H
33 #define XTENSA_CACHEATTRASM_H
34 
35 #include <xtensa/coreasm.h>
36 
37 /*  Determine whether cache attributes are controlled using eight 512MB entries:  */
38 #define XCHAL_CA_8X512	(XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR \
39 	|| (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY))
40 
41 
42 /*
43  *  This header file defines assembler macros of the form:
44  *	<x>cacheattr_<func>
45  *  where:
46  *	<x> is 'i', 'd' or absent for instruction, data
47  *		or both caches; and
48  *	<func> indicates the function of the macro.
49  *
50  *  The following functions are defined:
51  *
52  *  icacheattr_get
53  *	Reads I-cache CACHEATTR into a2 (clobbers a3-a5).
54  *
55  *  dcacheattr_get
56  *	Reads D-cache CACHEATTR into a2 (clobbers a3-a5).
57  *	(Note:  for configs with a real CACHEATTR register, the
58  *	 above two macros are identical.)
59  *
60  *  cacheattr_set
61  *	Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered).
62  *	Works even when changing one's own code's attributes.
63  *
64  *  icacheattr_is_enabled  label
65  *	Branches to \label if I-cache appears to have been enabled
66  *	(eg. if CACHEATTR contains a cache-enabled attribute).
67  *	(clobbers a2-a5,SAR)
68  *
69  *  dcacheattr_is_enabled  label
70  *	Branches to \label if D-cache appears to have been enabled
71  *	(eg. if CACHEATTR contains a cache-enabled attribute).
72  *	(clobbers a2-a5,SAR)
73  *
74  *  cacheattr_is_enabled  label
75  *	Branches to \label if either I-cache or D-cache appears to have been enabled
76  *	(eg. if CACHEATTR contains a cache-enabled attribute).
77  *	(clobbers a2-a5,SAR)
78  *
79  *  The following macros are only defined under certain conditions:
80  *
81  *  icacheattr_set	(if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
82  *	Writes I-cache CACHEATTR from a2 (a3-a8 clobbered).
83  *
84  *  dcacheattr_set	(if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
85  *	Writes D-cache CACHEATTR from a2 (a3-a8 clobbered).
86  */
87 
88 
89 
90 /***************************   GENERIC -- ALL CACHES   ***************************/
91 
92 /*
93  *  _cacheattr_get
94  *
95  *  (Internal macro.)
96  *  Returns value of CACHEATTR register (or closest equivalent) in a2.
97  *
98  *  Entry:
99  *	(none)
100  *  Exit:
101  *	a2	value read from CACHEATTR
102  *	a3-a5	clobbered (temporaries)
103  */
104 	.macro	_cacheattr_get	tlb
105 #if XCHAL_HAVE_CACHEATTR
106 	rsr.cacheattr	a2
107 #elif XCHAL_CA_8X512
108 	//  We have a config that "mimics" CACHEATTR using a simplified
109 	//  "MMU" composed of a single statically-mapped way.
110 	//  DTLB and ITLB are independent, so there's no single
111 	//  cache attribute that can describe both.  So for now
112 	//  just return the DTLB state.
113 	movi	a5, 0xE0000000
114 	movi	a2, 0
115 	movi	a3, XCHAL_SPANNING_WAY
116 1:	add	a3, a3, a5	// next segment
117 	r&tlb&1	a4, a3		// get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0
118 	dsync	// interlock???
119 	slli	a2, a2, 4
120 	extui	a4, a4, 0, 4	// extract CA
121 	or	a2, a2, a4
122 	bgeui	a3, 16, 1b
123 #else
124 	//  This macro isn't applicable to arbitrary MMU configurations.
125 	//  Just return zero.
126 	movi	a2, 0
127 #endif
128 	.endm
129 
130 	.macro	icacheattr_get
131 	_cacheattr_get	itlb
132 	.endm
133 
134 	.macro	dcacheattr_get
135 	_cacheattr_get	dtlb
136 	.endm
137 
138 
139 /* Default (powerup/reset) value of CACHEATTR,
140    all BYPASS mode (ie. disabled/bypassed caches): */
141 #if XCHAL_HAVE_PTP_MMU
142 # define XCHAL_CACHEATTR_ALL_BYPASS	0x33333333
143 #else
144 # define XCHAL_CACHEATTR_ALL_BYPASS	0x22222222
145 #endif
146 
147 #if XCHAL_CA_8X512
148 
149 #if XCHAL_HAVE_PTP_MMU
150 # define XCHAL_FCA_ENAMASK	0x0AA0	/* bitmap of fetch attributes that require enabled icache */
151 # define XCHAL_LCA_ENAMASK	0x0FF0	/* bitmap of load  attributes that require enabled dcache */
152 # define XCHAL_SCA_ENAMASK	0x0CC0	/* bitmap of store attributes that require enabled dcache */
153 #else
154 # define XCHAL_FCA_ENAMASK	0x003A	/* bitmap of fetch attributes that require enabled icache */
155 # define XCHAL_LCA_ENAMASK	0x0033	/* bitmap of load  attributes that require enabled dcache */
156 # define XCHAL_SCA_ENAMASK	0x0033	/* bitmap of store attributes that require enabled dcache */
157 #endif
158 #define XCHAL_LSCA_ENAMASK	(XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK)	/* l/s attrs requiring enabled dcache */
159 #define XCHAL_ALLCA_ENAMASK	(XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK)	/* all attrs requiring enabled caches */
160 
161 /*
162  *  _cacheattr_is_enabled
163  *
164  *  (Internal macro.)
165  *  Branches to \label if CACHEATTR in a2 indicates an enabled
166  *  cache, using mask in a3.
167  *
168  *  Parameters:
169  *	label	where to branch to if cache is enabled
170  *  Entry:
171  *	a2	contains CACHEATTR value used to determine whether
172  *		caches are enabled
173  *	a3	16-bit constant where each bit correspond to
174  *		one of the 16 possible CA values (in a CACHEATTR mask);
175  *		CA values that indicate the cache is enabled
176  *		have their corresponding bit set in this mask
177  *		(eg. use XCHAL_xCA_ENAMASK , above)
178  *  Exit:
179  *	a2,a4,a5	clobbered
180  *	SAR		clobbered
181  */
182 	.macro	_cacheattr_is_enabled	label
183 	movi	a4, 8		// loop 8 times
184 .Lcaife\@:
185 	extui	a5, a2, 0, 4	// get CA nibble
186 	ssr	a5		// index into mask according to CA...
187 	srl	a5, a3		// ...and get CA's mask bit in a5 bit 0
188 	bbsi.l	a5, 0, \label	// if CA indicates cache enabled, jump to label
189 	srli	a2, a2, 4	// next nibble
190 	addi	a4, a4, -1
191 	bnez	a4, .Lcaife\@	// loop for each nibble
192 	.endm
193 
194 #else /* XCHAL_CA_8X512 */
195 	.macro	_cacheattr_is_enabled	label
196 	j	\label		// macro not applicable, assume caches always enabled
197 	.endm
198 #endif /* XCHAL_CA_8X512 */
199 
200 
201 
202 /*
203  *  icacheattr_is_enabled
204  *
205  *  Branches to \label if I-cache is enabled.
206  *
207  *  Parameters:
208  *	label	where to branch to if icache is enabled
209  *  Entry:
210  *	(none)
211  *  Exit:
212  *	a2-a5, SAR	clobbered (temporaries)
213  */
214 	.macro	icacheattr_is_enabled	label
215 #if XCHAL_CA_8X512
216 	icacheattr_get
217 	movi	a3, XCHAL_FCA_ENAMASK
218 #endif
219 	_cacheattr_is_enabled	\label
220 	.endm
221 
222 /*
223  *  dcacheattr_is_enabled
224  *
225  *  Branches to \label if D-cache is enabled.
226  *
227  *  Parameters:
228  *	label	where to branch to if dcache is enabled
229  *  Entry:
230  *	(none)
231  *  Exit:
232  *	a2-a5, SAR	clobbered (temporaries)
233  */
234 	.macro	dcacheattr_is_enabled	label
235 #if XCHAL_CA_8X512
236 	dcacheattr_get
237 	movi	a3, XCHAL_LSCA_ENAMASK
238 #endif
239 	_cacheattr_is_enabled	\label
240 	.endm
241 
242 /*
243  *  cacheattr_is_enabled
244  *
245  *  Branches to \label if either I-cache or D-cache is enabled.
246  *
247  *  Parameters:
248  *	label	where to branch to if a cache is enabled
249  *  Entry:
250  *	(none)
251  *  Exit:
252  *	a2-a5, SAR	clobbered (temporaries)
253  */
254 	.macro	cacheattr_is_enabled	label
255 #if XCHAL_HAVE_CACHEATTR
256 	rsr.cacheattr	a2
257 	movi	a3, XCHAL_ALLCA_ENAMASK
258 #elif XCHAL_CA_8X512
259 	icacheattr_get
260 	movi	a3, XCHAL_FCA_ENAMASK
261 	_cacheattr_is_enabled	\label
262 	dcacheattr_get
263 	movi	a3, XCHAL_LSCA_ENAMASK
264 #endif
265 	_cacheattr_is_enabled	\label
266 	.endm
267 
268 
269 
270 /*
271  *  The ISA does not have a defined way to change the
272  *  instruction cache attributes of the running code,
273  *  ie. of the memory area that encloses the current PC.
274  *  However, each micro-architecture (or class of
275  *  configurations within a micro-architecture)
276  *  provides a way to deal with this issue.
277  *
278  *  Here are a few macros used to implement the relevant
279  *  approach taken.
280  */
281 
282 #if XCHAL_CA_8X512 && !XCHAL_HAVE_CACHEATTR
283 	//  We have a config that "mimics" CACHEATTR using a simplified
284 	//  "MMU" composed of a single statically-mapped way.
285 
286 /*
287  *  icacheattr_set
288  *
289  *  Entry:
290  *	a2		cacheattr value to set
291  *  Exit:
292  *	a2		unchanged
293  *	a3-a8		clobbered (temporaries)
294  */
295 	.macro	icacheattr_set
296 
297 	movi	a5, 0xE0000000	// mask of upper 3 bits
298 	movi	a6, 3f		// PC where ITLB is set
299 	movi	a3, XCHAL_SPANNING_WAY	// start at region 0 (0 .. 7)
300 	mov	a7, a2		// copy a2 so it doesn't get clobbered
301 	and	a6, a6, a5	// upper 3 bits of local PC area
302 	j	3f
303 
304 	//  Use micro-architecture specific method.
305 	//  The following 4-instruction sequence is aligned such that
306 	//  it all fits within a single I-cache line.  Sixteen byte
307 	//  alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE
308 	//  actually causes problems because that can be greater than
309 	//  the alignment of the reset vector, where this macro is often
310 	//  invoked, which would cause the linker to align the reset
311 	//  vector code away from the reset vector!!).
312 	.begin	no-transform
313 	.align	16 /*XCHAL_ICACHE_LINESIZE*/
314 1:	witlb	a4, a3		// write wired PTE (CA, no PPN) of 512MB segment to ITLB
315 	isync
316 	.end	no-transform
317 	nop
318 	nop
319 
320 	sub	a3, a3, a5	// next segment (add 0x20000000)
321 	bltui	a3, 16, 4f	// done?
322 
323 	//  Note that in the WITLB loop, we don't do any load/stores
324 	//  (may not be an issue here, but it is important in the DTLB case).
325 2:	srli	a7, a7, 4	// next CA
326 3:
327 # if XCHAL_HAVE_MIMIC_CACHEATTR
328 	extui	a4, a7, 0, 4	// extract CA to set
329 # else	/* have translation, preserve it: */
330 	ritlb1	a8, a3		// get current PPN+CA of segment
331 	//dsync	// interlock???
332 	extui	a4, a7, 0, 4	// extract CA to set
333 	srli	a8, a8, 4	// clear CA but keep PPN ...
334 	slli	a8, a8, 4	// ...
335 	add	a4, a4, a8	// combine new CA with PPN to preserve
336 # endif
337 	beq	a3, a6, 1b	// current PC's region? if so, do it in a safe way
338 	witlb	a4, a3		// write wired PTE (CA [+PPN]) of 512MB segment to ITLB
339 	sub	a3, a3, a5	// next segment (add 0x20000000)
340 	bgeui	a3, 16, 2b
341 	isync			// make sure all ifetch changes take effect
342 4:
343 	.endm	// icacheattr_set
344 
345 
346 /*
347  *  dcacheattr_set
348  *
349  *  Entry:
350  *	a2		cacheattr value to set
351  *  Exit:
352  *	a2		unchanged
353  *	a3-a8		clobbered (temporaries)
354  */
355 
356 	.macro	dcacheattr_set
357 
358 	movi	a5, 0xE0000000	// mask of upper 3 bits
359 	movi	a3, XCHAL_SPANNING_WAY	// start at region 0 (0 .. 7)
360 	mov	a7, a2		// copy a2 so it doesn't get clobbered
361 	//  Note that in the WDTLB loop, we don't do any load/stores
362 2:	//  (including implicit l32r via movi) because it isn't safe.
363 # if XCHAL_HAVE_MIMIC_CACHEATTR
364 	extui	a4, a7, 0, 4	// extract CA to set
365 # else	/* have translation, preserve it: */
366 	rdtlb1	a8, a3		// get current PPN+CA of segment
367 	//dsync	// interlock???
368 	extui	a4, a7, 0, 4	// extract CA to set
369 	srli	a8, a8, 4	// clear CA but keep PPN ...
370 	slli	a8, a8, 4	// ...
371 	add	a4, a4, a8	// combine new CA with PPN to preserve
372 # endif
373 	wdtlb	a4, a3		// write wired PTE (CA [+PPN]) of 512MB segment to DTLB
374 	sub	a3, a3, a5	// next segment (add 0x20000000)
375 	srli	a7, a7, 4	// next CA
376 	bgeui	a3, 16, 2b
377 	dsync			// make sure all data path changes take effect
378 	.endm	// dcacheattr_set
379 
380 #endif /* XCHAL_CA_8X512 && !XCHAL_HAVE_CACHEATTR */
381 
382 
383 
384 /*
385  *  cacheattr_set
386  *
387  *  Macro that sets the current CACHEATTR safely
388  *  (both i and d) according to the current contents of a2.
389  *  It works even when changing the cache attributes of
390  *  the currently running code.
391  *
392  *  Entry:
393  *	a2		cacheattr value to set
394  *  Exit:
395  *	a2		unchanged
396  *	a3-a8		clobbered (temporaries)
397  */
398 	.macro	cacheattr_set
399 
400 #if XCHAL_HAVE_CACHEATTR
401 # if XCHAL_ICACHE_LINESIZE < 4
402 	//  No i-cache, so can always safely write to CACHEATTR:
403 	wsr.cacheattr	a2
404 # else
405 	//  The Athens micro-architecture, when using the old
406 	//  exception architecture option (ie. with the CACHEATTR register)
407 	//  allows changing the cache attributes of the running code
408 	//  using the following exact sequence aligned to be within
409 	//  an instruction cache line.  (NOTE: using XCHAL_ICACHE_LINESIZE
410 	//  alignment actually causes problems because that can be greater
411 	//  than the alignment of the reset vector, where this macro is often
412 	//  invoked, which would cause the linker to align the reset
413 	//  vector code away from the reset vector!!).
414 	j	1f
415 	.begin	no-transform
416 	.align	16 /*XCHAL_ICACHE_LINESIZE*/	// align to within an I-cache line
417 1:	wsr.cacheattr	a2
418 	isync
419 	.end	no-transform
420 	nop
421 	nop
422 # endif
423 #elif XCHAL_CA_8X512
424 	//  DTLB and ITLB are independent, but to keep semantics
425 	//  of this macro we simply write to both.
426 	icacheattr_set
427 	dcacheattr_set
428 #else
429 	//  This macro isn't applicable to arbitrary MMU configurations.
430 	//  Do nothing in this case.
431 #endif
432 	.endm
433 
434 
435 #endif /*XTENSA_CACHEATTRASM_H*/
436