xref: /rk3399_ARM-atf/include/lib/cpus/aarch64/cpu_macros.S (revision 2b43216593f10ca55ba64d4990d1079083448835)
1add40351SSoby Mathew/*
2bb801857SBoyan Karatotev * Copyright (c) 2014-2025, 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:
520d020822SBoyan Karatotev	 *	Reset function for the CPU.
5380942622Slaurenw-arm	 * _e_handler:
5480942622Slaurenw-arm	 *	This is a placeholder for future per CPU exception handlers.
555dd9dbb5SJeenu Viswambharan	 * _power_down_ops:
565dd9dbb5SJeenu Viswambharan	 *	Comma-separated list of functions to perform power-down
575dd9dbb5SJeenu Viswambharan	 *	operatios on the CPU. At least one, and up to
585dd9dbb5SJeenu Viswambharan	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
595dd9dbb5SJeenu Viswambharan	 *	Starting at power level 0, these functions shall handle power
605dd9dbb5SJeenu Viswambharan	 *	down at subsequent power levels. If there aren't exactly
615dd9dbb5SJeenu Viswambharan	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
625dd9dbb5SJeenu Viswambharan	 *	used to handle power down at subsequent levels
635dd9dbb5SJeenu Viswambharan	 */
64a205a56eSDimitris Papastamos	.macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \
654caef42aSArvind Ram Prakash		_e_handler:req, _power_down_ops:vararg
66da04341eSChris Kay	.section .cpu_ops, "a"
675dd9dbb5SJeenu Viswambharan	.align 3
68add40351SSoby Mathew	.type cpu_ops_\_name, %object
69add40351SSoby Mathew	.quad \_midr
70b1d27b48SRoberto Vargas#if defined(IMAGE_AT_EL3)
715dd9dbb5SJeenu Viswambharan	.quad \_resetfunc
72add40351SSoby Mathew#endif
7380942622Slaurenw-arm	.quad \_e_handler
743d8256b2SMasahiro Yamada#ifdef IMAGE_BL31
755dd9dbb5SJeenu Viswambharan	/* Insert list of functions */
765dd9dbb5SJeenu Viswambharan	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
77add40351SSoby Mathew#endif
783f4c1e1eSBoyan Karatotev	/*
793f4c1e1eSBoyan Karatotev	 * It is possible (although unlikely) that a cpu may have no errata in
803f4c1e1eSBoyan Karatotev	 * code. In that case the start label will not be defined. The list is
813f4c1e1eSBoyan Karatotev	 * intended to be used in a loop, so define it as zero-length for
823f4c1e1eSBoyan Karatotev	 * predictable behaviour. Since this macro is always called at the end
833f4c1e1eSBoyan Karatotev	 * of the cpu file (after all errata have been parsed) we can be sure
843f4c1e1eSBoyan Karatotev	 * that we are at the end of the list. Some cpus call declare_cpu_ops
853f4c1e1eSBoyan Karatotev	 * twice, so only do this once.
863f4c1e1eSBoyan Karatotev	 */
873f4c1e1eSBoyan Karatotev	.pushsection .rodata.errata_entries
883f4c1e1eSBoyan Karatotev	.ifndef \_name\()_errata_list_start
893f4c1e1eSBoyan Karatotev		\_name\()_errata_list_start:
903f4c1e1eSBoyan Karatotev	.endif
913f4c1e1eSBoyan Karatotev	.ifndef \_name\()_errata_list_end
923f4c1e1eSBoyan Karatotev		\_name\()_errata_list_end:
933f4c1e1eSBoyan Karatotev	.endif
943f4c1e1eSBoyan Karatotev	.popsection
953f4c1e1eSBoyan Karatotev
963f4c1e1eSBoyan Karatotev	/* and now put them in cpu_ops */
973f4c1e1eSBoyan Karatotev	.quad \_name\()_errata_list_start
983f4c1e1eSBoyan Karatotev	.quad \_name\()_errata_list_end
9910bcd761SJeenu Viswambharan
10010bcd761SJeenu Viswambharan#if REPORT_ERRATA
10110bcd761SJeenu Viswambharan	.ifndef \_name\()_cpu_str
10210bcd761SJeenu Viswambharan	  /*
10310bcd761SJeenu Viswambharan	   * Place errata reported flag, and the spinlock to arbitrate access to
10410bcd761SJeenu Viswambharan	   * it in the data section.
10510bcd761SJeenu Viswambharan	   */
10610bcd761SJeenu Viswambharan	  .pushsection .data
10710bcd761SJeenu Viswambharan	  define_asm_spinlock \_name\()_errata_lock
10810bcd761SJeenu Viswambharan	  \_name\()_errata_reported:
10910bcd761SJeenu Viswambharan	  .word	0
11010bcd761SJeenu Viswambharan	  .popsection
11110bcd761SJeenu Viswambharan
11210bcd761SJeenu Viswambharan	  /* Place CPU string in rodata */
11310bcd761SJeenu Viswambharan	  .pushsection .rodata
11410bcd761SJeenu Viswambharan	  \_name\()_cpu_str:
11510bcd761SJeenu Viswambharan	  .asciz "\_name"
11610bcd761SJeenu Viswambharan	  .popsection
11710bcd761SJeenu Viswambharan	.endif
11810bcd761SJeenu Viswambharan
1193f4c1e1eSBoyan Karatotev	.quad \_name\()_cpu_str
12010bcd761SJeenu Viswambharan
12110bcd761SJeenu Viswambharan#ifdef IMAGE_BL31
12210bcd761SJeenu Viswambharan	/* Pointers to errata lock and reported flag */
12310bcd761SJeenu Viswambharan	.quad \_name\()_errata_lock
12410bcd761SJeenu Viswambharan	.quad \_name\()_errata_reported
1253f4c1e1eSBoyan Karatotev#endif /* IMAGE_BL31 */
1263f4c1e1eSBoyan Karatotev#endif /* REPORT_ERRATA */
12710bcd761SJeenu Viswambharan
1283d8256b2SMasahiro Yamada#if defined(IMAGE_BL31) && CRASH_REPORTING
129d3f70af6SSoby Mathew	.quad \_name\()_cpu_reg_dump
130d3f70af6SSoby Mathew#endif
131add40351SSoby Mathew	.endm
132e2bf57f8SDan Handley
133a205a56eSDimitris Papastamos	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
134a205a56eSDimitris Papastamos		_power_down_ops:vararg
135fd04156eSArvind Ram Prakash		declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, \_power_down_ops
136a205a56eSDimitris Papastamos	.endm
137a205a56eSDimitris Papastamos
13880942622Slaurenw-arm	.macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \
13980942622Slaurenw-arm		_e_handler:req, _power_down_ops:vararg
14080942622Slaurenw-arm		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
141fd04156eSArvind Ram Prakash			\_e_handler, \_power_down_ops
142a205a56eSDimitris Papastamos	.endm
143a205a56eSDimitris Papastamos
1443991a6a4SDimitris Papastamos	/*
1453991a6a4SDimitris Papastamos	 * This macro is used on some CPUs to detect if they are vulnerable
1463991a6a4SDimitris Papastamos	 * to CVE-2017-5715.
1473991a6a4SDimitris Papastamos	 */
1483991a6a4SDimitris Papastamos	.macro	cpu_check_csv2 _reg _label
1493991a6a4SDimitris Papastamos	mrs	\_reg, id_aa64pfr0_el1
1503991a6a4SDimitris Papastamos	ubfx	\_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH
1513991a6a4SDimitris Papastamos	/*
152ff6f62e1SAntonio Nino Diaz	 * If the field equals 1, branch targets trained in one context cannot
153ff6f62e1SAntonio Nino Diaz	 * affect speculative execution in a different context.
154ff6f62e1SAntonio Nino Diaz	 *
155*2b432165SArvind Ram Prakash	 * If the field equals 2 or 3, it means that the system is also aware of
156ff6f62e1SAntonio Nino Diaz	 * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we
157ff6f62e1SAntonio Nino Diaz	 * expect users of the registers to do the right thing.
158ff6f62e1SAntonio Nino Diaz	 *
159ff6f62e1SAntonio Nino Diaz	 * Only apply mitigations if the value of this field is 0.
1603991a6a4SDimitris Papastamos	 */
161ff6f62e1SAntonio Nino Diaz#if ENABLE_ASSERTIONS
162*2b432165SArvind Ram Prakash	cmp	\_reg, #4 /* Only values 0 to 3 are expected */
163ff6f62e1SAntonio Nino Diaz	ASM_ASSERT(lo)
164ff6f62e1SAntonio Nino Diaz#endif
165ff6f62e1SAntonio Nino Diaz
166ff6f62e1SAntonio Nino Diaz	cmp	\_reg, #0
167ff6f62e1SAntonio Nino Diaz	bne	\_label
1683991a6a4SDimitris Papastamos	.endm
169da3b038fSDeepak Pandey
170da3b038fSDeepak Pandey	/*
171da3b038fSDeepak Pandey	 * Helper macro that reads the part number of the current
172da3b038fSDeepak Pandey	 * CPU and jumps to the given label if it matches the CPU
173da3b038fSDeepak Pandey	 * MIDR provided.
174da3b038fSDeepak Pandey	 *
175da3b038fSDeepak Pandey	 * Clobbers x0.
176da3b038fSDeepak Pandey	 */
177da3b038fSDeepak Pandey	.macro  jump_if_cpu_midr _cpu_midr, _label
178da3b038fSDeepak Pandey	mrs	x0, midr_el1
179da3b038fSDeepak Pandey	ubfx	x0, x0, MIDR_PN_SHIFT, #12
180da3b038fSDeepak Pandey	cmp	w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
181da3b038fSDeepak Pandey	b.eq	\_label
182da3b038fSDeepak Pandey	.endm
183c3cf06f1SAntonio Nino Diaz
1843f4c1e1eSBoyan Karatotev
1853f4c1e1eSBoyan Karatotev/*
1863f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata
1873f4c1e1eSBoyan Karatotev * will be applied automatically
1883f4c1e1eSBoyan Karatotev *
1893f4c1e1eSBoyan Karatotev * _cpu:
1903f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
1913f4c1e1eSBoyan Karatotev *
1923f4c1e1eSBoyan Karatotev * _cve:
1933f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
1943f4c1e1eSBoyan Karatotev *
1953f4c1e1eSBoyan Karatotev * _id:
1963f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
1973f4c1e1eSBoyan Karatotev *	or CVE macros
1983f4c1e1eSBoyan Karatotev *
1993f4c1e1eSBoyan Karatotev * _chosen:
2003f4c1e1eSBoyan Karatotev *	Compile time flag on whether the erratum is included
2013f4c1e1eSBoyan Karatotev *
202bbff267bSArvind Ram Prakash * _split_wa:
203bbff267bSArvind Ram Prakash *	Flag that indicates whether an erratum has split workaround or not.
204bbff267bSArvind Ram Prakash *	Default value is 0.
2053f4c1e1eSBoyan Karatotev */
206bbff267bSArvind Ram Prakash.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _split_wa=0
207fd04156eSArvind Ram Prakash#if INCLUDE_ERRATA_LIST
2083f4c1e1eSBoyan Karatotev	.pushsection .rodata.errata_entries
2093f4c1e1eSBoyan Karatotev		.align	3
2103f4c1e1eSBoyan Karatotev		.ifndef \_cpu\()_errata_list_start
2113f4c1e1eSBoyan Karatotev		\_cpu\()_errata_list_start:
2123f4c1e1eSBoyan Karatotev		.endif
2133f4c1e1eSBoyan Karatotev
2143f4c1e1eSBoyan Karatotev		.quad	check_erratum_\_cpu\()_\_id
2153f4c1e1eSBoyan Karatotev		/* Will fit CVEs with up to 10 character in the ID field */
2163f4c1e1eSBoyan Karatotev		.word	\_id
2173f4c1e1eSBoyan Karatotev		.hword	\_cve
218bbff267bSArvind Ram Prakash		/* bit magic that appends chosen field based on _split_wa */
219bbff267bSArvind Ram Prakash		.byte	((\_chosen * 0b11) & ((\_split_wa << 1) | \_chosen))
22089dba82dSBoyan Karatotev		.byte	0x0 /* alignment */
2213f4c1e1eSBoyan Karatotev	.popsection
22289dba82dSBoyan Karatotev#endif
2233f4c1e1eSBoyan Karatotev.endm
2243f4c1e1eSBoyan Karatotev
2253f4c1e1eSBoyan Karatotev/*******************************************************************************
2263f4c1e1eSBoyan Karatotev * Errata workaround wrappers
2273f4c1e1eSBoyan Karatotev ******************************************************************************/
2283f4c1e1eSBoyan Karatotev/*
2293f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata
2303f4c1e1eSBoyan Karatotev * will be applied automatically
2313f4c1e1eSBoyan Karatotev *
2323f4c1e1eSBoyan Karatotev * _cpu:
2333f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
2343f4c1e1eSBoyan Karatotev *
2353f4c1e1eSBoyan Karatotev * _cve:
2363f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
2373f4c1e1eSBoyan Karatotev *
2383f4c1e1eSBoyan Karatotev * _id:
2393f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
2403f4c1e1eSBoyan Karatotev *	or CVE macros
2413f4c1e1eSBoyan Karatotev *
2423f4c1e1eSBoyan Karatotev * _chosen:
2433f4c1e1eSBoyan Karatotev *	Compile time flag on whether the erratum is included
2443f4c1e1eSBoyan Karatotev *
245bbff267bSArvind Ram Prakash * _split_wa:
246bbff267bSArvind Ram Prakash *	Flag that indicates whether an erratum has split workaround or not.
247bbff267bSArvind Ram Prakash *	Default value is 0.
248bbff267bSArvind Ram Prakash *
2493f4c1e1eSBoyan Karatotev * in body:
2503f4c1e1eSBoyan Karatotev *	clobber x0 to x7 (please only use those)
2513f4c1e1eSBoyan Karatotev *	argument x7 - cpu_rev_var
2523f4c1e1eSBoyan Karatotev *
2533f4c1e1eSBoyan Karatotev * _wa clobbers: x0-x8 (PCS compliant)
2543f4c1e1eSBoyan Karatotev */
255bbff267bSArvind Ram Prakash.macro workaround_reset_start _cpu:req, _cve:req, _id:req, \
256bbff267bSArvind Ram Prakash	_chosen:req, _split_wa=0
257bbff267bSArvind Ram Prakash
258bbff267bSArvind Ram Prakash	add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_split_wa
25989dba82dSBoyan Karatotev
26089dba82dSBoyan Karatotev	.if \_chosen
26189dba82dSBoyan Karatotev		/* put errata directly into the reset function */
26289dba82dSBoyan Karatotev		.pushsection .text.asm.\_cpu\()_reset_func, "ax"
26389dba82dSBoyan Karatotev	.else
26489dba82dSBoyan Karatotev		/* or something else that will get garbage collected by the
26589dba82dSBoyan Karatotev		 * linker */
26689dba82dSBoyan Karatotev		.pushsection .text.asm.erratum_\_cpu\()_\_id\()_wa, "ax"
26789dba82dSBoyan Karatotev	.endif
26889dba82dSBoyan Karatotev		/* revision is stored in x14, get it */
26989dba82dSBoyan Karatotev		mov	x0, x14
27089dba82dSBoyan Karatotev		bl	check_erratum_\_cpu\()_\_id
27189dba82dSBoyan Karatotev		/* save rev_var for workarounds that might need it */
27289dba82dSBoyan Karatotev		mov	x7, x14
27389dba82dSBoyan Karatotev		cbz	x0, erratum_\_cpu\()_\_id\()_skip_reset
2743f4c1e1eSBoyan Karatotev.endm
2753f4c1e1eSBoyan Karatotev
2763f4c1e1eSBoyan Karatotev/*
2773f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. Additional arguments:
2783f4c1e1eSBoyan Karatotev *
2793f4c1e1eSBoyan Karatotev * _midr:
2803f4c1e1eSBoyan Karatotev *	Check if CPU's MIDR matches the CPU it's meant for. Must be specified
2813f4c1e1eSBoyan Karatotev *	for errata applied in generic code
2823f4c1e1eSBoyan Karatotev */
2833f4c1e1eSBoyan Karatotev.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr
28489dba82dSBoyan Karatotev	add_erratum_entry \_cpu, \_cve, \_id, \_chosen
28589dba82dSBoyan Karatotev
28689dba82dSBoyan Karatotev	func erratum_\_cpu\()_\_id\()_wa
28789dba82dSBoyan Karatotev		mov	x8, x30
2883f4c1e1eSBoyan Karatotev	/*
2893f4c1e1eSBoyan Karatotev	 * Let errata specify if they need MIDR checking. Sadly, storing the
2903f4c1e1eSBoyan Karatotev	 * MIDR in an .equ to retrieve automatically blows up as it stores some
2913f4c1e1eSBoyan Karatotev	 * brackets in the symbol
2923f4c1e1eSBoyan Karatotev	 */
2933f4c1e1eSBoyan Karatotev	.ifnb \_midr
2943f4c1e1eSBoyan Karatotev		jump_if_cpu_midr \_midr, 1f
29589dba82dSBoyan Karatotev		b	erratum_\_cpu\()_\_id\()_skip_runtime
2963f4c1e1eSBoyan Karatotev
2973f4c1e1eSBoyan Karatotev		1:
2983f4c1e1eSBoyan Karatotev	.endif
29989dba82dSBoyan Karatotev		/* save rev_var for workarounds that might need it but don't
30089dba82dSBoyan Karatotev		 * restore to x0 because few will care */
30189dba82dSBoyan Karatotev		mov	x7, x0
30289dba82dSBoyan Karatotev		bl	check_erratum_\_cpu\()_\_id
30389dba82dSBoyan Karatotev		cbz	x0, erratum_\_cpu\()_\_id\()_skip_runtime
3043f4c1e1eSBoyan Karatotev.endm
3053f4c1e1eSBoyan Karatotev
3063f4c1e1eSBoyan Karatotev/*
3073f4c1e1eSBoyan Karatotev * Usage and arguments identical to `workaround_reset_start`. The _cve argument
3083f4c1e1eSBoyan Karatotev * is kept here so the same #define can be used as that macro
3093f4c1e1eSBoyan Karatotev */
3103f4c1e1eSBoyan Karatotev.macro workaround_reset_end _cpu:req, _cve:req, _id:req
31189dba82dSBoyan Karatotev	erratum_\_cpu\()_\_id\()_skip_reset:
31289dba82dSBoyan Karatotev	.popsection
3133f4c1e1eSBoyan Karatotev.endm
3143f4c1e1eSBoyan Karatotev
3153f4c1e1eSBoyan Karatotev/*
3163f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. The _cve argument is kept here
3173f4c1e1eSBoyan Karatotev * so the same #define can be used as that macro. Additional arguments:
3183f4c1e1eSBoyan Karatotev *
3193f4c1e1eSBoyan Karatotev * _no_isb:
3203f4c1e1eSBoyan Karatotev *	Optionally do not include the trailing isb. Please disable with the
3213f4c1e1eSBoyan Karatotev *	NO_ISB macro
3223f4c1e1eSBoyan Karatotev */
3233f4c1e1eSBoyan Karatotev.macro workaround_runtime_end _cpu:req, _cve:req, _id:req, _no_isb
3243f4c1e1eSBoyan Karatotev	/*
3253f4c1e1eSBoyan Karatotev	 * Runtime errata do not have a reset function to call the isb for them
3263f4c1e1eSBoyan Karatotev	 * and missing the isb could be very problematic. It is also likely as
3273f4c1e1eSBoyan Karatotev	 * they tend to be scattered in generic code.
3283f4c1e1eSBoyan Karatotev	 */
3293f4c1e1eSBoyan Karatotev	.ifb \_no_isb
3303f4c1e1eSBoyan Karatotev		isb
3313f4c1e1eSBoyan Karatotev	.endif
33289dba82dSBoyan Karatotev	erratum_\_cpu\()_\_id\()_skip_runtime:
33389dba82dSBoyan Karatotev		ret	x8
33489dba82dSBoyan Karatotev	endfunc erratum_\_cpu\()_\_id\()_wa
3353f4c1e1eSBoyan Karatotev.endm
3363f4c1e1eSBoyan Karatotev
3373f4c1e1eSBoyan Karatotev/*******************************************************************************
3383f4c1e1eSBoyan Karatotev * Errata workaround helpers
3393f4c1e1eSBoyan Karatotev ******************************************************************************/
3403f4c1e1eSBoyan Karatotev/*
3413f4c1e1eSBoyan Karatotev * Set a bit in a system register. Can set multiple bits but is limited by the
3423f4c1e1eSBoyan Karatotev *  way the ORR instruction encodes them.
3433f4c1e1eSBoyan Karatotev *
3443f4c1e1eSBoyan Karatotev * _reg:
3453f4c1e1eSBoyan Karatotev *	Register to write to
3463f4c1e1eSBoyan Karatotev *
3473f4c1e1eSBoyan Karatotev * _bit:
3483f4c1e1eSBoyan Karatotev *	Bit to set. Please use a descriptive #define
3493f4c1e1eSBoyan Karatotev *
3503f4c1e1eSBoyan Karatotev * _assert:
3513f4c1e1eSBoyan Karatotev *	Optionally whether to read back and assert that the bit has been
3523f4c1e1eSBoyan Karatotev *	written. Please disable with NO_ASSERT macro
3533f4c1e1eSBoyan Karatotev *
3543f4c1e1eSBoyan Karatotev * clobbers: x1
3553f4c1e1eSBoyan Karatotev */
3563f4c1e1eSBoyan Karatotev.macro sysreg_bit_set _reg:req, _bit:req, _assert=1
3573f4c1e1eSBoyan Karatotev	mrs	x1, \_reg
3583f4c1e1eSBoyan Karatotev	orr	x1, x1, #\_bit
3593f4c1e1eSBoyan Karatotev	msr	\_reg, x1
3603f4c1e1eSBoyan Karatotev.endm
3613f4c1e1eSBoyan Karatotev
3623f4c1e1eSBoyan Karatotev/*
36394a75ad4SBoyan Karatotev * Clear a bit in a system register. Can clear multiple bits but is limited by
36494a75ad4SBoyan Karatotev *  the way the BIC instrucion encodes them.
36594a75ad4SBoyan Karatotev *
36694a75ad4SBoyan Karatotev * see sysreg_bit_set for usage
36794a75ad4SBoyan Karatotev */
36894a75ad4SBoyan Karatotev.macro sysreg_bit_clear _reg:req, _bit:req
36994a75ad4SBoyan Karatotev	mrs	x1, \_reg
37094a75ad4SBoyan Karatotev	bic	x1, x1, #\_bit
37194a75ad4SBoyan Karatotev	msr	\_reg, x1
37294a75ad4SBoyan Karatotev.endm
37394a75ad4SBoyan Karatotev
374bb801857SBoyan Karatotev/*
375bb801857SBoyan Karatotev * Toggle a bit in a system register. Can toggle multiple bits but is limited by
376bb801857SBoyan Karatotev *  the way the EOR instrucion encodes them.
377bb801857SBoyan Karatotev *
378bb801857SBoyan Karatotev * see sysreg_bit_set for usage
379bb801857SBoyan Karatotev */
380bb801857SBoyan Karatotev.macro sysreg_bit_toggle _reg:req, _bit:req, _assert=1
381bb801857SBoyan Karatotev	mrs	x1, \_reg
382bb801857SBoyan Karatotev	eor	x1, x1, #\_bit
383bb801857SBoyan Karatotev	msr	\_reg, x1
384bb801857SBoyan Karatotev.endm
385bb801857SBoyan Karatotev
38694a75ad4SBoyan Karatotev.macro override_vector_table _table:req
38794a75ad4SBoyan Karatotev	adr	x1, \_table
38894a75ad4SBoyan Karatotev	msr	vbar_el3, x1
38994a75ad4SBoyan Karatotev.endm
39094a75ad4SBoyan Karatotev
39194a75ad4SBoyan Karatotev/*
392445f7b51SJayanth Dodderi Chidanand * BFI : Inserts bitfield into a system register.
393445f7b51SJayanth Dodderi Chidanand *
394445f7b51SJayanth Dodderi Chidanand * BFI{cond} Rd, Rn, #lsb, #width
395445f7b51SJayanth Dodderi Chidanand */
396445f7b51SJayanth Dodderi Chidanand.macro sysreg_bitfield_insert _reg:req, _src:req, _lsb:req, _width:req
397445f7b51SJayanth Dodderi Chidanand	/* Source value for BFI */
398445f7b51SJayanth Dodderi Chidanand	mov	x1, #\_src
399445f7b51SJayanth Dodderi Chidanand	mrs	x0, \_reg
400445f7b51SJayanth Dodderi Chidanand	bfi	x0, x1, #\_lsb, #\_width
401445f7b51SJayanth Dodderi Chidanand	msr	\_reg, x0
402445f7b51SJayanth Dodderi Chidanand.endm
403445f7b51SJayanth Dodderi Chidanand
404ad8b5141SJagdish Gediya.macro sysreg_bitfield_insert_from_gpr _reg:req, _gpr:req, _lsb:req, _width:req
405ad8b5141SJagdish Gediya	/* Source value in register for BFI */
406ad8b5141SJagdish Gediya	mov	x1, \_gpr
407ad8b5141SJagdish Gediya	mrs	x0, \_reg
408ad8b5141SJagdish Gediya	bfi	x0, x1, #\_lsb, #\_width
409ad8b5141SJagdish Gediya	msr	\_reg, x0
410ad8b5141SJagdish Gediya.endm
411ad8b5141SJagdish Gediya
412445f7b51SJayanth Dodderi Chidanand/*
41336eeb59fSBoyan Karatotev * Extract CPU revision and variant, and combine them into a single numeric for
41436eeb59fSBoyan Karatotev * easier comparison.
41536eeb59fSBoyan Karatotev *
41636eeb59fSBoyan Karatotev * _res:
41736eeb59fSBoyan Karatotev *	register where the result will be placed
41836eeb59fSBoyan Karatotev * _tmp:
41936eeb59fSBoyan Karatotev *	register to clobber for temporaries
42036eeb59fSBoyan Karatotev */
42136eeb59fSBoyan Karatotev.macro get_rev_var _res:req, _tmp:req
42236eeb59fSBoyan Karatotev	mrs	\_tmp, midr_el1
42336eeb59fSBoyan Karatotev
42436eeb59fSBoyan Karatotev	/*
42536eeb59fSBoyan Karatotev	 * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them
42636eeb59fSBoyan Karatotev	 * as variant[7:4] and revision[3:0] of x0.
42736eeb59fSBoyan Karatotev	 *
42836eeb59fSBoyan Karatotev	 * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then
42936eeb59fSBoyan Karatotev	 * extract x1[3:0] into x0[3:0] retaining other bits.
43036eeb59fSBoyan Karatotev	 */
43136eeb59fSBoyan Karatotev	ubfx	\_res, \_tmp, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
43236eeb59fSBoyan Karatotev	bfxil	\_res, \_tmp, #MIDR_REV_SHIFT, #MIDR_REV_BITS
43336eeb59fSBoyan Karatotev.endm
43436eeb59fSBoyan Karatotev
43536eeb59fSBoyan Karatotev/*
4363f4c1e1eSBoyan Karatotev * Apply erratum
4373f4c1e1eSBoyan Karatotev *
4383f4c1e1eSBoyan Karatotev * _cpu:
4393f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
4403f4c1e1eSBoyan Karatotev *
4413f4c1e1eSBoyan Karatotev * _cve:
4423f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
4433f4c1e1eSBoyan Karatotev *
4443f4c1e1eSBoyan Karatotev * _id:
4453f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
4463f4c1e1eSBoyan Karatotev *	or CVE macros
4473f4c1e1eSBoyan Karatotev *
4483f4c1e1eSBoyan Karatotev * _chosen:
4493f4c1e1eSBoyan Karatotev *	Compile time flag on whether the erratum is included
4503f4c1e1eSBoyan Karatotev *
4514d22b0e5SHarrison Mutai * _get_rev:
4524d22b0e5SHarrison Mutai *	Optional parameter that determines whether to insert a call to the CPU revision fetching
453db9ee834SBoyan Karatotev *	procedure. Stores the result of this in the temporary register x10 to allow for chaining
4544d22b0e5SHarrison Mutai *
4554d22b0e5SHarrison Mutai * clobbers: x0-x10 (PCS compliant)
4563f4c1e1eSBoyan Karatotev */
4574d22b0e5SHarrison Mutai.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req, _get_rev=GET_CPU_REV
458cc94e71bSBoyan Karatotev	.if (\_chosen && \_get_rev)
4593f4c1e1eSBoyan Karatotev		mov	x9, x30
4603f4c1e1eSBoyan Karatotev		bl	cpu_get_rev_var
4614d22b0e5SHarrison Mutai		mov	x10, x0
4624d22b0e5SHarrison Mutai	.elseif (\_chosen)
4634d22b0e5SHarrison Mutai		mov	x9, x30
4644d22b0e5SHarrison Mutai		mov	x0, x10
4654d22b0e5SHarrison Mutai	.endif
4664d22b0e5SHarrison Mutai
4674d22b0e5SHarrison Mutai	.if \_chosen
4683f4c1e1eSBoyan Karatotev		bl	erratum_\_cpu\()_\_id\()_wa
4693f4c1e1eSBoyan Karatotev		mov	x30, x9
4703f4c1e1eSBoyan Karatotev	.endif
4713f4c1e1eSBoyan Karatotev.endm
4723f4c1e1eSBoyan Karatotev
4733f4c1e1eSBoyan Karatotev/*
4747791ce21SBoyan Karatotev * Helpers to report if an erratum applies. Compares the given revision variant
4757791ce21SBoyan Karatotev * to the given value. Return ERRATA_APPLIES or ERRATA_NOT_APPLIES accordingly.
4767791ce21SBoyan Karatotev *
4777791ce21SBoyan Karatotev * _rev_num: the given revision variant. Or
4787791ce21SBoyan Karatotev * _rev_num_lo,_rev_num_hi: the lower and upper bounds of the revision variant
4797791ce21SBoyan Karatotev *
4807791ce21SBoyan Karatotev * in body:
4817791ce21SBoyan Karatotev *	clobber: x0
4827791ce21SBoyan Karatotev *	argument: x0 - cpu_rev_var
4837791ce21SBoyan Karatotev */
4847791ce21SBoyan Karatotev.macro cpu_rev_var_ls _rev_num:req
4857791ce21SBoyan Karatotev	cmp	x0, #\_rev_num
4867791ce21SBoyan Karatotev	cset	x0, ls
4877791ce21SBoyan Karatotev.endm
4887791ce21SBoyan Karatotev
4897791ce21SBoyan Karatotev.macro cpu_rev_var_hs _rev_num:req
4907791ce21SBoyan Karatotev	cmp	x0, #\_rev_num
4917791ce21SBoyan Karatotev	cset	x0, hs
4927791ce21SBoyan Karatotev.endm
4937791ce21SBoyan Karatotev
4947791ce21SBoyan Karatotev.macro cpu_rev_var_range _rev_num_lo:req, _rev_num_hi:req
4957791ce21SBoyan Karatotev	cmp	x0, #\_rev_num_lo
4967791ce21SBoyan Karatotev	mov	x1, #\_rev_num_hi
4977791ce21SBoyan Karatotev	ccmp	x0, x1, #2, hs
4987791ce21SBoyan Karatotev	cset	x0, ls
4997791ce21SBoyan Karatotev.endm
5007791ce21SBoyan Karatotev
501bdaf0d9bSGovindraj Raja
502bdaf0d9bSGovindraj Raja#if __clang_major__ < 17
503bdaf0d9bSGovindraj Raja/*
504bdaf0d9bSGovindraj Raja * A problem with clang version < 17 can cause resolving nested
505bdaf0d9bSGovindraj Raja * 'cfi_startproc' to fail compilation.
506bdaf0d9bSGovindraj Raja * So add a compatibility variant for start and endfunc expansions
507bdaf0d9bSGovindraj Raja * to ignore `cfi_startproc` and `cfi_endproc`, this to be used only with
508bdaf0d9bSGovindraj Raja * check_errata/reset macros if we build TF-A with clang version < 17
509bdaf0d9bSGovindraj Raja */
510bdaf0d9bSGovindraj Raja
511bdaf0d9bSGovindraj Raja.macro func_compat _name, _align=2
512bdaf0d9bSGovindraj Raja	.section .text.asm.\_name, "ax"
513bdaf0d9bSGovindraj Raja	.type \_name, %function
514bdaf0d9bSGovindraj Raja	.align \_align
515bdaf0d9bSGovindraj Raja	\_name:
516bdaf0d9bSGovindraj Raja#if ENABLE_BTI
517bdac600bSAndre Przywara	BTI	jc
518bdaf0d9bSGovindraj Raja#endif
519bdaf0d9bSGovindraj Raja.endm
520bdaf0d9bSGovindraj Raja
521bdaf0d9bSGovindraj Raja/*
522bdaf0d9bSGovindraj Raja * This macro is used to mark the end of a function.
523bdaf0d9bSGovindraj Raja */
524bdaf0d9bSGovindraj Raja.macro endfunc_compat _name
525bdaf0d9bSGovindraj Raja	.size \_name, . - \_name
526bdaf0d9bSGovindraj Raja.endm
527bdaf0d9bSGovindraj Raja
528bdaf0d9bSGovindraj Raja#else
529bdaf0d9bSGovindraj Raja
530bdaf0d9bSGovindraj Raja#define func_compat func
531bdaf0d9bSGovindraj Raja#define endfunc_compat endfunc
532bdaf0d9bSGovindraj Raja
533bdaf0d9bSGovindraj Raja#endif /* __clang_version__ < 17 */
534bdaf0d9bSGovindraj Raja
5357791ce21SBoyan Karatotev/*
5367791ce21SBoyan Karatotev * Helpers to select which revisions errata apply to.
5373f4c1e1eSBoyan Karatotev *
5383f4c1e1eSBoyan Karatotev * _cpu:
5393f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
5403f4c1e1eSBoyan Karatotev *
5413f4c1e1eSBoyan Karatotev * _cve:
5423f4c1e1eSBoyan Karatotev *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
5433f4c1e1eSBoyan Karatotev *
5443f4c1e1eSBoyan Karatotev * _id:
5453f4c1e1eSBoyan Karatotev *	Erratum or CVE number. Please combine with previous field with ERRATUM
5463f4c1e1eSBoyan Karatotev *	or CVE macros
5473f4c1e1eSBoyan Karatotev *
5483f4c1e1eSBoyan Karatotev * _rev_num:
5493f4c1e1eSBoyan Karatotev *	Revision to apply to
5503f4c1e1eSBoyan Karatotev *
5513f4c1e1eSBoyan Karatotev * in body:
5527791ce21SBoyan Karatotev *	clobber: x0 to x1
5533f4c1e1eSBoyan Karatotev *	argument: x0 - cpu_rev_var
5543f4c1e1eSBoyan Karatotev */
5553f4c1e1eSBoyan Karatotev.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req
556bdaf0d9bSGovindraj Raja	func_compat check_erratum_\_cpu\()_\_id
5577791ce21SBoyan Karatotev		cpu_rev_var_ls \_rev_num
5587791ce21SBoyan Karatotev		ret
559bdaf0d9bSGovindraj Raja	endfunc_compat check_erratum_\_cpu\()_\_id
5603f4c1e1eSBoyan Karatotev.endm
5613f4c1e1eSBoyan Karatotev
5623f4c1e1eSBoyan Karatotev.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req
563bdaf0d9bSGovindraj Raja	func_compat check_erratum_\_cpu\()_\_id
5647791ce21SBoyan Karatotev		cpu_rev_var_hs \_rev_num
5657791ce21SBoyan Karatotev		ret
566bdaf0d9bSGovindraj Raja	endfunc_compat check_erratum_\_cpu\()_\_id
5673f4c1e1eSBoyan Karatotev.endm
5683f4c1e1eSBoyan Karatotev
5693f4c1e1eSBoyan Karatotev.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req
570bdaf0d9bSGovindraj Raja	func_compat check_erratum_\_cpu\()_\_id
5717791ce21SBoyan Karatotev		cpu_rev_var_range \_rev_num_lo, \_rev_num_hi
5727791ce21SBoyan Karatotev		ret
573bdaf0d9bSGovindraj Raja	endfunc_compat check_erratum_\_cpu\()_\_id
5743f4c1e1eSBoyan Karatotev.endm
5753f4c1e1eSBoyan Karatotev
57694a75ad4SBoyan Karatotev.macro check_erratum_chosen _cpu:req, _cve:req, _id:req, _chosen:req
577bdaf0d9bSGovindraj Raja	func_compat check_erratum_\_cpu\()_\_id
57894a75ad4SBoyan Karatotev		.if \_chosen
57994a75ad4SBoyan Karatotev			mov	x0, #ERRATA_APPLIES
58094a75ad4SBoyan Karatotev		.else
58194a75ad4SBoyan Karatotev			mov	x0, #ERRATA_MISSING
58294a75ad4SBoyan Karatotev		.endif
58394a75ad4SBoyan Karatotev		ret
584bdaf0d9bSGovindraj Raja	endfunc_compat check_erratum_\_cpu\()_\_id
58594a75ad4SBoyan Karatotev.endm
58694a75ad4SBoyan Karatotev
5877791ce21SBoyan Karatotev/*
5887791ce21SBoyan Karatotev * provide a shorthand for the name format for annoying errata
58936eeb59fSBoyan Karatotev * body: clobber x0 to x4
5907791ce21SBoyan Karatotev */
59194a75ad4SBoyan Karatotev.macro check_erratum_custom_start _cpu:req, _cve:req, _id:req
592bdaf0d9bSGovindraj Raja	func_compat check_erratum_\_cpu\()_\_id
59394a75ad4SBoyan Karatotev.endm
59494a75ad4SBoyan Karatotev
59594a75ad4SBoyan Karatotev.macro check_erratum_custom_end _cpu:req, _cve:req, _id:req
596bdaf0d9bSGovindraj Raja	endfunc_compat check_erratum_\_cpu\()_\_id
59794a75ad4SBoyan Karatotev.endm
59894a75ad4SBoyan Karatotev
5993f4c1e1eSBoyan Karatotev/*******************************************************************************
6003f4c1e1eSBoyan Karatotev * CPU reset function wrapper
6013f4c1e1eSBoyan Karatotev ******************************************************************************/
6023f4c1e1eSBoyan Karatotev
6033f4c1e1eSBoyan Karatotev/*
60489dba82dSBoyan Karatotev * Helper to register a cpu with the errata framework. Begins the definition of
60589dba82dSBoyan Karatotev * the reset function.
60689dba82dSBoyan Karatotev *
60789dba82dSBoyan Karatotev * _cpu:
60889dba82dSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
60989dba82dSBoyan Karatotev */
61089dba82dSBoyan Karatotev.macro cpu_reset_prologue _cpu:req
611bdaf0d9bSGovindraj Raja	func_compat \_cpu\()_reset_func
61289dba82dSBoyan Karatotev		mov	x15, x30
61389dba82dSBoyan Karatotev		get_rev_var x14, x0
61489dba82dSBoyan Karatotev.endm
61589dba82dSBoyan Karatotev
61689dba82dSBoyan Karatotev/*
61789dba82dSBoyan Karatotev * Wrapper of the reset function to automatically apply all reset-time errata.
61889dba82dSBoyan Karatotev * Will end with an isb.
6193f4c1e1eSBoyan Karatotev *
6203f4c1e1eSBoyan Karatotev * _cpu:
6213f4c1e1eSBoyan Karatotev *	Name of cpu as given to declare_cpu_ops
6223f4c1e1eSBoyan Karatotev *
6233f4c1e1eSBoyan Karatotev * in body:
6243f4c1e1eSBoyan Karatotev *	clobber x8 to x14
6253f4c1e1eSBoyan Karatotev *	argument x14 - cpu_rev_var
6263f4c1e1eSBoyan Karatotev */
6273f4c1e1eSBoyan Karatotev.macro cpu_reset_func_start _cpu:req
62889dba82dSBoyan Karatotev	/* the func/endfunc macros will change sections. So change the section
62989dba82dSBoyan Karatotev	 * back to the reset function's */
63089dba82dSBoyan Karatotev	.section .text.asm.\_cpu\()_reset_func, "ax"
6313f4c1e1eSBoyan Karatotev.endm
6323f4c1e1eSBoyan Karatotev
6333f4c1e1eSBoyan Karatotev.macro cpu_reset_func_end _cpu:req
6343f4c1e1eSBoyan Karatotev		isb
6353f4c1e1eSBoyan Karatotev		ret	x15
636bdaf0d9bSGovindraj Raja	endfunc_compat \_cpu\()_reset_func
6373f4c1e1eSBoyan Karatotev.endm
6384f748cc4SBoyan Karatotev
6392590e819SBoyan Karatotev/*
6402590e819SBoyan Karatotev * Helper macro that enables Maximum Power Mitigation Mechanism (MPMM) on
6412590e819SBoyan Karatotev * compatible Arm cores.
6422590e819SBoyan Karatotev *
6432590e819SBoyan Karatotev * Clobbers x0.
6442590e819SBoyan Karatotev */
6452590e819SBoyan Karatotev.macro enable_mpmm
6462590e819SBoyan Karatotev#if ENABLE_MPMM
6472590e819SBoyan Karatotev	mrs	x0, CPUPPMCR_EL3
6482590e819SBoyan Karatotev	/* if CPUPPMCR_EL3.MPMMPINCTL != 0, skip enabling MPMM */
6492590e819SBoyan Karatotev	ands	x0, x0, CPUPPMCR_EL3_MPMMPINCTL_BIT
6502590e819SBoyan Karatotev	b.ne	1f
6512590e819SBoyan Karatotev	sysreg_bit_set CPUPPMCR_EL3, CPUMPMMCR_EL3_MPMM_EN_BIT
6522590e819SBoyan Karatotev	1:
6532590e819SBoyan Karatotev#endif
6542590e819SBoyan Karatotev.endm
6552590e819SBoyan Karatotev
656c3cf06f1SAntonio Nino Diaz#endif /* CPU_MACROS_S */
657