1/*
2 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#ifndef ASM_MACROS_S
7#define ASM_MACROS_S
8
9#include <arch.h>
10#include <common/asm_macros_common.S>
11#include <lib/spinlock.h>
12
13/*
14 * TLBI instruction with type specifier that implements the workaround for
15 * errata 813419 of Cortex-A57 or errata 1286807 of Cortex-A76.
16 */
17#if ERRATA_A57_813419 || ERRATA_A76_1286807
18#define TLB_INVALIDATE(_type) \
19	tlbi	_type; \
20	dsb	ish; \
21	tlbi	_type
22#else
23#define TLB_INVALIDATE(_type) \
24	tlbi	_type
25#endif
26
27
28	/*
29	 * Create a stack frame at the start of an assembly function. Will also
30	 * add all necessary call frame information (cfi) directives for a
31	 * pretty stack trace. This is necessary as there is quite a bit of
32	 * flexibility within a stack frame and the stack pointer can move
33	 * around throughout the function. If the debugger isn't told where to
34	 * find things, it gets lost, gives up and displays nothing. So inform
35	 * the debugger of what's where. Anchor the Canonical Frame Address
36	 * (CFA; the thing used to track what's where) to the frame pointer as
37	 * that's not expected to change in the function body and no extra
38	 * bookkeeping will be necessary, allowing free movement of the sp
39	 *
40	 *   _frame_size: requested space for caller to use. Must be a mutliple
41	 *     of 16 for stack pointer alignment
42	 */
43	.macro	func_prologue _frame_size=0
44	.if \_frame_size & 0xf
45	.error "frame_size must have stack pointer alignment (multiple of 16)"
46	.endif
47
48	/* put frame record at top of frame */
49	stp	x29, x30, [sp, #-0x10]!
50	mov	x29,sp
51	.if \_frame_size
52	sub	sp, sp, #\_frame_size
53	.endif
54
55	/* point CFA to start of frame record, i.e. x29 + 0x10 */
56	.cfi_def_cfa	x29,  0x10
57	/* inform it about x29, x30 locations */
58	.cfi_offset	x30, -0x8
59	.cfi_offset	x29, -0x10
60	.endm
61
62	/*
63	 * Clear stack frame at the end of an assembly function.
64	 *
65	 *   _frame_size: the value passed to func_prologue
66	 */
67	.macro	func_epilogue _frame_size=0
68	/* remove requested space */
69	.if \_frame_size
70	add	sp, sp, #\_frame_size
71	.endif
72	ldp	x29, x30, [sp], #0x10
73	.endm
74
75
76	.macro	dcache_line_size  reg, tmp
77	mrs	\tmp, ctr_el0
78	ubfx	\tmp, \tmp, #16, #4
79	mov	\reg, #4
80	lsl	\reg, \reg, \tmp
81	.endm
82
83
84	.macro	icache_line_size  reg, tmp
85	mrs	\tmp, ctr_el0
86	and	\tmp, \tmp, #0xf
87	mov	\reg, #4
88	lsl	\reg, \reg, \tmp
89	.endm
90
91
92	.macro	smc_check  label
93	mrs	x0, esr_el3
94	ubfx	x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH
95	cmp	x0, #EC_AARCH64_SMC
96	b.ne	$label
97	.endm
98
99	/*
100	 * Declare the exception vector table, enforcing it is aligned on a
101	 * 2KB boundary, as required by the ARMv8 architecture.
102	 * Use zero bytes as the fill value to be stored in the padding bytes
103	 * so that it inserts illegal AArch64 instructions. This increases
104	 * security, robustness and potentially facilitates debugging.
105	 */
106	.macro vector_base  label, section_name=.vectors
107	.section \section_name, "ax"
108	.align 11, 0
109	\label:
110	.endm
111
112	/*
113	 * Create an entry in the exception vector table, enforcing it is
114	 * aligned on a 128-byte boundary, as required by the ARMv8 architecture.
115	 * Use zero bytes as the fill value to be stored in the padding bytes
116	 * so that it inserts illegal AArch64 instructions. This increases
117	 * security, robustness and potentially facilitates debugging.
118	 */
119	.macro vector_entry  label, section_name=.vectors
120	.cfi_sections .debug_frame
121	.section \section_name, "ax"
122	.align 7, 0
123	.type \label, %function
124	.cfi_startproc
125	\label:
126	.endm
127
128	/*
129	 * Add the bytes until fill the full exception vector, whose size is always
130	 * 32 instructions. If there are more than 32 instructions in the
131	 * exception vector then an error is emitted.
132	 */
133	.macro end_vector_entry label
134	.cfi_endproc
135	.fill	\label + (32 * 4) - .
136	.endm
137
138	/*
139	 * This macro calculates the base address of the current CPU's MP stack
140	 * using the plat_my_core_pos() index, the name of the stack storage
141	 * and the size of each stack
142	 * Out: X0 = physical address of stack base
143	 * Clobber: X30, X1, X2
144	 */
145	.macro get_my_mp_stack _name, _size
146	bl	plat_my_core_pos
147	adrp	x2, (\_name + \_size)
148	add	x2, x2, :lo12:(\_name + \_size)
149	mov x1, #\_size
150	madd x0, x0, x1, x2
151	.endm
152
153	/*
154	 * This macro calculates the base address of a UP stack using the
155	 * name of the stack storage and the size of the stack
156	 * Out: X0 = physical address of stack base
157	 */
158	.macro get_up_stack _name, _size
159	adrp	x0, (\_name + \_size)
160	add	x0, x0, :lo12:(\_name + \_size)
161	.endm
162
163	/*
164	 * Helper macro to generate the best mov/movk combinations according
165	 * the value to be moved. The 16 bits from '_shift' are tested and
166	 * if not zero, they are moved into '_reg' without affecting
167	 * other bits.
168	 */
169	.macro _mov_imm16 _reg, _val, _shift
170		.if (\_val >> \_shift) & 0xffff
171			.if (\_val & (1 << \_shift - 1))
172				movk	\_reg, (\_val >> \_shift) & 0xffff, LSL \_shift
173			.else
174				mov	\_reg, \_val & (0xffff << \_shift)
175			.endif
176		.endif
177	.endm
178
179	/*
180	 * Helper macro to load arbitrary values into 32 or 64-bit registers
181	 * which generates the best mov/movk combinations. Many base addresses
182	 * are 64KB aligned the macro will eliminate updating bits 15:0 in
183	 * that case
184	 */
185	.macro mov_imm _reg, _val
186		.if (\_val) == 0
187			mov	\_reg, #0
188		.else
189			_mov_imm16	\_reg, (\_val), 0
190			_mov_imm16	\_reg, (\_val), 16
191			_mov_imm16	\_reg, (\_val), 32
192			_mov_imm16	\_reg, (\_val), 48
193		.endif
194	.endm
195
196	/*
197	 * Macro to mark instances where we're jumping to a function and don't
198	 * expect a return. To provide the function being jumped to with
199	 * additional information, we use 'bl' instruction to jump rather than
200	 * 'b'.
201         *
202	 * Debuggers infer the location of a call from where LR points to, which
203	 * is usually the instruction after 'bl'. If this macro expansion
204	 * happens to be the last location in a function, that'll cause the LR
205	 * to point a location beyond the function, thereby misleading debugger
206	 * back trace. We therefore insert a 'nop' after the function call for
207	 * debug builds, unless 'skip_nop' parameter is non-zero.
208	 */
209	.macro no_ret _func:req, skip_nop=0
210	bl	\_func
211#if DEBUG
212	.ifeq \skip_nop
213	nop
214	.endif
215#endif
216	.endm
217
218	/*
219	 * Reserve space for a spin lock in assembly file.
220	 */
221	.macro define_asm_spinlock _name:req
222	.align	SPINLOCK_ASM_ALIGN
223	\_name:
224	.space	SPINLOCK_ASM_SIZE
225	.endm
226
227	/*
228	 * With RAS extension executes esb instruction, else NOP
229	 */
230	.macro esb
231	.inst	0xd503221f
232	.endm
233
234	/*
235	 * Helper macro to read system register value into x0
236	 */
237	.macro	read reg:req
238#if ENABLE_BTI
239	bti	j
240#endif
241	mrs	x0, \reg
242	ret
243	.endm
244
245	/*
246	 * Helper macro to write value from x1 to system register
247	 */
248	.macro	write reg:req
249#if ENABLE_BTI
250	bti	j
251#endif
252	msr	\reg, x1
253	ret
254	.endm
255
256	/*
257	 * The "sb" instruction was introduced later into the architecture,
258	 * so not all toolchains understand it. Some deny its usage unless
259	 * a supported processor is specified on the build command line.
260	 * Use sb's system register encoding to work around this, we already
261	 * guard the sb execution with a feature flag.
262	 */
263
264	.macro sb_barrier_insn
265	msr	SYSREG_SB, xzr
266	.endm
267
268	/*
269	 * Macro for using speculation barrier instruction introduced by
270	 * FEAT_SB, if it's enabled.
271	 */
272	.macro speculation_barrier
273#if ENABLE_FEAT_SB
274	sb_barrier_insn
275#else
276	dsb	sy
277	isb
278#endif
279	.endm
280
281	/*
282	 * Macro for mitigating against speculative execution beyond ERET. Uses the
283	 * speculation barrier instruction introduced by FEAT_SB, if it's enabled.
284	 */
285	.macro exception_return
286	eret
287#if ENABLE_FEAT_SB
288	sb_barrier_insn
289#else
290	dsb	nsh
291	isb
292#endif
293	.endm
294
295	/*
296	 * Macro to unmask External Aborts by changing PSTATE.A bit.
297	 * Put explicit synchronization event to ensure newly unmasked interrupt
298	 * is taken immediately.
299	 */
300	.macro  unmask_async_ea
301	msr     daifclr, #DAIF_ABT_BIT
302	isb
303	.endm
304
305	/* Macro for error synchronization on exception boundries.
306	 * With FEAT_RAS enabled, it is assumed that FEAT_IESB is also present
307	 * and enabled.
308	 * FEAT_IESB provides an implicit error synchronization event at exception
309	 * entry and exception return, so there is no need for any explicit instruction.
310	 */
311	.macro synchronize_errors
312#if !ENABLE_FEAT_RAS
313	/* Complete any stores that may return an abort */
314	dsb	sy
315	/* Synchronise the CPU context with the completion of the dsb */
316	isb
317#endif
318	.endm
319
320	/*
321	 * Helper macro to instruction adr <reg>, <symbol> where <symbol> is
322	 * within the range +/- 4 GB.
323	 */
324	.macro adr_l, dst, sym
325	adrp	\dst, \sym
326	add	\dst, \dst, :lo12:\sym
327	.endm
328#endif /* ASM_MACROS_S */
329