xref: /arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2016-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 <lib/cpus/cpu_ops.h>
10*91f16700Schasinglulu#include <lib/cpus/errata.h>
11*91f16700Schasinglulu
12*91f16700Schasinglulu	/*
13*91f16700Schasinglulu	 * Write given expressions as words
14*91f16700Schasinglulu	 *
15*91f16700Schasinglulu	 * _count:
16*91f16700Schasinglulu	 *	Write at least _count words. If the given number of expressions
17*91f16700Schasinglulu	 *	is less than _count, repeat the last expression to fill _count
18*91f16700Schasinglulu	 *	words in total
19*91f16700Schasinglulu	 * _rest:
20*91f16700Schasinglulu	 *	Optional list of expressions. _this is for parameter extraction
21*91f16700Schasinglulu	 *	only, and has no significance to the caller
22*91f16700Schasinglulu	 *
23*91f16700Schasinglulu	 * Invoked as:
24*91f16700Schasinglulu	 *	fill_constants 2, foo, bar, blah, ...
25*91f16700Schasinglulu	 */
26*91f16700Schasinglulu	.macro fill_constants _count:req, _this, _rest:vararg
27*91f16700Schasinglulu	  .ifgt \_count
28*91f16700Schasinglulu	    /* Write the current expression */
29*91f16700Schasinglulu	    .ifb \_this
30*91f16700Schasinglulu	      .error "Nothing to fill"
31*91f16700Schasinglulu	    .endif
32*91f16700Schasinglulu	    .word \_this
33*91f16700Schasinglulu
34*91f16700Schasinglulu	    /* Invoke recursively for remaining expressions */
35*91f16700Schasinglulu	    .ifnb \_rest
36*91f16700Schasinglulu	      fill_constants \_count-1, \_rest
37*91f16700Schasinglulu	    .else
38*91f16700Schasinglulu	      fill_constants \_count-1, \_this
39*91f16700Schasinglulu	    .endif
40*91f16700Schasinglulu	  .endif
41*91f16700Schasinglulu	.endm
42*91f16700Schasinglulu
43*91f16700Schasinglulu	/*
44*91f16700Schasinglulu	 * Declare CPU operations
45*91f16700Schasinglulu	 *
46*91f16700Schasinglulu	 * _name:
47*91f16700Schasinglulu	 *	Name of the CPU for which operations are being specified
48*91f16700Schasinglulu	 * _midr:
49*91f16700Schasinglulu	 *	Numeric value expected to read from CPU's MIDR
50*91f16700Schasinglulu	 * _resetfunc:
51*91f16700Schasinglulu	 *	Reset function for the CPU. If there's no CPU reset function,
52*91f16700Schasinglulu	 *	specify CPU_NO_RESET_FUNC
53*91f16700Schasinglulu	 * _power_down_ops:
54*91f16700Schasinglulu	 *	Comma-separated list of functions to perform power-down
55*91f16700Schasinglulu	 *	operatios on the CPU. At least one, and up to
56*91f16700Schasinglulu	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
57*91f16700Schasinglulu	 *	Starting at power level 0, these functions shall handle power
58*91f16700Schasinglulu	 *	down at subsequent power levels. If there aren't exactly
59*91f16700Schasinglulu	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
60*91f16700Schasinglulu	 *	used to handle power down at subsequent levels
61*91f16700Schasinglulu	 */
62*91f16700Schasinglulu	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
63*91f16700Schasinglulu		_power_down_ops:vararg
64*91f16700Schasinglulu	.section .cpu_ops, "a"
65*91f16700Schasinglulu	.align 2
66*91f16700Schasinglulu	.type cpu_ops_\_name, %object
67*91f16700Schasinglulu	.word \_midr
68*91f16700Schasinglulu#if defined(IMAGE_AT_EL3)
69*91f16700Schasinglulu	.word \_resetfunc
70*91f16700Schasinglulu#endif
71*91f16700Schasinglulu#ifdef IMAGE_BL32
72*91f16700Schasinglulu	/* Insert list of functions */
73*91f16700Schasinglulu	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
74*91f16700Schasinglulu#endif
75*91f16700Schasinglulu
76*91f16700Schasinglulu	/*
77*91f16700Schasinglulu	 * It is possible (although unlikely) that a cpu may have no errata in
78*91f16700Schasinglulu	 * code. In that case the start label will not be defined. The list is
79*91f16700Schasinglulu	 * inteded to be used in a loop, so define it as zero-length for
80*91f16700Schasinglulu	 * predictable behaviour. Since this macro is always called at the end
81*91f16700Schasinglulu	 * of the cpu file (after all errata have been parsed) we can be sure
82*91f16700Schasinglulu	 * that we are at the end of the list. Some cpus call the macro twice,
83*91f16700Schasinglulu	 * so only do this once.
84*91f16700Schasinglulu	 */
85*91f16700Schasinglulu	.pushsection .rodata.errata_entries
86*91f16700Schasinglulu	.ifndef \_name\()_errata_list_start
87*91f16700Schasinglulu		\_name\()_errata_list_start:
88*91f16700Schasinglulu	.endif
89*91f16700Schasinglulu	/* some call this multiple times, so only do this once */
90*91f16700Schasinglulu	.ifndef \_name\()_errata_list_end
91*91f16700Schasinglulu		\_name\()_errata_list_end:
92*91f16700Schasinglulu	.endif
93*91f16700Schasinglulu	.popsection
94*91f16700Schasinglulu
95*91f16700Schasinglulu	/* and now put them in cpu_ops */
96*91f16700Schasinglulu	.word \_name\()_errata_list_start
97*91f16700Schasinglulu	.word \_name\()_errata_list_end
98*91f16700Schasinglulu
99*91f16700Schasinglulu#if REPORT_ERRATA
100*91f16700Schasinglulu	.ifndef \_name\()_cpu_str
101*91f16700Schasinglulu	  /*
102*91f16700Schasinglulu	   * Place errata reported flag, and the spinlock to arbitrate access to
103*91f16700Schasinglulu	   * it in the data section.
104*91f16700Schasinglulu	   */
105*91f16700Schasinglulu	  .pushsection .data
106*91f16700Schasinglulu	  define_asm_spinlock \_name\()_errata_lock
107*91f16700Schasinglulu	  \_name\()_errata_reported:
108*91f16700Schasinglulu	  .word	0
109*91f16700Schasinglulu	  .popsection
110*91f16700Schasinglulu
111*91f16700Schasinglulu	  /* Place CPU string in rodata */
112*91f16700Schasinglulu	  .pushsection .rodata
113*91f16700Schasinglulu	  \_name\()_cpu_str:
114*91f16700Schasinglulu	  .asciz "\_name"
115*91f16700Schasinglulu	  .popsection
116*91f16700Schasinglulu	.endif
117*91f16700Schasinglulu
118*91f16700Schasinglulu	/*
119*91f16700Schasinglulu	 * Mandatory errata status printing function for CPUs of
120*91f16700Schasinglulu	 * this class.
121*91f16700Schasinglulu	 */
122*91f16700Schasinglulu	.word \_name\()_errata_report
123*91f16700Schasinglulu	.word \_name\()_cpu_str
124*91f16700Schasinglulu
125*91f16700Schasinglulu#ifdef IMAGE_BL32
126*91f16700Schasinglulu	/* Pointers to errata lock and reported flag */
127*91f16700Schasinglulu	.word \_name\()_errata_lock
128*91f16700Schasinglulu	.word \_name\()_errata_reported
129*91f16700Schasinglulu#endif
130*91f16700Schasinglulu#endif
131*91f16700Schasinglulu	.endm
132*91f16700Schasinglulu
133*91f16700Schasinglulu#if REPORT_ERRATA
134*91f16700Schasinglulu	/*
135*91f16700Schasinglulu	 * Print status of a CPU errata
136*91f16700Schasinglulu	 *
137*91f16700Schasinglulu	 * _chosen:
138*91f16700Schasinglulu	 *	Identifier indicating whether or not a CPU errata has been
139*91f16700Schasinglulu	 *	compiled in.
140*91f16700Schasinglulu	 * _cpu:
141*91f16700Schasinglulu	 *	Name of the CPU
142*91f16700Schasinglulu	 * _id:
143*91f16700Schasinglulu	 *	Errata identifier
144*91f16700Schasinglulu	 * _rev_var:
145*91f16700Schasinglulu	 *	Register containing the combined value CPU revision and variant
146*91f16700Schasinglulu	 *	- typically the return value of cpu_get_rev_var
147*91f16700Schasinglulu	 */
148*91f16700Schasinglulu	.macro report_errata _chosen, _cpu, _id, _rev_var=r4
149*91f16700Schasinglulu	/* Stash a string with errata ID */
150*91f16700Schasinglulu	.pushsection .rodata
151*91f16700Schasinglulu	\_cpu\()_errata_\_id\()_str:
152*91f16700Schasinglulu	.asciz	"\_id"
153*91f16700Schasinglulu	.popsection
154*91f16700Schasinglulu
155*91f16700Schasinglulu	/* Check whether errata applies */
156*91f16700Schasinglulu	mov	r0, \_rev_var
157*91f16700Schasinglulu	bl	check_errata_\_id
158*91f16700Schasinglulu
159*91f16700Schasinglulu	.ifeq \_chosen
160*91f16700Schasinglulu	/*
161*91f16700Schasinglulu	 * Errata workaround has not been compiled in. If the errata would have
162*91f16700Schasinglulu	 * applied had it been compiled in, print its status as missing.
163*91f16700Schasinglulu	 */
164*91f16700Schasinglulu	cmp	r0, #0
165*91f16700Schasinglulu	movne	r0, #ERRATA_MISSING
166*91f16700Schasinglulu	.endif
167*91f16700Schasinglulu	ldr	r1, =\_cpu\()_cpu_str
168*91f16700Schasinglulu	ldr	r2, =\_cpu\()_errata_\_id\()_str
169*91f16700Schasinglulu	bl	errata_print_msg
170*91f16700Schasinglulu	.endm
171*91f16700Schasinglulu#endif
172*91f16700Schasinglulu	/*
173*91f16700Schasinglulu	 * Helper macro that reads the part number of the current CPU and jumps
174*91f16700Schasinglulu	 * to the given label if it matches the CPU MIDR provided.
175*91f16700Schasinglulu	 *
176*91f16700Schasinglulu	 * Clobbers: r0-r1
177*91f16700Schasinglulu	 */
178*91f16700Schasinglulu	.macro  jump_if_cpu_midr _cpu_midr, _label
179*91f16700Schasinglulu	ldcopr	r0, MIDR
180*91f16700Schasinglulu	ubfx	r0, r0, #MIDR_PN_SHIFT, #12
181*91f16700Schasinglulu	ldr	r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
182*91f16700Schasinglulu	cmp	r0, r1
183*91f16700Schasinglulu	beq	\_label
184*91f16700Schasinglulu	.endm
185*91f16700Schasinglulu
186*91f16700Schasinglulu/*
187*91f16700Schasinglulu * NOTE an erratum and CVE id could clash. However, both numbers are very large
188*91f16700Schasinglulu * and the probablity is minuscule. Working around this makes code very
189*91f16700Schasinglulu * complicated and extremely difficult to read so it is not considered. In the
190*91f16700Schasinglulu * unlikely event that this does happen, prepending the CVE id with a 0 should
191*91f16700Schasinglulu * resolve the conflict
192*91f16700Schasinglulu */
193*91f16700Schasinglulu
194*91f16700Schasinglulu/*
195*91f16700Schasinglulu * Add an entry for this erratum to the errata framework
196*91f16700Schasinglulu *
197*91f16700Schasinglulu * _cpu:
198*91f16700Schasinglulu *	Name of cpu as given to declare_cpu_ops
199*91f16700Schasinglulu *
200*91f16700Schasinglulu * _cve:
201*91f16700Schasinglulu *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
202*91f16700Schasinglulu *
203*91f16700Schasinglulu * _id:
204*91f16700Schasinglulu *	Erratum or CVE number. Please combine with the previous field with the
205*91f16700Schasinglulu *	ERRATUM or CVE macros
206*91f16700Schasinglulu *
207*91f16700Schasinglulu * _chosen:
208*91f16700Schasinglulu *	Compile time flag on whether the erratum is included
209*91f16700Schasinglulu *
210*91f16700Schasinglulu * _special:
211*91f16700Schasinglulu *	The special non-standard name of an erratum
212*91f16700Schasinglulu */
213*91f16700Schasinglulu.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _special
214*91f16700Schasinglulu	.pushsection .rodata.errata_entries
215*91f16700Schasinglulu		.align	2
216*91f16700Schasinglulu		.ifndef \_cpu\()_errata_list_start
217*91f16700Schasinglulu		\_cpu\()_errata_list_start:
218*91f16700Schasinglulu		.endif
219*91f16700Schasinglulu
220*91f16700Schasinglulu		/* unused on AArch32, maintain for portability */
221*91f16700Schasinglulu		.word	0
222*91f16700Schasinglulu		/* TODO(errata ABI): this prevents all checker functions from
223*91f16700Schasinglulu		 * being optimised away. Can be done away with unless the ABI
224*91f16700Schasinglulu		 * needs them */
225*91f16700Schasinglulu		.ifnb \_special
226*91f16700Schasinglulu			.word	check_errata_\_special
227*91f16700Schasinglulu		.elseif \_cve
228*91f16700Schasinglulu			.word	check_errata_cve_\_cve\()_\_id
229*91f16700Schasinglulu		.else
230*91f16700Schasinglulu			.word	check_errata_\_id
231*91f16700Schasinglulu		.endif
232*91f16700Schasinglulu		/* Will fit CVEs with up to 10 character in the ID field */
233*91f16700Schasinglulu		.word	\_id
234*91f16700Schasinglulu		.hword	\_cve
235*91f16700Schasinglulu		.byte	\_chosen
236*91f16700Schasinglulu		/* TODO(errata ABI): mitigated field for known but unmitigated
237*91f16700Schasinglulu		 * errata*/
238*91f16700Schasinglulu		.byte	0x1
239*91f16700Schasinglulu	.popsection
240*91f16700Schasinglulu.endm
241*91f16700Schasinglulu
242*91f16700Schasinglulu/*
243*91f16700Schasinglulu * Maintain compatibility with the old scheme of "each cpu has its own reporter".
244*91f16700Schasinglulu * TODO remove entirely once all cpus have been converted. This includes the
245*91f16700Schasinglulu * cpu_ops entry, as print_errata_status can call this directly for all cpus
246*91f16700Schasinglulu */
247*91f16700Schasinglulu.macro errata_report_shim _cpu:req
248*91f16700Schasinglulu	#if REPORT_ERRATA
249*91f16700Schasinglulu	func \_cpu\()_errata_report
250*91f16700Schasinglulu		push	{r12, lr}
251*91f16700Schasinglulu
252*91f16700Schasinglulu		bl generic_errata_report
253*91f16700Schasinglulu
254*91f16700Schasinglulu		pop	{r12, lr}
255*91f16700Schasinglulu		bx	lr
256*91f16700Schasinglulu	endfunc \_cpu\()_errata_report
257*91f16700Schasinglulu	#endif
258*91f16700Schasinglulu.endm
259*91f16700Schasinglulu#endif /* CPU_MACROS_S */
260