aboutsummaryrefslogtreecommitdiff
path: root/lib/cpus/aarch64/cortex_a75.S
blob: e66ad06670eb65b4df676164a67e0b0b2c706f1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <arch.h>
#include <asm_macros.S>
#include <bl_common.h>
#include <cpu_macros.S>
#include <plat_macros.S>
#include <cortex_a75.h>

	.globl	cortex_a75_amu_cnt_read
	.globl	cortex_a75_amu_cnt_write
	.globl	cortex_a75_amu_read_cpuamcntenset_el0
	.globl	cortex_a75_amu_read_cpuamcntenclr_el0
	.globl	cortex_a75_amu_write_cpuamcntenset_el0
	.globl	cortex_a75_amu_write_cpuamcntenclr_el0

/*
 * uint64_t cortex_a75_amu_cnt_read(int idx);
 *
 * Given `idx`, read the corresponding AMU counter
 * and return it in `x0`.
 */
func cortex_a75_amu_cnt_read
	adr	x1, 1f
	lsl	x0, x0, #3
	add	x1, x1, x0
	br	x1

1:
	mrs	x0, CPUAMEVCNTR0_EL0
	ret
	mrs	x0, CPUAMEVCNTR1_EL0
	ret
	mrs	x0, CPUAMEVCNTR2_EL0
	ret
	mrs	x0, CPUAMEVCNTR3_EL0
	ret
	mrs	x0, CPUAMEVCNTR4_EL0
	ret
endfunc cortex_a75_amu_cnt_read

/*
 * void cortex_a75_amu_cnt_write(int idx, uint64_t val);
 *
 * Given `idx`, write `val` to the corresponding AMU counter.
 */
func cortex_a75_amu_cnt_write
	adr	x2, 1f
	lsl	x0, x0, #3
	add	x2, x2, x0
	br	x2

1:
	msr	CPUAMEVCNTR0_EL0, x0
	ret
	msr	CPUAMEVCNTR1_EL0, x0
	ret
	msr	CPUAMEVCNTR2_EL0, x0
	ret
	msr	CPUAMEVCNTR3_EL0, x0
	ret
	msr	CPUAMEVCNTR4_EL0, x0
	ret
endfunc cortex_a75_amu_cnt_write

/*
 * unsigned int cortex_a75_amu_read_cpuamcntenset_el0(void);
 *
 * Read the `CPUAMCNTENSET_EL0` CPU register and return
 * it in `x0`.
 */
func cortex_a75_amu_read_cpuamcntenset_el0
	mrs	x0, CPUAMCNTENSET_EL0
	ret
endfunc cortex_a75_amu_read_cpuamcntenset_el0

/*
 * unsigned int cortex_a75_amu_read_cpuamcntenclr_el0(void);
 *
 * Read the `CPUAMCNTENCLR_EL0` CPU register and return
 * it in `x0`.
 */
func cortex_a75_amu_read_cpuamcntenclr_el0
	mrs	x0, CPUAMCNTENCLR_EL0
	ret
endfunc cortex_a75_amu_read_cpuamcntenclr_el0

/*
 * void cortex_a75_amu_write_cpuamcntenset_el0(unsigned int mask);
 *
 * Write `mask` to the `CPUAMCNTENSET_EL0` CPU register.
 */
func cortex_a75_amu_write_cpuamcntenset_el0
	msr	CPUAMCNTENSET_EL0, x0
	ret
endfunc cortex_a75_amu_write_cpuamcntenset_el0

/*
 * void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask);
 *
 * Write `mask` to the `CPUAMCNTENCLR_EL0` CPU register.
 */
func cortex_a75_amu_write_cpuamcntenclr_el0
	mrs	x0, CPUAMCNTENCLR_EL0
	ret
endfunc cortex_a75_amu_write_cpuamcntenclr_el0

func cortex_a75_reset_func
#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
	mrs	x0, id_aa64pfr0_el1
	ubfx	x0, x0, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH
	/*
	 * If the field equals to 1 then branch targets trained in one
	 * context cannot affect speculative execution in a different context.
	 */
	cmp	x0, #1
	beq	1f

	adr	x0, workaround_bpiall_vbar0_runtime_exceptions
	msr	vbar_el3, x0
1:
#endif

#if ENABLE_AMU
	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
	mrs	x0, actlr_el3
	orr	x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT
	msr	actlr_el3, x0
	isb

	/* Make sure accesses from EL0/EL1 are not trapped to EL2 */
	mrs	x0, actlr_el2
	orr	x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT
	msr	actlr_el2, x0
	isb

	/* Enable group0 counters */
	mov	x0, #CORTEX_A75_AMU_GROUP0_MASK
	msr	CPUAMCNTENSET_EL0, x0
	isb

	/* Enable group1 counters */
	mov	x0, #CORTEX_A75_AMU_GROUP1_MASK
	msr	CPUAMCNTENSET_EL0, x0
	isb
#endif
	ret
endfunc cortex_a75_reset_func

	/* ---------------------------------------------
	 * HW will do the cache maintenance while powering down
	 * ---------------------------------------------
	 */
func cortex_a75_core_pwr_dwn
	/* ---------------------------------------------
	 * Enable CPU power down bit in power control register
	 * ---------------------------------------------
	 */
	mrs	x0, CORTEX_A75_CPUPWRCTLR_EL1
	orr	x0, x0, #CORTEX_A75_CORE_PWRDN_EN_MASK
	msr	CORTEX_A75_CPUPWRCTLR_EL1, x0
	isb
	ret
endfunc cortex_a75_core_pwr_dwn

	/* ---------------------------------------------
	 * This function provides cortex_a75 specific
	 * register information for crash reporting.
	 * It needs to return with x6 pointing to
	 * a list of register names in ascii and
	 * x8 - x15 having values of registers to be
	 * reported.
	 * ---------------------------------------------
	 */
.section .rodata.cortex_a75_regs, "aS"
cortex_a75_regs:  /* The ascii list of register names to be reported */
	.asciz	"cpuectlr_el1", ""

func cortex_a75_cpu_reg_dump
	adr	x6, cortex_a75_regs
	mrs	x8, CORTEX_A75_CPUECTLR_EL1
	ret
endfunc cortex_a75_cpu_reg_dump

declare_cpu_ops cortex_a75, CORTEX_A75_MIDR, \
	cortex_a75_reset_func, \
	cortex_a75_core_pwr_dwn