asm_macros.S 4.82 KB
Newer Older
1
/*
2
 * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
3
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
 */
6
7
#ifndef ASM_MACROS_S
#define ASM_MACROS_S
8

9
#include <arch.h>
10
11
#include <common/asm_macros_common.S>
#include <lib/spinlock.h>
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * TLBI instruction with type specifier that implements the workaround for
 * errata 813419 of Cortex-A57.
 */
#if ERRATA_A57_813419
#define TLB_INVALIDATE(_type) \
	tlbi	_type; \
	dsb	ish; \
	tlbi	_type
#else
#define TLB_INVALIDATE(_type) \
	tlbi	_type
#endif

27

28
29
30
31
32
33
34
35
36
37
38
	.macro	func_prologue
	stp	x29, x30, [sp, #-0x10]!
	mov	x29,sp
	.endm

	.macro	func_epilogue
	ldp	x29, x30, [sp], #0x10
	.endm


	.macro	dcache_line_size  reg, tmp
39
	mrs	\tmp, ctr_el0
40
	ubfx	\tmp, \tmp, #16, #4
41
42
	mov	\reg, #4
	lsl	\reg, \reg, \tmp
43
44
45
46
	.endm


	.macro	icache_line_size  reg, tmp
47
48
49
50
	mrs	\tmp, ctr_el0
	and	\tmp, \tmp, #0xf
	mov	\reg, #4
	lsl	\reg, \reg, \tmp
51
52
53
54
	.endm


	.macro	smc_check  label
55
	mrs	x0, esr_el3
56
57
58
59
60
	ubfx	x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH
	cmp	x0, #EC_AARCH64_SMC
	b.ne	$label
	.endm

61
62
63
	/*
	 * Declare the exception vector table, enforcing it is aligned on a
	 * 2KB boundary, as required by the ARMv8 architecture.
64
65
66
	 * Use zero bytes as the fill value to be stored in the padding bytes
	 * so that it inserts illegal AArch64 instructions. This increases
	 * security, robustness and potentially facilitates debugging.
67
	 */
68
69
	.macro vector_base  label, section_name=.vectors
	.section \section_name, "ax"
70
	.align 11, 0
71
72
73
74
75
76
	\label:
	.endm

	/*
	 * Create an entry in the exception vector table, enforcing it is
	 * aligned on a 128-byte boundary, as required by the ARMv8 architecture.
77
78
79
	 * Use zero bytes as the fill value to be stored in the padding bytes
	 * so that it inserts illegal AArch64 instructions. This increases
	 * security, robustness and potentially facilitates debugging.
80
	 */
81
	.macro vector_entry  label, section_name=.vectors
82
	.cfi_sections .debug_frame
83
	.section \section_name, "ax"
84
	.align 7, 0
85
86
	.type \label, %function
	.cfi_startproc
87
88
	\label:
	.endm
89

90
91
92
93
94
95
96
97
98
99
	/*
	 * Add the bytes until fill the full exception vector, whose size is always
	 * 32 instructions. If there are more than 32 instructions in the
	 * exception vector then an error is emitted.
	 */
	.macro end_vector_entry label
	.cfi_endproc
	.fill	\label + (32 * 4) - .
	.endm

100
101
102
103
104
105
106
107
	/*
	 * This macro calculates the base address of the current CPU's MP stack
	 * using the plat_my_core_pos() index, the name of the stack storage
	 * and the size of each stack
	 * Out: X0 = physical address of stack base
	 * Clobber: X30, X1, X2
	 */
	.macro get_my_mp_stack _name, _size
108
109
110
	bl	plat_my_core_pos
	adrp	x2, (\_name + \_size)
	add	x2, x2, :lo12:(\_name + \_size)
111
112
113
114
	mov x1, #\_size
	madd x0, x0, x1, x2
	.endm

115
116
117
118
119
120
	/*
	 * This macro calculates the base address of a UP stack using the
	 * name of the stack storage and the size of the stack
	 * Out: X0 = physical address of stack base
	 */
	.macro get_up_stack _name, _size
121
122
	adrp	x0, (\_name + \_size)
	add	x0, x0, :lo12:(\_name + \_size)
123
	.endm
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

	/*
	 * Helper macro to generate the best mov/movk combinations according
	 * the value to be moved. The 16 bits from '_shift' are tested and
	 * if not zero, they are moved into '_reg' without affecting
	 * other bits.
	 */
	.macro _mov_imm16 _reg, _val, _shift
		.if (\_val >> \_shift) & 0xffff
			.if (\_val & (1 << \_shift - 1))
				movk	\_reg, (\_val >> \_shift) & 0xffff, LSL \_shift
			.else
				mov	\_reg, \_val & (0xffff << \_shift)
			.endif
		.endif
	.endm

	/*
	 * Helper macro to load arbitrary values into 32 or 64-bit registers
	 * which generates the best mov/movk combinations. Many base addresses
	 * are 64KB aligned the macro will eliminate updating bits 15:0 in
	 * that case
	 */
	.macro mov_imm _reg, _val
		.if (\_val) == 0
			mov	\_reg, #0
		.else
			_mov_imm16	\_reg, (\_val), 0
			_mov_imm16	\_reg, (\_val), 16
			_mov_imm16	\_reg, (\_val), 32
			_mov_imm16	\_reg, (\_val), 48
		.endif
	.endm
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
	/*
	 * Macro to mark instances where we're jumping to a function and don't
	 * expect a return. To provide the function being jumped to with
	 * additional information, we use 'bl' instruction to jump rather than
	 * 'b'.
         *
	 * Debuggers infer the location of a call from where LR points to, which
	 * is usually the instruction after 'bl'. If this macro expansion
	 * happens to be the last location in a function, that'll cause the LR
	 * to point a location beyond the function, thereby misleading debugger
	 * back trace. We therefore insert a 'nop' after the function call for
	 * debug builds, unless 'skip_nop' parameter is non-zero.
	 */
	.macro no_ret _func:req, skip_nop=0
	bl	\_func
#if DEBUG
	.ifeq \skip_nop
	nop
	.endif
#endif
	.endm

180
181
182
183
184
185
186
187
188
	/*
	 * Reserve space for a spin lock in assembly file.
	 */
	.macro define_asm_spinlock _name:req
	.align	SPINLOCK_ASM_ALIGN
	\_name:
	.space	SPINLOCK_ASM_SIZE
	.endm

189
190
191
192
193
194
#if RAS_EXTENSION
	.macro esb
	.inst	0xd503221f
	.endm
#endif

195
#endif /* ASM_MACROS_S */