xref: /rk3399_ARM-atf/include/lib/cpus/aarch64/cpu_macros.S (revision 3f4c1e1e7b976e6950cbcc4ddf8c32e989d837ac)
1add40351SSoby Mathew/*
2007433d8SBoyan Karatotev * Copyright (c) 2014-2023, ARM Limited and Contributors. All rights reserved.
3add40351SSoby Mathew *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
5add40351SSoby Mathew */
6c3cf06f1SAntonio Nino Diaz#ifndef CPU_MACROS_S
7c3cf06f1SAntonio Nino Diaz#define CPU_MACROS_S
8add40351SSoby Mathew
9ff6f62e1SAntonio Nino Diaz#include <assert_macros.S>
10007433d8SBoyan Karatotev#include <lib/cpus/cpu_ops.h>
116bb96fa6SBoyan Karatotev#include <lib/cpus/errata.h>
12add40351SSoby Mathew
13add40351SSoby Mathew	/*
145dd9dbb5SJeenu Viswambharan	 * Write given expressions as quad words
155dd9dbb5SJeenu Viswambharan	 *
165dd9dbb5SJeenu Viswambharan	 * _count:
175dd9dbb5SJeenu Viswambharan	 *	Write at least _count quad words. If the given number of
185dd9dbb5SJeenu Viswambharan	 *	expressions is less than _count, repeat the last expression to
195dd9dbb5SJeenu Viswambharan	 *	fill _count quad words in total
205dd9dbb5SJeenu Viswambharan	 * _rest:
215dd9dbb5SJeenu Viswambharan	 *	Optional list of expressions. _this is for parameter extraction
225dd9dbb5SJeenu Viswambharan	 *	only, and has no significance to the caller
235dd9dbb5SJeenu Viswambharan	 *
245dd9dbb5SJeenu Viswambharan	 * Invoked as:
255dd9dbb5SJeenu Viswambharan	 *	fill_constants 2, foo, bar, blah, ...
26add40351SSoby Mathew	 */
275dd9dbb5SJeenu Viswambharan	.macro fill_constants _count:req, _this, _rest:vararg
285dd9dbb5SJeenu Viswambharan	  .ifgt \_count
295dd9dbb5SJeenu Viswambharan	    /* Write the current expression */
305dd9dbb5SJeenu Viswambharan	    .ifb \_this
315dd9dbb5SJeenu Viswambharan	      .error "Nothing to fill"
325dd9dbb5SJeenu Viswambharan	    .endif
335dd9dbb5SJeenu Viswambharan	    .quad \_this
345dd9dbb5SJeenu Viswambharan
355dd9dbb5SJeenu Viswambharan	    /* Invoke recursively for remaining expressions */
365dd9dbb5SJeenu Viswambharan	    .ifnb \_rest
375dd9dbb5SJeenu Viswambharan	      fill_constants \_count-1, \_rest
385dd9dbb5SJeenu Viswambharan	    .else
395dd9dbb5SJeenu Viswambharan	      fill_constants \_count-1, \_this
405dd9dbb5SJeenu Viswambharan	    .endif
415dd9dbb5SJeenu Viswambharan	  .endif
425dd9dbb5SJeenu Viswambharan	.endm
435dd9dbb5SJeenu Viswambharan
445dd9dbb5SJeenu Viswambharan	/*
455dd9dbb5SJeenu Viswambharan	 * Declare CPU operations
465dd9dbb5SJeenu Viswambharan	 *
475dd9dbb5SJeenu Viswambharan	 * _name:
485dd9dbb5SJeenu Viswambharan	 *	Name of the CPU for which operations are being specified
495dd9dbb5SJeenu Viswambharan	 * _midr:
505dd9dbb5SJeenu Viswambharan	 *	Numeric value expected to read from CPU's MIDR
515dd9dbb5SJeenu Viswambharan	 * _resetfunc:
525dd9dbb5SJeenu Viswambharan	 *	Reset function for the CPU. If there's no CPU reset function,
535dd9dbb5SJeenu Viswambharan	 *	specify CPU_NO_RESET_FUNC
54a205a56eSDimitris Papastamos	 * _extra1:
55a205a56eSDimitris Papastamos	 *	This is a placeholder for future per CPU operations.  Currently,
56a205a56eSDimitris Papastamos	 *	some CPUs use this entry to set a test function to determine if
57a205a56eSDimitris Papastamos	 *	the workaround for CVE-2017-5715 needs to be applied or not.
58fe007b2eSDimitris Papastamos	 * _extra2:
59fe007b2eSDimitris Papastamos	 *	This is a placeholder for future per CPU operations. Currently
60fe007b2eSDimitris Papastamos	 *	some CPUs use this entry to set a function to disable the
61fe007b2eSDimitris Papastamos	 *	workaround for CVE-2018-3639.
629b2510b6SBipin Ravi	 * _extra3:
639b2510b6SBipin Ravi	 *	This is a placeholder for future per CPU operations. Currently,
649b2510b6SBipin Ravi	 *	some CPUs use this entry to set a test function to determine if
659b2510b6SBipin Ravi	 *	the workaround for CVE-2022-23960 needs to be applied or not.
6680942622Slaurenw-arm	 * _e_handler:
6780942622Slaurenw-arm	 *	This is a placeholder for future per CPU exception handlers.
685dd9dbb5SJeenu Viswambharan	 * _power_down_ops:
695dd9dbb5SJeenu Viswambharan	 *	Comma-separated list of functions to perform power-down
705dd9dbb5SJeenu Viswambharan	 *	operatios on the CPU. At least one, and up to
715dd9dbb5SJeenu Viswambharan	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
725dd9dbb5SJeenu Viswambharan	 *	Starting at power level 0, these functions shall handle power
735dd9dbb5SJeenu Viswambharan	 *	down at subsequent power levels. If there aren't exactly
745dd9dbb5SJeenu Viswambharan	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
755dd9dbb5SJeenu Viswambharan	 *	used to handle power down at subsequent levels
765dd9dbb5SJeenu Viswambharan	 */
77a205a56eSDimitris Papastamos	.macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \
789b2510b6SBipin Ravi		_extra1:req, _extra2:req, _extra3:req, _e_handler:req, _power_down_ops:vararg
79da04341eSChris Kay	.section .cpu_ops, "a"
805dd9dbb5SJeenu Viswambharan	.align 3
81add40351SSoby Mathew	.type cpu_ops_\_name, %object
82add40351SSoby Mathew	.quad \_midr
83b1d27b48SRoberto Vargas#if defined(IMAGE_AT_EL3)
845dd9dbb5SJeenu Viswambharan	.quad \_resetfunc
85add40351SSoby Mathew#endif
86a205a56eSDimitris Papastamos	.quad \_extra1
87fe007b2eSDimitris Papastamos	.quad \_extra2
889b2510b6SBipin Ravi	.quad \_extra3
8980942622Slaurenw-arm	.quad \_e_handler
903d8256b2SMasahiro Yamada#ifdef IMAGE_BL31
915dd9dbb5SJeenu Viswambharan	/* Insert list of functions */
925dd9dbb5SJeenu Viswambharan	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
93add40351SSoby Mathew#endif
94*3f4c1e1eSBoyan Karatotev	/*
95*3f4c1e1eSBoyan Karatotev	 * It is possible (although unlikely) that a cpu may have no errata in
96*3f4c1e1eSBoyan Karatotev	 * code. In that case the start label will not be defined. The list is
97*3f4c1e1eSBoyan Karatotev	 * intended to be used in a loop, so define it as zero-length for
98*3f4c1e1eSBoyan Karatotev	 * predictable behaviour. Since this macro is always called at the end
99*3f4c1e1eSBoyan Karatotev	 * of the cpu file (after all errata have been parsed) we can be sure
100*3f4c1e1eSBoyan Karatotev	 * that we are at the end of the list. Some cpus call declare_cpu_ops
101*3f4c1e1eSBoyan Karatotev	 * twice, so only do this once.
102*3f4c1e1eSBoyan Karatotev	 */
103*3f4c1e1eSBoyan Karatotev	.pushsection .rodata.errata_entries
104*3f4c1e1eSBoyan Karatotev	.ifndef \_name\()_errata_list_start
105*3f4c1e1eSBoyan Karatotev		\_name\()_errata_list_start:
106*3f4c1e1eSBoyan Karatotev	.endif
107*3f4c1e1eSBoyan Karatotev	.ifndef \_name\()_errata_list_end
108*3f4c1e1eSBoyan Karatotev		\_name\()_errata_list_end:
109*3f4c1e1eSBoyan Karatotev	.endif
110*3f4c1e1eSBoyan Karatotev	.popsection
111*3f4c1e1eSBoyan Karatotev
112*3f4c1e1eSBoyan Karatotev	/* and now put them in cpu_ops */
113*3f4c1e1eSBoyan Karatotev	.quad \_name\()_errata_list_start
114*3f4c1e1eSBoyan Karatotev	.quad \_name\()_errata_list_end
11510bcd761SJeenu Viswambharan
11610bcd761SJeenu Viswambharan#if REPORT_ERRATA
11710bcd761SJeenu Viswambharan	.ifndef \_name\()_cpu_str
11810bcd761SJeenu Viswambharan	  /*
11910bcd761SJeenu Viswambharan	   * Place errata reported flag, and the spinlock to arbitrate access to
12010bcd761SJeenu Viswambharan	   * it in the data section.
12110bcd761SJeenu Viswambharan	   */
12210bcd761SJeenu Viswambharan	  .pushsection .data
12310bcd761SJeenu Viswambharan	  define_asm_spinlock \_name\()_errata_lock
12410bcd761SJeenu Viswambharan	  \_name\()_errata_reported:
12510bcd761SJeenu Viswambharan	  .word	0
12610bcd761SJeenu Viswambharan	  .popsection
12710bcd761SJeenu Viswambharan
12810bcd761SJeenu Viswambharan	  /* Place CPU string in rodata */
12910bcd761SJeenu Viswambharan	  .pushsection .rodata
13010bcd761SJeenu Viswambharan	  \_name\()_cpu_str:
13110bcd761SJeenu Viswambharan	  .asciz "\_name"
13210bcd761SJeenu Viswambharan	  .popsection
13310bcd761SJeenu Viswambharan	.endif
13410bcd761SJeenu Viswambharan
135*3f4c1e1eSBoyan Karatotev
13610bcd761SJeenu Viswambharan	/*
13712af5ed4SSoby Mathew	 * Mandatory errata status printing function for CPUs of
13810bcd761SJeenu Viswambharan	 * this class.
13910bcd761SJeenu Viswambharan	 */
14010bcd761SJeenu Viswambharan	.quad \_name\()_errata_report
141*3f4c1e1eSBoyan Karatotev	.quad \_name\()_cpu_str
14210bcd761SJeenu Viswambharan
14310bcd761SJeenu Viswambharan#ifdef IMAGE_BL31
14410bcd761SJeenu Viswambharan	/* Pointers to errata lock and reported flag */
14510bcd761SJeenu Viswambharan	.quad \_name\()_errata_lock
14610bcd761SJeenu Viswambharan	.quad \_name\()_errata_reported
147*3f4c1e1eSBoyan Karatotev#endif /* IMAGE_BL31 */
148*3f4c1e1eSBoyan Karatotev#endif /* REPORT_ERRATA */
14910bcd761SJeenu Viswambharan
1503d8256b2SMasahiro Yamada#if defined(IMAGE_BL31) && CRASH_REPORTING
151d3f70af6SSoby Mathew	.quad \_name\()_cpu_reg_dump
152d3f70af6SSoby Mathew#endif
153add40351SSoby Mathew	.endm
154e2bf57f8SDan Handley
155a205a56eSDimitris Papastamos	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
156a205a56eSDimitris Papastamos		_power_down_ops:vararg
1579b2510b6SBipin Ravi		declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, \
158a205a56eSDimitris Papastamos			\_power_down_ops
159a205a56eSDimitris Papastamos	.endm
160a205a56eSDimitris Papastamos
16180942622Slaurenw-arm	.macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \
16280942622Slaurenw-arm		_e_handler:req, _power_down_ops:vararg
16380942622Slaurenw-arm		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
1649b2510b6SBipin Ravi			0, 0, 0, \_e_handler, \_power_down_ops
16580942622Slaurenw-arm	.endm
16680942622Slaurenw-arm
167fe007b2eSDimitris Papastamos	.macro declare_cpu_ops_wa _name:req, _midr:req, \
168fe007b2eSDimitris Papastamos		_resetfunc:req, _extra1:req, _extra2:req, \
1699b2510b6SBipin Ravi		_extra3:req, _power_down_ops:vararg
170a205a56eSDimitris Papastamos		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
1719b2510b6SBipin Ravi			\_extra1, \_extra2, \_extra3, 0, \_power_down_ops
172a205a56eSDimitris Papastamos	.endm
173a205a56eSDimitris Papastamos
174*3f4c1e1eSBoyan Karatotev/* TODO can be deleted once all CPUs have been converted */
17510bcd761SJeenu Viswambharan#if REPORT_ERRATA
17610bcd761SJeenu Viswambharan	/*
17710bcd761SJeenu Viswambharan	 * Print status of a CPU errata
17810bcd761SJeenu Viswambharan	 *
17910bcd761SJeenu Viswambharan	 * _chosen:
18010bcd761SJeenu Viswambharan	 *	Identifier indicating whether or not a CPU errata has been
18110bcd761SJeenu Viswambharan	 *	compiled in.
18210bcd761SJeenu Viswambharan	 * _cpu:
18310bcd761SJeenu Viswambharan	 *	Name of the CPU
18410bcd761SJeenu Viswambharan	 * _id:
18510bcd761SJeenu Viswambharan	 *	Errata identifier
18610bcd761SJeenu Viswambharan	 * _rev_var:
18710bcd761SJeenu Viswambharan	 *	Register containing the combined value CPU revision and variant
18810bcd761SJeenu Viswambharan	 *	- typically the return value of cpu_get_rev_var
18910bcd761SJeenu Viswambharan	 */
19010bcd761SJeenu Viswambharan	.macro report_errata _chosen, _cpu, _id, _rev_var=x8
19110bcd761SJeenu Viswambharan	/* Stash a string with errata ID */
19210bcd761SJeenu Viswambharan	.pushsection .rodata
19310bcd761SJeenu Viswambharan	\_cpu\()_errata_\_id\()_str:
19410bcd761SJeenu Viswambharan	.asciz	"\_id"
19510bcd761SJeenu Viswambharan	.popsection
19610bcd761SJeenu Viswambharan
19710bcd761SJeenu Viswambharan	/* Check whether errata applies */
19810bcd761SJeenu Viswambharan	mov	x0, \_rev_var
1999ec3921cSJonathan Wright	/* Shall clobber: x0-x7 */
20010bcd761SJeenu Viswambharan	bl	check_errata_\_id
20110bcd761SJeenu Viswambharan
20210bcd761SJeenu Viswambharan	.ifeq \_chosen
20310bcd761SJeenu Viswambharan	/*
20410bcd761SJeenu Viswambharan	 * Errata workaround has not been compiled in. If the errata would have
20510bcd761SJeenu Viswambharan	 * applied had it been compiled in, print its status as missing.
20610bcd761SJeenu Viswambharan	 */
20710bcd761SJeenu Viswambharan	cbz	x0, 900f
20810bcd761SJeenu Viswambharan	mov	x0, #ERRATA_MISSING
20910bcd761SJeenu Viswambharan	.endif
21010bcd761SJeenu Viswambharan900:
21110bcd761SJeenu Viswambharan	adr	x1, \_cpu\()_cpu_str
21210bcd761SJeenu Viswambharan	adr	x2, \_cpu\()_errata_\_id\()_str
21310bcd761SJeenu Viswambharan	bl	errata_print_msg
21410bcd761SJeenu Viswambharan	.endm
21510bcd761SJeenu Viswambharan#endif
21610bcd761SJeenu Viswambharan
2173991a6a4SDimitris Papastamos	/*
2183991a6a4SDimitris Papastamos	 * This macro is used on some CPUs to detect if they are vulnerable
2193991a6a4SDimitris Papastamos	 * to CVE-2017-5715.
2203991a6a4SDimitris Papastamos	 */
2213991a6a4SDimitris Papastamos	.macro	cpu_check_csv2 _reg _label
2223991a6a4SDimitris Papastamos	mrs	\_reg, id_aa64pfr0_el1
2233991a6a4SDimitris Papastamos	ubfx	\_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH
2243991a6a4SDimitris Papastamos	/*
225ff6f62e1SAntonio Nino Diaz	 * If the field equals 1, branch targets trained in one context cannot
226ff6f62e1SAntonio Nino Diaz	 * affect speculative execution in a different context.
227ff6f62e1SAntonio Nino Diaz	 *
228ff6f62e1SAntonio Nino Diaz	 * If the field equals 2, it means that the system is also aware of
229ff6f62e1SAntonio Nino Diaz	 * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we
230ff6f62e1SAntonio Nino Diaz	 * expect users of the registers to do the right thing.
231ff6f62e1SAntonio Nino Diaz	 *
232ff6f62e1SAntonio Nino Diaz	 * Only apply mitigations if the value of this field is 0.
2333991a6a4SDimitris Papastamos	 */
234ff6f62e1SAntonio Nino Diaz#if ENABLE_ASSERTIONS
235ff6f62e1SAntonio Nino Diaz	cmp	\_reg, #3 /* Only values 0 to 2 are expected */
236ff6f62e1SAntonio Nino Diaz	ASM_ASSERT(lo)
237ff6f62e1SAntonio Nino Diaz#endif
238ff6f62e1SAntonio Nino Diaz
239ff6f62e1SAntonio Nino Diaz	cmp	\_reg, #0
240ff6f62e1SAntonio Nino Diaz	bne	\_label
2413991a6a4SDimitris Papastamos	.endm
242da3b038fSDeepak Pandey
243da3b038fSDeepak Pandey	/*
244da3b038fSDeepak Pandey	 * Helper macro that reads the part number of the current
245da3b038fSDeepak Pandey	 * CPU and jumps to the given label if it matches the CPU
246da3b038fSDeepak Pandey	 * MIDR provided.
247da3b038fSDeepak Pandey	 *
248da3b038fSDeepak Pandey	 * Clobbers x0.
249da3b038fSDeepak Pandey	 */
250da3b038fSDeepak Pandey	.macro  jump_if_cpu_midr _cpu_midr, _label
251da3b038fSDeepak Pandey	mrs	x0, midr_el1
252da3b038fSDeepak Pandey	ubfx	x0, x0, MIDR_PN_SHIFT, #12
253da3b038fSDeepak Pandey	cmp	w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
254da3b038fSDeepak Pandey	b.eq	\_label
255da3b038fSDeepak Pandey	.endm
256c3cf06f1SAntonio Nino Diaz
257*3f4c1e1eSBoyan Karatotev
258*3f4c1e1eSBoyan Karatotev/*
259*3f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata
260*3f4c1e1eSBoyan Karatotev * will be applied automatically
261*3f4c1e1eSBoyan Karatotev *
262*3f4c1e1eSBoyan Karatotev * _cpu:
263*3f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
264*3f4c1e1eSBoyan Karatotev *
265*3f4c1e1eSBoyan Karatotev * _cve:
266*3f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
267*3f4c1e1eSBoyan Karatotev *
268*3f4c1e1eSBoyan Karatotev * _id:
269*3f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
270*3f4c1e1eSBoyan Karatotev *	or CVE macros
271*3f4c1e1eSBoyan Karatotev *
272*3f4c1e1eSBoyan Karatotev * _chosen:
273*3f4c1e1eSBoyan Karatotev *	Compile time flag on whether the erratum is included
274*3f4c1e1eSBoyan Karatotev *
275*3f4c1e1eSBoyan Karatotev * _apply_at_reset:
276*3f4c1e1eSBoyan Karatotev *	Whether the erratum should be automatically applied at reset
277*3f4c1e1eSBoyan Karatotev */
278*3f4c1e1eSBoyan Karatotev.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
279*3f4c1e1eSBoyan Karatotev	.pushsection .rodata.errata_entries
280*3f4c1e1eSBoyan Karatotev		.align	3
281*3f4c1e1eSBoyan Karatotev		.ifndef \_cpu\()_errata_list_start
282*3f4c1e1eSBoyan Karatotev		\_cpu\()_errata_list_start:
283*3f4c1e1eSBoyan Karatotev		.endif
284*3f4c1e1eSBoyan Karatotev
285*3f4c1e1eSBoyan Karatotev		/* check if unused and compile out if no references */
286*3f4c1e1eSBoyan Karatotev		.if \_apply_at_reset && \_chosen
287*3f4c1e1eSBoyan Karatotev			.quad	erratum_\_cpu\()_\_id\()_wa
288*3f4c1e1eSBoyan Karatotev		.else
289*3f4c1e1eSBoyan Karatotev			.quad	0
290*3f4c1e1eSBoyan Karatotev		.endif
291*3f4c1e1eSBoyan Karatotev		/* TODO(errata ABI): this prevents all checker functions from
292*3f4c1e1eSBoyan Karatotev		 * being optimised away. Can be done away with unless the ABI
293*3f4c1e1eSBoyan Karatotev		 * needs them */
294*3f4c1e1eSBoyan Karatotev		.quad	check_erratum_\_cpu\()_\_id
295*3f4c1e1eSBoyan Karatotev		/* Will fit CVEs with up to 10 character in the ID field */
296*3f4c1e1eSBoyan Karatotev		.word	\_id
297*3f4c1e1eSBoyan Karatotev		.hword	\_cve
298*3f4c1e1eSBoyan Karatotev		.byte	\_chosen
299*3f4c1e1eSBoyan Karatotev		/* TODO(errata ABI): mitigated field for known but unmitigated
300*3f4c1e1eSBoyan Karatotev		 * errata */
301*3f4c1e1eSBoyan Karatotev		.byte	0x1
302*3f4c1e1eSBoyan Karatotev	.popsection
303*3f4c1e1eSBoyan Karatotev.endm
304*3f4c1e1eSBoyan Karatotev
305*3f4c1e1eSBoyan Karatotev.macro _workaround_start _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
306*3f4c1e1eSBoyan Karatotev	add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_apply_at_reset
307*3f4c1e1eSBoyan Karatotev
308*3f4c1e1eSBoyan Karatotev	func erratum_\_cpu\()_\_id\()_wa
309*3f4c1e1eSBoyan Karatotev		mov	x8, x30
310*3f4c1e1eSBoyan Karatotev
311*3f4c1e1eSBoyan Karatotev		/* save rev_var for workarounds that might need it but don't
312*3f4c1e1eSBoyan Karatotev		 * restore to x0 because few will care */
313*3f4c1e1eSBoyan Karatotev		mov	x7, x0
314*3f4c1e1eSBoyan Karatotev		bl	check_erratum_\_cpu\()_\_id
315*3f4c1e1eSBoyan Karatotev		cbz	x0, erratum_\_cpu\()_\_id\()_skip
316*3f4c1e1eSBoyan Karatotev.endm
317*3f4c1e1eSBoyan Karatotev
318*3f4c1e1eSBoyan Karatotev.macro _workaround_end _cpu:req, _id:req
319*3f4c1e1eSBoyan Karatotev	erratum_\_cpu\()_\_id\()_skip:
320*3f4c1e1eSBoyan Karatotev		ret	x8
321*3f4c1e1eSBoyan Karatotev	endfunc erratum_\_cpu\()_\_id\()_wa
322*3f4c1e1eSBoyan Karatotev.endm
323*3f4c1e1eSBoyan Karatotev
324*3f4c1e1eSBoyan Karatotev/*******************************************************************************
325*3f4c1e1eSBoyan Karatotev * Errata workaround wrappers
326*3f4c1e1eSBoyan Karatotev ******************************************************************************/
327*3f4c1e1eSBoyan Karatotev/*
328*3f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata
329*3f4c1e1eSBoyan Karatotev * will be applied automatically
330*3f4c1e1eSBoyan Karatotev *
331*3f4c1e1eSBoyan Karatotev * _cpu:
332*3f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
333*3f4c1e1eSBoyan Karatotev *
334*3f4c1e1eSBoyan Karatotev * _cve:
335*3f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
336*3f4c1e1eSBoyan Karatotev *
337*3f4c1e1eSBoyan Karatotev * _id:
338*3f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
339*3f4c1e1eSBoyan Karatotev *	or CVE macros
340*3f4c1e1eSBoyan Karatotev *
341*3f4c1e1eSBoyan Karatotev * _chosen:
342*3f4c1e1eSBoyan Karatotev *	Compile time flag on whether the erratum is included
343*3f4c1e1eSBoyan Karatotev *
344*3f4c1e1eSBoyan Karatotev * in body:
345*3f4c1e1eSBoyan Karatotev *	clobber x0 to x7 (please only use those)
346*3f4c1e1eSBoyan Karatotev *	argument x7 - cpu_rev_var
347*3f4c1e1eSBoyan Karatotev *
348*3f4c1e1eSBoyan Karatotev * _wa clobbers: x0-x8 (PCS compliant)
349*3f4c1e1eSBoyan Karatotev */
350*3f4c1e1eSBoyan Karatotev.macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req
351*3f4c1e1eSBoyan Karatotev	_workaround_start \_cpu, \_cve, \_id, \_chosen, 1
352*3f4c1e1eSBoyan Karatotev.endm
353*3f4c1e1eSBoyan Karatotev
354*3f4c1e1eSBoyan Karatotev/*
355*3f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. Additional arguments:
356*3f4c1e1eSBoyan Karatotev *
357*3f4c1e1eSBoyan Karatotev * _midr:
358*3f4c1e1eSBoyan Karatotev *	Check if CPU's MIDR matches the CPU it's meant for. Must be specified
359*3f4c1e1eSBoyan Karatotev *	for errata applied in generic code
360*3f4c1e1eSBoyan Karatotev */
361*3f4c1e1eSBoyan Karatotev.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr
362*3f4c1e1eSBoyan Karatotev	/*
363*3f4c1e1eSBoyan Karatotev	 * Let errata specify if they need MIDR checking. Sadly, storing the
364*3f4c1e1eSBoyan Karatotev	 * MIDR in an .equ to retrieve automatically blows up as it stores some
365*3f4c1e1eSBoyan Karatotev	 * brackets in the symbol
366*3f4c1e1eSBoyan Karatotev	 */
367*3f4c1e1eSBoyan Karatotev	.ifnb \_midr
368*3f4c1e1eSBoyan Karatotev		jump_if_cpu_midr \_midr, 1f
369*3f4c1e1eSBoyan Karatotev		b	erratum_\_cpu\()_\_id\()_skip
370*3f4c1e1eSBoyan Karatotev
371*3f4c1e1eSBoyan Karatotev		1:
372*3f4c1e1eSBoyan Karatotev	.endif
373*3f4c1e1eSBoyan Karatotev	_workaround_start \_cpu, \_cve, \_id, \_chosen, 0
374*3f4c1e1eSBoyan Karatotev.endm
375*3f4c1e1eSBoyan Karatotev
376*3f4c1e1eSBoyan Karatotev/*
377*3f4c1e1eSBoyan Karatotev * Usage and arguments identical to `workaround_reset_start`. The _cve argument
378*3f4c1e1eSBoyan Karatotev * is kept here so the same #define can be used as that macro
379*3f4c1e1eSBoyan Karatotev */
380*3f4c1e1eSBoyan Karatotev.macro workaround_reset_end _cpu:req, _cve:req, _id:req
381*3f4c1e1eSBoyan Karatotev	_workaround_end \_cpu, \_id
382*3f4c1e1eSBoyan Karatotev.endm
383*3f4c1e1eSBoyan Karatotev
384*3f4c1e1eSBoyan Karatotev/*
385*3f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. The _cve argument is kept here
386*3f4c1e1eSBoyan Karatotev * so the same #define can be used as that macro. Additional arguments:
387*3f4c1e1eSBoyan Karatotev *
388*3f4c1e1eSBoyan Karatotev * _no_isb:
389*3f4c1e1eSBoyan Karatotev *	Optionally do not include the trailing isb. Please disable with the
390*3f4c1e1eSBoyan Karatotev *	NO_ISB macro
391*3f4c1e1eSBoyan Karatotev */
392*3f4c1e1eSBoyan Karatotev.macro workaround_runtime_end _cpu:req, _cve:req, _id:req, _no_isb
393*3f4c1e1eSBoyan Karatotev	/*
394*3f4c1e1eSBoyan Karatotev	 * Runtime errata do not have a reset function to call the isb for them
395*3f4c1e1eSBoyan Karatotev	 * and missing the isb could be very problematic. It is also likely as
396*3f4c1e1eSBoyan Karatotev	 * they tend to be scattered in generic code.
397*3f4c1e1eSBoyan Karatotev	 */
398*3f4c1e1eSBoyan Karatotev	.ifb \_no_isb
399*3f4c1e1eSBoyan Karatotev		isb
400*3f4c1e1eSBoyan Karatotev	.endif
401*3f4c1e1eSBoyan Karatotev	_workaround_end \_cpu, \_id
402*3f4c1e1eSBoyan Karatotev.endm
403*3f4c1e1eSBoyan Karatotev
404*3f4c1e1eSBoyan Karatotev/*******************************************************************************
405*3f4c1e1eSBoyan Karatotev * Errata workaround helpers
406*3f4c1e1eSBoyan Karatotev ******************************************************************************/
407*3f4c1e1eSBoyan Karatotev/*
408*3f4c1e1eSBoyan Karatotev * Set a bit in a system register. Can set multiple bits but is limited by the
409*3f4c1e1eSBoyan Karatotev *  way the ORR instruction encodes them.
410*3f4c1e1eSBoyan Karatotev *
411*3f4c1e1eSBoyan Karatotev * _reg:
412*3f4c1e1eSBoyan Karatotev *	Register to write to
413*3f4c1e1eSBoyan Karatotev *
414*3f4c1e1eSBoyan Karatotev * _bit:
415*3f4c1e1eSBoyan Karatotev *	Bit to set. Please use a descriptive #define
416*3f4c1e1eSBoyan Karatotev *
417*3f4c1e1eSBoyan Karatotev * _assert:
418*3f4c1e1eSBoyan Karatotev *	Optionally whether to read back and assert that the bit has been
419*3f4c1e1eSBoyan Karatotev *	written. Please disable with NO_ASSERT macro
420*3f4c1e1eSBoyan Karatotev *
421*3f4c1e1eSBoyan Karatotev * clobbers: x1
422*3f4c1e1eSBoyan Karatotev */
423*3f4c1e1eSBoyan Karatotev.macro sysreg_bit_set _reg:req, _bit:req, _assert=1
424*3f4c1e1eSBoyan Karatotev	mrs	x1, \_reg
425*3f4c1e1eSBoyan Karatotev	orr	x1, x1, #\_bit
426*3f4c1e1eSBoyan Karatotev	msr	\_reg, x1
427*3f4c1e1eSBoyan Karatotev.endm
428*3f4c1e1eSBoyan Karatotev
429*3f4c1e1eSBoyan Karatotev/*
430*3f4c1e1eSBoyan Karatotev * Apply erratum
431*3f4c1e1eSBoyan Karatotev *
432*3f4c1e1eSBoyan Karatotev * _cpu:
433*3f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
434*3f4c1e1eSBoyan Karatotev *
435*3f4c1e1eSBoyan Karatotev * _cve:
436*3f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
437*3f4c1e1eSBoyan Karatotev *
438*3f4c1e1eSBoyan Karatotev * _id:
439*3f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
440*3f4c1e1eSBoyan Karatotev *	or CVE macros
441*3f4c1e1eSBoyan Karatotev *
442*3f4c1e1eSBoyan Karatotev * _chosen:
443*3f4c1e1eSBoyan Karatotev *	Compile time flag on whether the erratum is included
444*3f4c1e1eSBoyan Karatotev *
445*3f4c1e1eSBoyan Karatotev * clobbers: x0-x9 (PCS compliant)
446*3f4c1e1eSBoyan Karatotev */
447*3f4c1e1eSBoyan Karatotev.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req
448*3f4c1e1eSBoyan Karatotev	.if \_chosen
449*3f4c1e1eSBoyan Karatotev		mov	x9, x30
450*3f4c1e1eSBoyan Karatotev		bl	cpu_get_rev_var
451*3f4c1e1eSBoyan Karatotev		bl	erratum_\_cpu\()_\_id\()_wa
452*3f4c1e1eSBoyan Karatotev		mov	x30, x9
453*3f4c1e1eSBoyan Karatotev
454*3f4c1e1eSBoyan Karatotev	.endif
455*3f4c1e1eSBoyan Karatotev.endm
456*3f4c1e1eSBoyan Karatotev
457*3f4c1e1eSBoyan Karatotev/*
458*3f4c1e1eSBoyan Karatotev * Helpers to select which revisions errata apply to. Don't leave a link
459*3f4c1e1eSBoyan Karatotev * register as the cpu_rev_var_*** will call the ret and we can save on one.
460*3f4c1e1eSBoyan Karatotev *
461*3f4c1e1eSBoyan Karatotev * _cpu:
462*3f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
463*3f4c1e1eSBoyan Karatotev *
464*3f4c1e1eSBoyan Karatotev * _cve:
465*3f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
466*3f4c1e1eSBoyan Karatotev *
467*3f4c1e1eSBoyan Karatotev * _id:
468*3f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
469*3f4c1e1eSBoyan Karatotev *	or CVE macros
470*3f4c1e1eSBoyan Karatotev *
471*3f4c1e1eSBoyan Karatotev * _rev_num:
472*3f4c1e1eSBoyan Karatotev *	Revision to apply to
473*3f4c1e1eSBoyan Karatotev *
474*3f4c1e1eSBoyan Karatotev * in body:
475*3f4c1e1eSBoyan Karatotev *	clobber: x0 to x4
476*3f4c1e1eSBoyan Karatotev *	argument: x0 - cpu_rev_var
477*3f4c1e1eSBoyan Karatotev */
478*3f4c1e1eSBoyan Karatotev.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req
479*3f4c1e1eSBoyan Karatotev	func check_erratum_\_cpu\()_\_id
480*3f4c1e1eSBoyan Karatotev		mov	x1, #\_rev_num
481*3f4c1e1eSBoyan Karatotev		b	cpu_rev_var_ls
482*3f4c1e1eSBoyan Karatotev	endfunc check_erratum_\_cpu\()_\_id
483*3f4c1e1eSBoyan Karatotev.endm
484*3f4c1e1eSBoyan Karatotev
485*3f4c1e1eSBoyan Karatotev.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req
486*3f4c1e1eSBoyan Karatotev	func check_erratum_\_cpu\()_\_id
487*3f4c1e1eSBoyan Karatotev		mov	x1, #\_rev_num
488*3f4c1e1eSBoyan Karatotev		b	cpu_rev_var_hs
489*3f4c1e1eSBoyan Karatotev	endfunc check_erratum_\_cpu\()_\_id
490*3f4c1e1eSBoyan Karatotev.endm
491*3f4c1e1eSBoyan Karatotev
492*3f4c1e1eSBoyan Karatotev.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req
493*3f4c1e1eSBoyan Karatotev	func check_erratum_\_cpu\()_\_id
494*3f4c1e1eSBoyan Karatotev		mov	x1, #\_rev_num_lo
495*3f4c1e1eSBoyan Karatotev		mov	x2, #\_rev_num_hi
496*3f4c1e1eSBoyan Karatotev		b	cpu_rev_var_range
497*3f4c1e1eSBoyan Karatotev	endfunc check_erratum_\_cpu\()_\_id
498*3f4c1e1eSBoyan Karatotev.endm
499*3f4c1e1eSBoyan Karatotev
500*3f4c1e1eSBoyan Karatotev/*******************************************************************************
501*3f4c1e1eSBoyan Karatotev * CPU reset function wrapper
502*3f4c1e1eSBoyan Karatotev ******************************************************************************/
503*3f4c1e1eSBoyan Karatotev
504*3f4c1e1eSBoyan Karatotev/*
505*3f4c1e1eSBoyan Karatotev * Wrapper to automatically apply all reset-time errata. Will end with an isb.
506*3f4c1e1eSBoyan Karatotev *
507*3f4c1e1eSBoyan Karatotev * _cpu:
508*3f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
509*3f4c1e1eSBoyan Karatotev *
510*3f4c1e1eSBoyan Karatotev * in body:
511*3f4c1e1eSBoyan Karatotev *	clobber x8 to x14
512*3f4c1e1eSBoyan Karatotev *	argument x14 - cpu_rev_var
513*3f4c1e1eSBoyan Karatotev */
514*3f4c1e1eSBoyan Karatotev.macro cpu_reset_func_start _cpu:req
515*3f4c1e1eSBoyan Karatotev	func \_cpu\()_reset_func
516*3f4c1e1eSBoyan Karatotev		mov	x15, x30
517*3f4c1e1eSBoyan Karatotev		bl	cpu_get_rev_var
518*3f4c1e1eSBoyan Karatotev		mov	x14, x0
519*3f4c1e1eSBoyan Karatotev
520*3f4c1e1eSBoyan Karatotev		/* short circuit the location to avoid searching the list */
521*3f4c1e1eSBoyan Karatotev		adrp	x12, \_cpu\()_errata_list_start
522*3f4c1e1eSBoyan Karatotev		add	x12, x12, :lo12:\_cpu\()_errata_list_start
523*3f4c1e1eSBoyan Karatotev		adrp	x13, \_cpu\()_errata_list_end
524*3f4c1e1eSBoyan Karatotev		add	x13, x13, :lo12:\_cpu\()_errata_list_end
525*3f4c1e1eSBoyan Karatotev
526*3f4c1e1eSBoyan Karatotev	errata_begin:
527*3f4c1e1eSBoyan Karatotev		/* if head catches up with end of list, exit */
528*3f4c1e1eSBoyan Karatotev		cmp	x12, x13
529*3f4c1e1eSBoyan Karatotev		b.eq	errata_end
530*3f4c1e1eSBoyan Karatotev
531*3f4c1e1eSBoyan Karatotev		ldr	x10, [x12, #ERRATUM_WA_FUNC]
532*3f4c1e1eSBoyan Karatotev		/* TODO(errata ABI): check mitigated and checker function fields
533*3f4c1e1eSBoyan Karatotev		 * for 0 */
534*3f4c1e1eSBoyan Karatotev		ldrb	w11, [x12, #ERRATUM_CHOSEN]
535*3f4c1e1eSBoyan Karatotev
536*3f4c1e1eSBoyan Karatotev		/* skip if not chosen */
537*3f4c1e1eSBoyan Karatotev		cbz	x11, 1f
538*3f4c1e1eSBoyan Karatotev		/* skip if runtime erratum */
539*3f4c1e1eSBoyan Karatotev		cbz	x10, 1f
540*3f4c1e1eSBoyan Karatotev
541*3f4c1e1eSBoyan Karatotev		/* put cpu revision in x0 and call workaround */
542*3f4c1e1eSBoyan Karatotev		mov	x0, x14
543*3f4c1e1eSBoyan Karatotev		blr	x10
544*3f4c1e1eSBoyan Karatotev	1:
545*3f4c1e1eSBoyan Karatotev		add	x12, x12, #ERRATUM_ENTRY_SIZE
546*3f4c1e1eSBoyan Karatotev		b	errata_begin
547*3f4c1e1eSBoyan Karatotev	errata_end:
548*3f4c1e1eSBoyan Karatotev.endm
549*3f4c1e1eSBoyan Karatotev
550*3f4c1e1eSBoyan Karatotev.macro cpu_reset_func_end _cpu:req
551*3f4c1e1eSBoyan Karatotev		isb
552*3f4c1e1eSBoyan Karatotev		ret	x15
553*3f4c1e1eSBoyan Karatotev	endfunc \_cpu\()_reset_func
554*3f4c1e1eSBoyan Karatotev.endm
555c3cf06f1SAntonio Nino Diaz#endif /* CPU_MACROS_S */
556