xref: /aosp_15_r20/external/arm-trusted-firmware/lib/aarch64/cache_helpers.S (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park/*
2*54fd6939SJiyong Park * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park#include <arch.h>
8*54fd6939SJiyong Park#include <asm_macros.S>
9*54fd6939SJiyong Park
10*54fd6939SJiyong Park	.globl	flush_dcache_range
11*54fd6939SJiyong Park	.globl	clean_dcache_range
12*54fd6939SJiyong Park	.globl	inv_dcache_range
13*54fd6939SJiyong Park	.globl	dcsw_op_louis
14*54fd6939SJiyong Park	.globl	dcsw_op_all
15*54fd6939SJiyong Park	.globl	dcsw_op_level1
16*54fd6939SJiyong Park	.globl	dcsw_op_level2
17*54fd6939SJiyong Park	.globl	dcsw_op_level3
18*54fd6939SJiyong Park
19*54fd6939SJiyong Park/*
20*54fd6939SJiyong Park * This macro can be used for implementing various data cache operations `op`
21*54fd6939SJiyong Park */
22*54fd6939SJiyong Park.macro do_dcache_maintenance_by_mva op
23*54fd6939SJiyong Park	/* Exit early if size is zero */
24*54fd6939SJiyong Park	cbz	x1, exit_loop_\op
25*54fd6939SJiyong Park	dcache_line_size x2, x3
26*54fd6939SJiyong Park	add	x1, x0, x1
27*54fd6939SJiyong Park	sub	x3, x2, #1
28*54fd6939SJiyong Park	bic	x0, x0, x3
29*54fd6939SJiyong Parkloop_\op:
30*54fd6939SJiyong Park	dc	\op, x0
31*54fd6939SJiyong Park	add	x0, x0, x2
32*54fd6939SJiyong Park	cmp	x0, x1
33*54fd6939SJiyong Park	b.lo	loop_\op
34*54fd6939SJiyong Park	dsb	sy
35*54fd6939SJiyong Parkexit_loop_\op:
36*54fd6939SJiyong Park	ret
37*54fd6939SJiyong Park.endm
38*54fd6939SJiyong Park	/* ------------------------------------------
39*54fd6939SJiyong Park	 * Clean+Invalidate from base address till
40*54fd6939SJiyong Park	 * size. 'x0' = addr, 'x1' = size
41*54fd6939SJiyong Park	 * ------------------------------------------
42*54fd6939SJiyong Park	 */
43*54fd6939SJiyong Parkfunc flush_dcache_range
44*54fd6939SJiyong Park	do_dcache_maintenance_by_mva civac
45*54fd6939SJiyong Parkendfunc flush_dcache_range
46*54fd6939SJiyong Park
47*54fd6939SJiyong Park	/* ------------------------------------------
48*54fd6939SJiyong Park	 * Clean from base address till size.
49*54fd6939SJiyong Park	 * 'x0' = addr, 'x1' = size
50*54fd6939SJiyong Park	 * ------------------------------------------
51*54fd6939SJiyong Park	 */
52*54fd6939SJiyong Parkfunc clean_dcache_range
53*54fd6939SJiyong Park	do_dcache_maintenance_by_mva cvac
54*54fd6939SJiyong Parkendfunc clean_dcache_range
55*54fd6939SJiyong Park
56*54fd6939SJiyong Park	/* ------------------------------------------
57*54fd6939SJiyong Park	 * Invalidate from base address till
58*54fd6939SJiyong Park	 * size. 'x0' = addr, 'x1' = size
59*54fd6939SJiyong Park	 * ------------------------------------------
60*54fd6939SJiyong Park	 */
61*54fd6939SJiyong Parkfunc inv_dcache_range
62*54fd6939SJiyong Park	do_dcache_maintenance_by_mva ivac
63*54fd6939SJiyong Parkendfunc inv_dcache_range
64*54fd6939SJiyong Park
65*54fd6939SJiyong Park
66*54fd6939SJiyong Park	/* ---------------------------------------------------------------
67*54fd6939SJiyong Park	 * Data cache operations by set/way to the level specified
68*54fd6939SJiyong Park	 *
69*54fd6939SJiyong Park	 * The main function, do_dcsw_op requires:
70*54fd6939SJiyong Park	 * x0: The operation type (0-2), as defined in arch.h
71*54fd6939SJiyong Park	 * x3: The last cache level to operate on
72*54fd6939SJiyong Park	 * x9: clidr_el1
73*54fd6939SJiyong Park	 * x10: The cache level to begin operation from
74*54fd6939SJiyong Park	 * and will carry out the operation on each data cache from level 0
75*54fd6939SJiyong Park	 * to the level in x3 in sequence
76*54fd6939SJiyong Park	 *
77*54fd6939SJiyong Park	 * The dcsw_op macro sets up the x3 and x9 parameters based on
78*54fd6939SJiyong Park	 * clidr_el1 cache information before invoking the main function
79*54fd6939SJiyong Park	 * ---------------------------------------------------------------
80*54fd6939SJiyong Park	 */
81*54fd6939SJiyong Park
82*54fd6939SJiyong Park	.macro	dcsw_op shift, fw, ls
83*54fd6939SJiyong Park	mrs	x9, clidr_el1
84*54fd6939SJiyong Park	ubfx	x3, x9, \shift, \fw
85*54fd6939SJiyong Park	lsl	x3, x3, \ls
86*54fd6939SJiyong Park	mov	x10, xzr
87*54fd6939SJiyong Park	b	do_dcsw_op
88*54fd6939SJiyong Park	.endm
89*54fd6939SJiyong Park
90*54fd6939SJiyong Parkfunc do_dcsw_op
91*54fd6939SJiyong Park	cbz	x3, exit
92*54fd6939SJiyong Park	adr	x14, dcsw_loop_table	// compute inner loop address
93*54fd6939SJiyong Park	add	x14, x14, x0, lsl #5	// inner loop is 8x32-bit instructions
94*54fd6939SJiyong Park#if ENABLE_BTI
95*54fd6939SJiyong Park	add	x14, x14, x0, lsl #2	// inner loop is + "bti j" instruction
96*54fd6939SJiyong Park#endif
97*54fd6939SJiyong Park	mov	x0, x9
98*54fd6939SJiyong Park	mov	w8, #1
99*54fd6939SJiyong Parkloop1:
100*54fd6939SJiyong Park	add	x2, x10, x10, lsr #1	// work out 3x current cache level
101*54fd6939SJiyong Park	lsr	x1, x0, x2		// extract cache type bits from clidr
102*54fd6939SJiyong Park	and	x1, x1, #7		// mask the bits for current cache only
103*54fd6939SJiyong Park	cmp	x1, #2			// see what cache we have at this level
104*54fd6939SJiyong Park	b.lo	level_done		// nothing to do if no cache or icache
105*54fd6939SJiyong Park
106*54fd6939SJiyong Park	msr	csselr_el1, x10		// select current cache level in csselr
107*54fd6939SJiyong Park	isb				// isb to sych the new cssr&csidr
108*54fd6939SJiyong Park	mrs	x1, ccsidr_el1		// read the new ccsidr
109*54fd6939SJiyong Park	and	x2, x1, #7		// extract the length of the cache lines
110*54fd6939SJiyong Park	add	x2, x2, #4		// add 4 (line length offset)
111*54fd6939SJiyong Park	ubfx	x4, x1, #3, #10		// maximum way number
112*54fd6939SJiyong Park	clz	w5, w4			// bit position of way size increment
113*54fd6939SJiyong Park	lsl	w9, w4, w5		// w9 = aligned max way number
114*54fd6939SJiyong Park	lsl	w16, w8, w5		// w16 = way number loop decrement
115*54fd6939SJiyong Park	orr	w9, w10, w9		// w9 = combine way and cache number
116*54fd6939SJiyong Park	ubfx	w6, w1, #13, #15	// w6 = max set number
117*54fd6939SJiyong Park	lsl	w17, w8, w2		// w17 = set number loop decrement
118*54fd6939SJiyong Park	dsb	sy			// barrier before we start this level
119*54fd6939SJiyong Park	br	x14			// jump to DC operation specific loop
120*54fd6939SJiyong Park
121*54fd6939SJiyong Park	.macro	dcsw_loop _op
122*54fd6939SJiyong Park#if ENABLE_BTI
123*54fd6939SJiyong Park	bti	j
124*54fd6939SJiyong Park#endif
125*54fd6939SJiyong Parkloop2_\_op:
126*54fd6939SJiyong Park	lsl	w7, w6, w2		// w7 = aligned max set number
127*54fd6939SJiyong Park
128*54fd6939SJiyong Parkloop3_\_op:
129*54fd6939SJiyong Park	orr	w11, w9, w7		// combine cache, way and set number
130*54fd6939SJiyong Park	dc	\_op, x11
131*54fd6939SJiyong Park	subs	w7, w7, w17		// decrement set number
132*54fd6939SJiyong Park	b.hs	loop3_\_op
133*54fd6939SJiyong Park
134*54fd6939SJiyong Park	subs	x9, x9, x16		// decrement way number
135*54fd6939SJiyong Park	b.hs	loop2_\_op
136*54fd6939SJiyong Park
137*54fd6939SJiyong Park	b	level_done
138*54fd6939SJiyong Park	.endm
139*54fd6939SJiyong Park
140*54fd6939SJiyong Parklevel_done:
141*54fd6939SJiyong Park	add	x10, x10, #2		// increment cache number
142*54fd6939SJiyong Park	cmp	x3, x10
143*54fd6939SJiyong Park	b.hi	loop1
144*54fd6939SJiyong Park	msr	csselr_el1, xzr		// select cache level 0 in csselr
145*54fd6939SJiyong Park	dsb	sy			// barrier to complete final cache operation
146*54fd6939SJiyong Park	isb
147*54fd6939SJiyong Parkexit:
148*54fd6939SJiyong Park	ret
149*54fd6939SJiyong Parkendfunc do_dcsw_op
150*54fd6939SJiyong Park
151*54fd6939SJiyong Parkdcsw_loop_table:
152*54fd6939SJiyong Park	dcsw_loop isw
153*54fd6939SJiyong Park	dcsw_loop cisw
154*54fd6939SJiyong Park	dcsw_loop csw
155*54fd6939SJiyong Park
156*54fd6939SJiyong Park
157*54fd6939SJiyong Parkfunc dcsw_op_louis
158*54fd6939SJiyong Park	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
159*54fd6939SJiyong Parkendfunc dcsw_op_louis
160*54fd6939SJiyong Park
161*54fd6939SJiyong Park
162*54fd6939SJiyong Parkfunc dcsw_op_all
163*54fd6939SJiyong Park	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
164*54fd6939SJiyong Parkendfunc dcsw_op_all
165*54fd6939SJiyong Park
166*54fd6939SJiyong Park	/* ---------------------------------------------------------------
167*54fd6939SJiyong Park	 *  Helper macro for data cache operations by set/way for the
168*54fd6939SJiyong Park	 *  level specified
169*54fd6939SJiyong Park	 * ---------------------------------------------------------------
170*54fd6939SJiyong Park	 */
171*54fd6939SJiyong Park	.macro dcsw_op_level level
172*54fd6939SJiyong Park	mrs	x9, clidr_el1
173*54fd6939SJiyong Park	mov	x3, \level
174*54fd6939SJiyong Park	sub	x10, x3, #2
175*54fd6939SJiyong Park	b	do_dcsw_op
176*54fd6939SJiyong Park	.endm
177*54fd6939SJiyong Park
178*54fd6939SJiyong Park	/* ---------------------------------------------------------------
179*54fd6939SJiyong Park	 * Data cache operations by set/way for level 1 cache
180*54fd6939SJiyong Park	 *
181*54fd6939SJiyong Park	 * The main function, do_dcsw_op requires:
182*54fd6939SJiyong Park	 * x0: The operation type (0-2), as defined in arch.h
183*54fd6939SJiyong Park	 * ---------------------------------------------------------------
184*54fd6939SJiyong Park	 */
185*54fd6939SJiyong Parkfunc dcsw_op_level1
186*54fd6939SJiyong Park	dcsw_op_level #(1 << LEVEL_SHIFT)
187*54fd6939SJiyong Parkendfunc dcsw_op_level1
188*54fd6939SJiyong Park
189*54fd6939SJiyong Park	/* ---------------------------------------------------------------
190*54fd6939SJiyong Park	 * Data cache operations by set/way for level 2 cache
191*54fd6939SJiyong Park	 *
192*54fd6939SJiyong Park	 * The main function, do_dcsw_op requires:
193*54fd6939SJiyong Park	 * x0: The operation type (0-2), as defined in arch.h
194*54fd6939SJiyong Park	 * ---------------------------------------------------------------
195*54fd6939SJiyong Park	 */
196*54fd6939SJiyong Parkfunc dcsw_op_level2
197*54fd6939SJiyong Park	dcsw_op_level #(2 << LEVEL_SHIFT)
198*54fd6939SJiyong Parkendfunc dcsw_op_level2
199*54fd6939SJiyong Park
200*54fd6939SJiyong Park	/* ---------------------------------------------------------------
201*54fd6939SJiyong Park	 * Data cache operations by set/way for level 3 cache
202*54fd6939SJiyong Park	 *
203*54fd6939SJiyong Park	 * The main function, do_dcsw_op requires:
204*54fd6939SJiyong Park	 * x0: The operation type (0-2), as defined in arch.h
205*54fd6939SJiyong Park	 * ---------------------------------------------------------------
206*54fd6939SJiyong Park	 */
207*54fd6939SJiyong Parkfunc dcsw_op_level3
208*54fd6939SJiyong Park	dcsw_op_level #(3 << LEVEL_SHIFT)
209*54fd6939SJiyong Parkendfunc dcsw_op_level3
210