xref: /arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu *
4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu */
6*91f16700Schasinglulu#ifndef CPU_MACROS_S
7*91f16700Schasinglulu#define CPU_MACROS_S
8*91f16700Schasinglulu
9*91f16700Schasinglulu#include <assert_macros.S>
10*91f16700Schasinglulu#include <lib/cpus/cpu_ops.h>
11*91f16700Schasinglulu#include <lib/cpus/errata.h>
12*91f16700Schasinglulu
13*91f16700Schasinglulu	/*
14*91f16700Schasinglulu	 * Write given expressions as quad words
15*91f16700Schasinglulu	 *
16*91f16700Schasinglulu	 * _count:
17*91f16700Schasinglulu	 *	Write at least _count quad words. If the given number of
18*91f16700Schasinglulu	 *	expressions is less than _count, repeat the last expression to
19*91f16700Schasinglulu	 *	fill _count quad words in total
20*91f16700Schasinglulu	 * _rest:
21*91f16700Schasinglulu	 *	Optional list of expressions. _this is for parameter extraction
22*91f16700Schasinglulu	 *	only, and has no significance to the caller
23*91f16700Schasinglulu	 *
24*91f16700Schasinglulu	 * Invoked as:
25*91f16700Schasinglulu	 *	fill_constants 2, foo, bar, blah, ...
26*91f16700Schasinglulu	 */
27*91f16700Schasinglulu	.macro fill_constants _count:req, _this, _rest:vararg
28*91f16700Schasinglulu	  .ifgt \_count
29*91f16700Schasinglulu	    /* Write the current expression */
30*91f16700Schasinglulu	    .ifb \_this
31*91f16700Schasinglulu	      .error "Nothing to fill"
32*91f16700Schasinglulu	    .endif
33*91f16700Schasinglulu	    .quad \_this
34*91f16700Schasinglulu
35*91f16700Schasinglulu	    /* Invoke recursively for remaining expressions */
36*91f16700Schasinglulu	    .ifnb \_rest
37*91f16700Schasinglulu	      fill_constants \_count-1, \_rest
38*91f16700Schasinglulu	    .else
39*91f16700Schasinglulu	      fill_constants \_count-1, \_this
40*91f16700Schasinglulu	    .endif
41*91f16700Schasinglulu	  .endif
42*91f16700Schasinglulu	.endm
43*91f16700Schasinglulu
44*91f16700Schasinglulu	/*
45*91f16700Schasinglulu	 * Declare CPU operations
46*91f16700Schasinglulu	 *
47*91f16700Schasinglulu	 * _name:
48*91f16700Schasinglulu	 *	Name of the CPU for which operations are being specified
49*91f16700Schasinglulu	 * _midr:
50*91f16700Schasinglulu	 *	Numeric value expected to read from CPU's MIDR
51*91f16700Schasinglulu	 * _resetfunc:
52*91f16700Schasinglulu	 *	Reset function for the CPU. If there's no CPU reset function,
53*91f16700Schasinglulu	 *	specify CPU_NO_RESET_FUNC
54*91f16700Schasinglulu	 * _extra1:
55*91f16700Schasinglulu	 *	This is a placeholder for future per CPU operations.  Currently,
56*91f16700Schasinglulu	 *	some CPUs use this entry to set a test function to determine if
57*91f16700Schasinglulu	 *	the workaround for CVE-2017-5715 needs to be applied or not.
58*91f16700Schasinglulu	 * _extra2:
59*91f16700Schasinglulu	 *	This is a placeholder for future per CPU operations. Currently
60*91f16700Schasinglulu	 *	some CPUs use this entry to set a function to disable the
61*91f16700Schasinglulu	 *	workaround for CVE-2018-3639.
62*91f16700Schasinglulu	 * _extra3:
63*91f16700Schasinglulu	 *	This is a placeholder for future per CPU operations. Currently,
64*91f16700Schasinglulu	 *	some CPUs use this entry to set a test function to determine if
65*91f16700Schasinglulu	 *	the workaround for CVE-2022-23960 needs to be applied or not.
66*91f16700Schasinglulu	 * _e_handler:
67*91f16700Schasinglulu	 *	This is a placeholder for future per CPU exception handlers.
68*91f16700Schasinglulu	 * _power_down_ops:
69*91f16700Schasinglulu	 *	Comma-separated list of functions to perform power-down
70*91f16700Schasinglulu	 *	operatios on the CPU. At least one, and up to
71*91f16700Schasinglulu	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
72*91f16700Schasinglulu	 *	Starting at power level 0, these functions shall handle power
73*91f16700Schasinglulu	 *	down at subsequent power levels. If there aren't exactly
74*91f16700Schasinglulu	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
75*91f16700Schasinglulu	 *	used to handle power down at subsequent levels
76*91f16700Schasinglulu	 */
77*91f16700Schasinglulu	.macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \
78*91f16700Schasinglulu		_extra1:req, _extra2:req, _extra3:req, _e_handler:req, _power_down_ops:vararg
79*91f16700Schasinglulu	.section .cpu_ops, "a"
80*91f16700Schasinglulu	.align 3
81*91f16700Schasinglulu	.type cpu_ops_\_name, %object
82*91f16700Schasinglulu	.quad \_midr
83*91f16700Schasinglulu#if defined(IMAGE_AT_EL3)
84*91f16700Schasinglulu	.quad \_resetfunc
85*91f16700Schasinglulu#endif
86*91f16700Schasinglulu	.quad \_extra1
87*91f16700Schasinglulu	.quad \_extra2
88*91f16700Schasinglulu	.quad \_extra3
89*91f16700Schasinglulu	.quad \_e_handler
90*91f16700Schasinglulu#ifdef IMAGE_BL31
91*91f16700Schasinglulu	/* Insert list of functions */
92*91f16700Schasinglulu	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
93*91f16700Schasinglulu#endif
94*91f16700Schasinglulu	/*
95*91f16700Schasinglulu	 * It is possible (although unlikely) that a cpu may have no errata in
96*91f16700Schasinglulu	 * code. In that case the start label will not be defined. The list is
97*91f16700Schasinglulu	 * intended to be used in a loop, so define it as zero-length for
98*91f16700Schasinglulu	 * predictable behaviour. Since this macro is always called at the end
99*91f16700Schasinglulu	 * of the cpu file (after all errata have been parsed) we can be sure
100*91f16700Schasinglulu	 * that we are at the end of the list. Some cpus call declare_cpu_ops
101*91f16700Schasinglulu	 * twice, so only do this once.
102*91f16700Schasinglulu	 */
103*91f16700Schasinglulu	.pushsection .rodata.errata_entries
104*91f16700Schasinglulu	.ifndef \_name\()_errata_list_start
105*91f16700Schasinglulu		\_name\()_errata_list_start:
106*91f16700Schasinglulu	.endif
107*91f16700Schasinglulu	.ifndef \_name\()_errata_list_end
108*91f16700Schasinglulu		\_name\()_errata_list_end:
109*91f16700Schasinglulu	.endif
110*91f16700Schasinglulu	.popsection
111*91f16700Schasinglulu
112*91f16700Schasinglulu	/* and now put them in cpu_ops */
113*91f16700Schasinglulu	.quad \_name\()_errata_list_start
114*91f16700Schasinglulu	.quad \_name\()_errata_list_end
115*91f16700Schasinglulu
116*91f16700Schasinglulu#if REPORT_ERRATA
117*91f16700Schasinglulu	.ifndef \_name\()_cpu_str
118*91f16700Schasinglulu	  /*
119*91f16700Schasinglulu	   * Place errata reported flag, and the spinlock to arbitrate access to
120*91f16700Schasinglulu	   * it in the data section.
121*91f16700Schasinglulu	   */
122*91f16700Schasinglulu	  .pushsection .data
123*91f16700Schasinglulu	  define_asm_spinlock \_name\()_errata_lock
124*91f16700Schasinglulu	  \_name\()_errata_reported:
125*91f16700Schasinglulu	  .word	0
126*91f16700Schasinglulu	  .popsection
127*91f16700Schasinglulu
128*91f16700Schasinglulu	  /* Place CPU string in rodata */
129*91f16700Schasinglulu	  .pushsection .rodata
130*91f16700Schasinglulu	  \_name\()_cpu_str:
131*91f16700Schasinglulu	  .asciz "\_name"
132*91f16700Schasinglulu	  .popsection
133*91f16700Schasinglulu	.endif
134*91f16700Schasinglulu
135*91f16700Schasinglulu
136*91f16700Schasinglulu	/*
137*91f16700Schasinglulu	 * Mandatory errata status printing function for CPUs of
138*91f16700Schasinglulu	 * this class.
139*91f16700Schasinglulu	 */
140*91f16700Schasinglulu	.quad \_name\()_errata_report
141*91f16700Schasinglulu	.quad \_name\()_cpu_str
142*91f16700Schasinglulu
143*91f16700Schasinglulu#ifdef IMAGE_BL31
144*91f16700Schasinglulu	/* Pointers to errata lock and reported flag */
145*91f16700Schasinglulu	.quad \_name\()_errata_lock
146*91f16700Schasinglulu	.quad \_name\()_errata_reported
147*91f16700Schasinglulu#endif /* IMAGE_BL31 */
148*91f16700Schasinglulu#endif /* REPORT_ERRATA */
149*91f16700Schasinglulu
150*91f16700Schasinglulu#if defined(IMAGE_BL31) && CRASH_REPORTING
151*91f16700Schasinglulu	.quad \_name\()_cpu_reg_dump
152*91f16700Schasinglulu#endif
153*91f16700Schasinglulu	.endm
154*91f16700Schasinglulu
155*91f16700Schasinglulu	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
156*91f16700Schasinglulu		_power_down_ops:vararg
157*91f16700Schasinglulu		declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, \
158*91f16700Schasinglulu			\_power_down_ops
159*91f16700Schasinglulu	.endm
160*91f16700Schasinglulu
161*91f16700Schasinglulu	.macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \
162*91f16700Schasinglulu		_e_handler:req, _power_down_ops:vararg
163*91f16700Schasinglulu		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
164*91f16700Schasinglulu			0, 0, 0, \_e_handler, \_power_down_ops
165*91f16700Schasinglulu	.endm
166*91f16700Schasinglulu
167*91f16700Schasinglulu	.macro declare_cpu_ops_wa _name:req, _midr:req, \
168*91f16700Schasinglulu		_resetfunc:req, _extra1:req, _extra2:req, \
169*91f16700Schasinglulu		_extra3:req, _power_down_ops:vararg
170*91f16700Schasinglulu		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
171*91f16700Schasinglulu			\_extra1, \_extra2, \_extra3, 0, \_power_down_ops
172*91f16700Schasinglulu	.endm
173*91f16700Schasinglulu
174*91f16700Schasinglulu/* TODO can be deleted once all CPUs have been converted */
175*91f16700Schasinglulu#if REPORT_ERRATA
176*91f16700Schasinglulu	/*
177*91f16700Schasinglulu	 * Print status of a CPU errata
178*91f16700Schasinglulu	 *
179*91f16700Schasinglulu	 * _chosen:
180*91f16700Schasinglulu	 *	Identifier indicating whether or not a CPU errata has been
181*91f16700Schasinglulu	 *	compiled in.
182*91f16700Schasinglulu	 * _cpu:
183*91f16700Schasinglulu	 *	Name of the CPU
184*91f16700Schasinglulu	 * _id:
185*91f16700Schasinglulu	 *	Errata identifier
186*91f16700Schasinglulu	 * _rev_var:
187*91f16700Schasinglulu	 *	Register containing the combined value CPU revision and variant
188*91f16700Schasinglulu	 *	- typically the return value of cpu_get_rev_var
189*91f16700Schasinglulu	 */
190*91f16700Schasinglulu	.macro report_errata _chosen, _cpu, _id, _rev_var=x8
191*91f16700Schasinglulu	/* Stash a string with errata ID */
192*91f16700Schasinglulu	.pushsection .rodata
193*91f16700Schasinglulu	\_cpu\()_errata_\_id\()_str:
194*91f16700Schasinglulu	.asciz	"\_id"
195*91f16700Schasinglulu	.popsection
196*91f16700Schasinglulu
197*91f16700Schasinglulu	/* Check whether errata applies */
198*91f16700Schasinglulu	mov	x0, \_rev_var
199*91f16700Schasinglulu	/* Shall clobber: x0-x7 */
200*91f16700Schasinglulu	bl	check_errata_\_id
201*91f16700Schasinglulu
202*91f16700Schasinglulu	.ifeq \_chosen
203*91f16700Schasinglulu	/*
204*91f16700Schasinglulu	 * Errata workaround has not been compiled in. If the errata would have
205*91f16700Schasinglulu	 * applied had it been compiled in, print its status as missing.
206*91f16700Schasinglulu	 */
207*91f16700Schasinglulu	cbz	x0, 900f
208*91f16700Schasinglulu	mov	x0, #ERRATA_MISSING
209*91f16700Schasinglulu	.endif
210*91f16700Schasinglulu900:
211*91f16700Schasinglulu	adr	x1, \_cpu\()_cpu_str
212*91f16700Schasinglulu	adr	x2, \_cpu\()_errata_\_id\()_str
213*91f16700Schasinglulu	bl	errata_print_msg
214*91f16700Schasinglulu	.endm
215*91f16700Schasinglulu#endif
216*91f16700Schasinglulu
217*91f16700Schasinglulu	/*
218*91f16700Schasinglulu	 * This macro is used on some CPUs to detect if they are vulnerable
219*91f16700Schasinglulu	 * to CVE-2017-5715.
220*91f16700Schasinglulu	 */
221*91f16700Schasinglulu	.macro	cpu_check_csv2 _reg _label
222*91f16700Schasinglulu	mrs	\_reg, id_aa64pfr0_el1
223*91f16700Schasinglulu	ubfx	\_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH
224*91f16700Schasinglulu	/*
225*91f16700Schasinglulu	 * If the field equals 1, branch targets trained in one context cannot
226*91f16700Schasinglulu	 * affect speculative execution in a different context.
227*91f16700Schasinglulu	 *
228*91f16700Schasinglulu	 * If the field equals 2, it means that the system is also aware of
229*91f16700Schasinglulu	 * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we
230*91f16700Schasinglulu	 * expect users of the registers to do the right thing.
231*91f16700Schasinglulu	 *
232*91f16700Schasinglulu	 * Only apply mitigations if the value of this field is 0.
233*91f16700Schasinglulu	 */
234*91f16700Schasinglulu#if ENABLE_ASSERTIONS
235*91f16700Schasinglulu	cmp	\_reg, #3 /* Only values 0 to 2 are expected */
236*91f16700Schasinglulu	ASM_ASSERT(lo)
237*91f16700Schasinglulu#endif
238*91f16700Schasinglulu
239*91f16700Schasinglulu	cmp	\_reg, #0
240*91f16700Schasinglulu	bne	\_label
241*91f16700Schasinglulu	.endm
242*91f16700Schasinglulu
243*91f16700Schasinglulu	/*
244*91f16700Schasinglulu	 * Helper macro that reads the part number of the current
245*91f16700Schasinglulu	 * CPU and jumps to the given label if it matches the CPU
246*91f16700Schasinglulu	 * MIDR provided.
247*91f16700Schasinglulu	 *
248*91f16700Schasinglulu	 * Clobbers x0.
249*91f16700Schasinglulu	 */
250*91f16700Schasinglulu	.macro  jump_if_cpu_midr _cpu_midr, _label
251*91f16700Schasinglulu	mrs	x0, midr_el1
252*91f16700Schasinglulu	ubfx	x0, x0, MIDR_PN_SHIFT, #12
253*91f16700Schasinglulu	cmp	w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
254*91f16700Schasinglulu	b.eq	\_label
255*91f16700Schasinglulu	.endm
256*91f16700Schasinglulu
257*91f16700Schasinglulu
258*91f16700Schasinglulu/*
259*91f16700Schasinglulu * Workaround wrappers for errata that apply at reset or runtime. Reset errata
260*91f16700Schasinglulu * will be applied automatically
261*91f16700Schasinglulu *
262*91f16700Schasinglulu * _cpu:
263*91f16700Schasinglulu *	Name of cpu as given to declare_cpu_ops
264*91f16700Schasinglulu *
265*91f16700Schasinglulu * _cve:
266*91f16700Schasinglulu *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
267*91f16700Schasinglulu *
268*91f16700Schasinglulu * _id:
269*91f16700Schasinglulu *	Erratum or CVE number. Please combine with previous field with ERRATUM
270*91f16700Schasinglulu *	or CVE macros
271*91f16700Schasinglulu *
272*91f16700Schasinglulu * _chosen:
273*91f16700Schasinglulu *	Compile time flag on whether the erratum is included
274*91f16700Schasinglulu *
275*91f16700Schasinglulu * _apply_at_reset:
276*91f16700Schasinglulu *	Whether the erratum should be automatically applied at reset
277*91f16700Schasinglulu */
278*91f16700Schasinglulu.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
279*91f16700Schasinglulu	.pushsection .rodata.errata_entries
280*91f16700Schasinglulu		.align	3
281*91f16700Schasinglulu		.ifndef \_cpu\()_errata_list_start
282*91f16700Schasinglulu		\_cpu\()_errata_list_start:
283*91f16700Schasinglulu		.endif
284*91f16700Schasinglulu
285*91f16700Schasinglulu		/* check if unused and compile out if no references */
286*91f16700Schasinglulu		.if \_apply_at_reset && \_chosen
287*91f16700Schasinglulu			.quad	erratum_\_cpu\()_\_id\()_wa
288*91f16700Schasinglulu		.else
289*91f16700Schasinglulu			.quad	0
290*91f16700Schasinglulu		.endif
291*91f16700Schasinglulu		/* TODO(errata ABI): this prevents all checker functions from
292*91f16700Schasinglulu		 * being optimised away. Can be done away with unless the ABI
293*91f16700Schasinglulu		 * needs them */
294*91f16700Schasinglulu		.quad	check_erratum_\_cpu\()_\_id
295*91f16700Schasinglulu		/* Will fit CVEs with up to 10 character in the ID field */
296*91f16700Schasinglulu		.word	\_id
297*91f16700Schasinglulu		.hword	\_cve
298*91f16700Schasinglulu		.byte	\_chosen
299*91f16700Schasinglulu		/* TODO(errata ABI): mitigated field for known but unmitigated
300*91f16700Schasinglulu		 * errata */
301*91f16700Schasinglulu		.byte	0x1
302*91f16700Schasinglulu	.popsection
303*91f16700Schasinglulu.endm
304*91f16700Schasinglulu
305*91f16700Schasinglulu.macro _workaround_start _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
306*91f16700Schasinglulu	add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_apply_at_reset
307*91f16700Schasinglulu
308*91f16700Schasinglulu	func erratum_\_cpu\()_\_id\()_wa
309*91f16700Schasinglulu		mov	x8, x30
310*91f16700Schasinglulu
311*91f16700Schasinglulu		/* save rev_var for workarounds that might need it but don't
312*91f16700Schasinglulu		 * restore to x0 because few will care */
313*91f16700Schasinglulu		mov	x7, x0
314*91f16700Schasinglulu		bl	check_erratum_\_cpu\()_\_id
315*91f16700Schasinglulu		cbz	x0, erratum_\_cpu\()_\_id\()_skip
316*91f16700Schasinglulu.endm
317*91f16700Schasinglulu
318*91f16700Schasinglulu.macro _workaround_end _cpu:req, _id:req
319*91f16700Schasinglulu	erratum_\_cpu\()_\_id\()_skip:
320*91f16700Schasinglulu		ret	x8
321*91f16700Schasinglulu	endfunc erratum_\_cpu\()_\_id\()_wa
322*91f16700Schasinglulu.endm
323*91f16700Schasinglulu
324*91f16700Schasinglulu/*******************************************************************************
325*91f16700Schasinglulu * Errata workaround wrappers
326*91f16700Schasinglulu ******************************************************************************/
327*91f16700Schasinglulu/*
328*91f16700Schasinglulu * Workaround wrappers for errata that apply at reset or runtime. Reset errata
329*91f16700Schasinglulu * will be applied automatically
330*91f16700Schasinglulu *
331*91f16700Schasinglulu * _cpu:
332*91f16700Schasinglulu *	Name of cpu as given to declare_cpu_ops
333*91f16700Schasinglulu *
334*91f16700Schasinglulu * _cve:
335*91f16700Schasinglulu *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
336*91f16700Schasinglulu *
337*91f16700Schasinglulu * _id:
338*91f16700Schasinglulu *	Erratum or CVE number. Please combine with previous field with ERRATUM
339*91f16700Schasinglulu *	or CVE macros
340*91f16700Schasinglulu *
341*91f16700Schasinglulu * _chosen:
342*91f16700Schasinglulu *	Compile time flag on whether the erratum is included
343*91f16700Schasinglulu *
344*91f16700Schasinglulu * in body:
345*91f16700Schasinglulu *	clobber x0 to x7 (please only use those)
346*91f16700Schasinglulu *	argument x7 - cpu_rev_var
347*91f16700Schasinglulu *
348*91f16700Schasinglulu * _wa clobbers: x0-x8 (PCS compliant)
349*91f16700Schasinglulu */
350*91f16700Schasinglulu.macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req
351*91f16700Schasinglulu	_workaround_start \_cpu, \_cve, \_id, \_chosen, 1
352*91f16700Schasinglulu.endm
353*91f16700Schasinglulu
354*91f16700Schasinglulu/*
355*91f16700Schasinglulu * See `workaround_reset_start` for usage info. Additional arguments:
356*91f16700Schasinglulu *
357*91f16700Schasinglulu * _midr:
358*91f16700Schasinglulu *	Check if CPU's MIDR matches the CPU it's meant for. Must be specified
359*91f16700Schasinglulu *	for errata applied in generic code
360*91f16700Schasinglulu */
361*91f16700Schasinglulu.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr
362*91f16700Schasinglulu	/*
363*91f16700Schasinglulu	 * Let errata specify if they need MIDR checking. Sadly, storing the
364*91f16700Schasinglulu	 * MIDR in an .equ to retrieve automatically blows up as it stores some
365*91f16700Schasinglulu	 * brackets in the symbol
366*91f16700Schasinglulu	 */
367*91f16700Schasinglulu	.ifnb \_midr
368*91f16700Schasinglulu		jump_if_cpu_midr \_midr, 1f
369*91f16700Schasinglulu		b	erratum_\_cpu\()_\_id\()_skip
370*91f16700Schasinglulu
371*91f16700Schasinglulu		1:
372*91f16700Schasinglulu	.endif
373*91f16700Schasinglulu	_workaround_start \_cpu, \_cve, \_id, \_chosen, 0
374*91f16700Schasinglulu.endm
375*91f16700Schasinglulu
376*91f16700Schasinglulu/*
377*91f16700Schasinglulu * Usage and arguments identical to `workaround_reset_start`. The _cve argument
378*91f16700Schasinglulu * is kept here so the same #define can be used as that macro
379*91f16700Schasinglulu */
380*91f16700Schasinglulu.macro workaround_reset_end _cpu:req, _cve:req, _id:req
381*91f16700Schasinglulu	_workaround_end \_cpu, \_id
382*91f16700Schasinglulu.endm
383*91f16700Schasinglulu
384*91f16700Schasinglulu/*
385*91f16700Schasinglulu * See `workaround_reset_start` for usage info. The _cve argument is kept here
386*91f16700Schasinglulu * so the same #define can be used as that macro. Additional arguments:
387*91f16700Schasinglulu *
388*91f16700Schasinglulu * _no_isb:
389*91f16700Schasinglulu *	Optionally do not include the trailing isb. Please disable with the
390*91f16700Schasinglulu *	NO_ISB macro
391*91f16700Schasinglulu */
392*91f16700Schasinglulu.macro workaround_runtime_end _cpu:req, _cve:req, _id:req, _no_isb
393*91f16700Schasinglulu	/*
394*91f16700Schasinglulu	 * Runtime errata do not have a reset function to call the isb for them
395*91f16700Schasinglulu	 * and missing the isb could be very problematic. It is also likely as
396*91f16700Schasinglulu	 * they tend to be scattered in generic code.
397*91f16700Schasinglulu	 */
398*91f16700Schasinglulu	.ifb \_no_isb
399*91f16700Schasinglulu		isb
400*91f16700Schasinglulu	.endif
401*91f16700Schasinglulu	_workaround_end \_cpu, \_id
402*91f16700Schasinglulu.endm
403*91f16700Schasinglulu
404*91f16700Schasinglulu/*******************************************************************************
405*91f16700Schasinglulu * Errata workaround helpers
406*91f16700Schasinglulu ******************************************************************************/
407*91f16700Schasinglulu/*
408*91f16700Schasinglulu * Set a bit in a system register. Can set multiple bits but is limited by the
409*91f16700Schasinglulu *  way the ORR instruction encodes them.
410*91f16700Schasinglulu *
411*91f16700Schasinglulu * _reg:
412*91f16700Schasinglulu *	Register to write to
413*91f16700Schasinglulu *
414*91f16700Schasinglulu * _bit:
415*91f16700Schasinglulu *	Bit to set. Please use a descriptive #define
416*91f16700Schasinglulu *
417*91f16700Schasinglulu * _assert:
418*91f16700Schasinglulu *	Optionally whether to read back and assert that the bit has been
419*91f16700Schasinglulu *	written. Please disable with NO_ASSERT macro
420*91f16700Schasinglulu *
421*91f16700Schasinglulu * clobbers: x1
422*91f16700Schasinglulu */
423*91f16700Schasinglulu.macro sysreg_bit_set _reg:req, _bit:req, _assert=1
424*91f16700Schasinglulu	mrs	x1, \_reg
425*91f16700Schasinglulu	orr	x1, x1, #\_bit
426*91f16700Schasinglulu	msr	\_reg, x1
427*91f16700Schasinglulu.endm
428*91f16700Schasinglulu
429*91f16700Schasinglulu/*
430*91f16700Schasinglulu * Clear a bit in a system register. Can clear multiple bits but is limited by
431*91f16700Schasinglulu *  the way the BIC instrucion encodes them.
432*91f16700Schasinglulu *
433*91f16700Schasinglulu * see sysreg_bit_set for usage
434*91f16700Schasinglulu */
435*91f16700Schasinglulu.macro sysreg_bit_clear _reg:req, _bit:req
436*91f16700Schasinglulu	mrs	x1, \_reg
437*91f16700Schasinglulu	bic	x1, x1, #\_bit
438*91f16700Schasinglulu	msr	\_reg, x1
439*91f16700Schasinglulu.endm
440*91f16700Schasinglulu
441*91f16700Schasinglulu.macro override_vector_table _table:req
442*91f16700Schasinglulu	adr	x1, \_table
443*91f16700Schasinglulu	msr	vbar_el3, x1
444*91f16700Schasinglulu.endm
445*91f16700Schasinglulu
446*91f16700Schasinglulu/*
447*91f16700Schasinglulu * BFI : Inserts bitfield into a system register.
448*91f16700Schasinglulu *
449*91f16700Schasinglulu * BFI{cond} Rd, Rn, #lsb, #width
450*91f16700Schasinglulu */
451*91f16700Schasinglulu.macro sysreg_bitfield_insert _reg:req, _src:req, _lsb:req, _width:req
452*91f16700Schasinglulu	/* Source value for BFI */
453*91f16700Schasinglulu	mov	x1, #\_src
454*91f16700Schasinglulu	mrs	x0, \_reg
455*91f16700Schasinglulu	bfi	x0, x1, #\_lsb, #\_width
456*91f16700Schasinglulu	msr	\_reg, x0
457*91f16700Schasinglulu.endm
458*91f16700Schasinglulu
459*91f16700Schasinglulu/*
460*91f16700Schasinglulu * Apply erratum
461*91f16700Schasinglulu *
462*91f16700Schasinglulu * _cpu:
463*91f16700Schasinglulu *	Name of cpu as given to declare_cpu_ops
464*91f16700Schasinglulu *
465*91f16700Schasinglulu * _cve:
466*91f16700Schasinglulu *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
467*91f16700Schasinglulu *
468*91f16700Schasinglulu * _id:
469*91f16700Schasinglulu *	Erratum or CVE number. Please combine with previous field with ERRATUM
470*91f16700Schasinglulu *	or CVE macros
471*91f16700Schasinglulu *
472*91f16700Schasinglulu * _chosen:
473*91f16700Schasinglulu *	Compile time flag on whether the erratum is included
474*91f16700Schasinglulu *
475*91f16700Schasinglulu * _get_rev:
476*91f16700Schasinglulu *	Optional parameter that determines whether to insert a call to the CPU revision fetching
477*91f16700Schasinglulu *	procedure. Stores the result of this in the temporary register x10.
478*91f16700Schasinglulu *
479*91f16700Schasinglulu * clobbers: x0-x10 (PCS compliant)
480*91f16700Schasinglulu */
481*91f16700Schasinglulu.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req, _get_rev=GET_CPU_REV
482*91f16700Schasinglulu	.if (\_chosen & \_get_rev)
483*91f16700Schasinglulu		mov	x9, x30
484*91f16700Schasinglulu		bl	cpu_get_rev_var
485*91f16700Schasinglulu		mov	x10, x0
486*91f16700Schasinglulu	.elseif (\_chosen)
487*91f16700Schasinglulu		mov	x9, x30
488*91f16700Schasinglulu		mov	x0, x10
489*91f16700Schasinglulu	.endif
490*91f16700Schasinglulu
491*91f16700Schasinglulu	.if \_chosen
492*91f16700Schasinglulu		bl	erratum_\_cpu\()_\_id\()_wa
493*91f16700Schasinglulu		mov	x30, x9
494*91f16700Schasinglulu	.endif
495*91f16700Schasinglulu.endm
496*91f16700Schasinglulu
497*91f16700Schasinglulu/*
498*91f16700Schasinglulu * Helpers to select which revisions errata apply to. Don't leave a link
499*91f16700Schasinglulu * register as the cpu_rev_var_*** will call the ret and we can save on one.
500*91f16700Schasinglulu *
501*91f16700Schasinglulu * _cpu:
502*91f16700Schasinglulu *	Name of cpu as given to declare_cpu_ops
503*91f16700Schasinglulu *
504*91f16700Schasinglulu * _cve:
505*91f16700Schasinglulu *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
506*91f16700Schasinglulu *
507*91f16700Schasinglulu * _id:
508*91f16700Schasinglulu *	Erratum or CVE number. Please combine with previous field with ERRATUM
509*91f16700Schasinglulu *	or CVE macros
510*91f16700Schasinglulu *
511*91f16700Schasinglulu * _rev_num:
512*91f16700Schasinglulu *	Revision to apply to
513*91f16700Schasinglulu *
514*91f16700Schasinglulu * in body:
515*91f16700Schasinglulu *	clobber: x0 to x4
516*91f16700Schasinglulu *	argument: x0 - cpu_rev_var
517*91f16700Schasinglulu */
518*91f16700Schasinglulu.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req
519*91f16700Schasinglulu	func check_erratum_\_cpu\()_\_id
520*91f16700Schasinglulu		mov	x1, #\_rev_num
521*91f16700Schasinglulu		b	cpu_rev_var_ls
522*91f16700Schasinglulu	endfunc check_erratum_\_cpu\()_\_id
523*91f16700Schasinglulu.endm
524*91f16700Schasinglulu
525*91f16700Schasinglulu.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req
526*91f16700Schasinglulu	func check_erratum_\_cpu\()_\_id
527*91f16700Schasinglulu		mov	x1, #\_rev_num
528*91f16700Schasinglulu		b	cpu_rev_var_hs
529*91f16700Schasinglulu	endfunc check_erratum_\_cpu\()_\_id
530*91f16700Schasinglulu.endm
531*91f16700Schasinglulu
532*91f16700Schasinglulu.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req
533*91f16700Schasinglulu	func check_erratum_\_cpu\()_\_id
534*91f16700Schasinglulu		mov	x1, #\_rev_num_lo
535*91f16700Schasinglulu		mov	x2, #\_rev_num_hi
536*91f16700Schasinglulu		b	cpu_rev_var_range
537*91f16700Schasinglulu	endfunc check_erratum_\_cpu\()_\_id
538*91f16700Schasinglulu.endm
539*91f16700Schasinglulu
540*91f16700Schasinglulu.macro check_erratum_chosen _cpu:req, _cve:req, _id:req, _chosen:req
541*91f16700Schasinglulu	func check_erratum_\_cpu\()_\_id
542*91f16700Schasinglulu		.if \_chosen
543*91f16700Schasinglulu			mov	x0, #ERRATA_APPLIES
544*91f16700Schasinglulu		.else
545*91f16700Schasinglulu			mov	x0, #ERRATA_MISSING
546*91f16700Schasinglulu		.endif
547*91f16700Schasinglulu		ret
548*91f16700Schasinglulu	endfunc check_erratum_\_cpu\()_\_id
549*91f16700Schasinglulu.endm
550*91f16700Schasinglulu
551*91f16700Schasinglulu/* provide a shorthand for the name format for annoying errata */
552*91f16700Schasinglulu.macro check_erratum_custom_start _cpu:req, _cve:req, _id:req
553*91f16700Schasinglulu	func check_erratum_\_cpu\()_\_id
554*91f16700Schasinglulu.endm
555*91f16700Schasinglulu
556*91f16700Schasinglulu.macro check_erratum_custom_end _cpu:req, _cve:req, _id:req
557*91f16700Schasinglulu	endfunc check_erratum_\_cpu\()_\_id
558*91f16700Schasinglulu.endm
559*91f16700Schasinglulu
560*91f16700Schasinglulu
561*91f16700Schasinglulu/*******************************************************************************
562*91f16700Schasinglulu * CPU reset function wrapper
563*91f16700Schasinglulu ******************************************************************************/
564*91f16700Schasinglulu
565*91f16700Schasinglulu/*
566*91f16700Schasinglulu * Wrapper to automatically apply all reset-time errata. Will end with an isb.
567*91f16700Schasinglulu *
568*91f16700Schasinglulu * _cpu:
569*91f16700Schasinglulu *	Name of cpu as given to declare_cpu_ops
570*91f16700Schasinglulu *
571*91f16700Schasinglulu * in body:
572*91f16700Schasinglulu *	clobber x8 to x14
573*91f16700Schasinglulu *	argument x14 - cpu_rev_var
574*91f16700Schasinglulu */
575*91f16700Schasinglulu.macro cpu_reset_func_start _cpu:req
576*91f16700Schasinglulu	func \_cpu\()_reset_func
577*91f16700Schasinglulu		mov	x15, x30
578*91f16700Schasinglulu		bl	cpu_get_rev_var
579*91f16700Schasinglulu		mov	x14, x0
580*91f16700Schasinglulu
581*91f16700Schasinglulu		/* short circuit the location to avoid searching the list */
582*91f16700Schasinglulu		adrp	x12, \_cpu\()_errata_list_start
583*91f16700Schasinglulu		add	x12, x12, :lo12:\_cpu\()_errata_list_start
584*91f16700Schasinglulu		adrp	x13, \_cpu\()_errata_list_end
585*91f16700Schasinglulu		add	x13, x13, :lo12:\_cpu\()_errata_list_end
586*91f16700Schasinglulu
587*91f16700Schasinglulu	errata_begin:
588*91f16700Schasinglulu		/* if head catches up with end of list, exit */
589*91f16700Schasinglulu		cmp	x12, x13
590*91f16700Schasinglulu		b.eq	errata_end
591*91f16700Schasinglulu
592*91f16700Schasinglulu		ldr	x10, [x12, #ERRATUM_WA_FUNC]
593*91f16700Schasinglulu		/* TODO(errata ABI): check mitigated and checker function fields
594*91f16700Schasinglulu		 * for 0 */
595*91f16700Schasinglulu		ldrb	w11, [x12, #ERRATUM_CHOSEN]
596*91f16700Schasinglulu
597*91f16700Schasinglulu		/* skip if not chosen */
598*91f16700Schasinglulu		cbz	x11, 1f
599*91f16700Schasinglulu		/* skip if runtime erratum */
600*91f16700Schasinglulu		cbz	x10, 1f
601*91f16700Schasinglulu
602*91f16700Schasinglulu		/* put cpu revision in x0 and call workaround */
603*91f16700Schasinglulu		mov	x0, x14
604*91f16700Schasinglulu		blr	x10
605*91f16700Schasinglulu	1:
606*91f16700Schasinglulu		add	x12, x12, #ERRATUM_ENTRY_SIZE
607*91f16700Schasinglulu		b	errata_begin
608*91f16700Schasinglulu	errata_end:
609*91f16700Schasinglulu.endm
610*91f16700Schasinglulu
611*91f16700Schasinglulu.macro cpu_reset_func_end _cpu:req
612*91f16700Schasinglulu		isb
613*91f16700Schasinglulu		ret	x15
614*91f16700Schasinglulu	endfunc \_cpu\()_reset_func
615*91f16700Schasinglulu.endm
616*91f16700Schasinglulu
617*91f16700Schasinglulu/*
618*91f16700Schasinglulu * Maintain compatibility with the old scheme of each cpu has its own reporting.
619*91f16700Schasinglulu * TODO remove entirely once all cpus have been converted. This includes the
620*91f16700Schasinglulu * cpu_ops entry, as print_errata_status can call this directly for all cpus
621*91f16700Schasinglulu */
622*91f16700Schasinglulu.macro errata_report_shim _cpu:req
623*91f16700Schasinglulu	#if REPORT_ERRATA
624*91f16700Schasinglulu	func \_cpu\()_errata_report
625*91f16700Schasinglulu		/* normal stack frame for pretty debugging */
626*91f16700Schasinglulu		stp	x29, x30, [sp, #-16]!
627*91f16700Schasinglulu		mov	x29, sp
628*91f16700Schasinglulu
629*91f16700Schasinglulu		bl	generic_errata_report
630*91f16700Schasinglulu
631*91f16700Schasinglulu		ldp	x29, x30, [sp], #16
632*91f16700Schasinglulu		ret
633*91f16700Schasinglulu	endfunc \_cpu\()_errata_report
634*91f16700Schasinglulu	#endif
635*91f16700Schasinglulu.endm
636*91f16700Schasinglulu#endif /* CPU_MACROS_S */
637