xref: /arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu *
4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu */
6*91f16700Schasinglulu
7*91f16700Schasinglulu#include <arch.h>
8*91f16700Schasinglulu#include <assert_macros.S>
9*91f16700Schasinglulu#include <asm_macros.S>
10*91f16700Schasinglulu
11*91f16700Schasinglulu	.globl	amu_group0_cnt_read_internal
12*91f16700Schasinglulu	.globl	amu_group0_cnt_write_internal
13*91f16700Schasinglulu	.globl	amu_group1_cnt_read_internal
14*91f16700Schasinglulu	.globl	amu_group1_cnt_write_internal
15*91f16700Schasinglulu	.globl	amu_group1_set_evtype_internal
16*91f16700Schasinglulu
17*91f16700Schasinglulu	/* FEAT_AMUv1p1 virtualisation offset register functions */
18*91f16700Schasinglulu	.globl	amu_group0_voffset_read_internal
19*91f16700Schasinglulu	.globl	amu_group0_voffset_write_internal
20*91f16700Schasinglulu	.globl	amu_group1_voffset_read_internal
21*91f16700Schasinglulu	.globl	amu_group1_voffset_write_internal
22*91f16700Schasinglulu
23*91f16700Schasinglulu/*
24*91f16700Schasinglulu * uint64_t amu_group0_cnt_read_internal(int idx);
25*91f16700Schasinglulu *
26*91f16700Schasinglulu * Given `idx`, read the corresponding AMU counter
27*91f16700Schasinglulu * and return it in `x0`.
28*91f16700Schasinglulu */
29*91f16700Schasinglulufunc amu_group0_cnt_read_internal
30*91f16700Schasinglulu	adr	x1, 1f
31*91f16700Schasinglulu#if ENABLE_ASSERTIONS
32*91f16700Schasinglulu	/*
33*91f16700Schasinglulu	 * It can be dangerous to call this function with an
34*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
35*91f16700Schasinglulu	 */
36*91f16700Schasinglulu	tst	x0, #~3
37*91f16700Schasinglulu	ASM_ASSERT(eq)
38*91f16700Schasinglulu#endif
39*91f16700Schasinglulu	/*
40*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
41*91f16700Schasinglulu	 * in the table below.
42*91f16700Schasinglulu	 */
43*91f16700Schasinglulu	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
44*91f16700Schasinglulu#if ENABLE_BTI
45*91f16700Schasinglulu	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
46*91f16700Schasinglulu#endif
47*91f16700Schasinglulu	br	x1
48*91f16700Schasinglulu
49*91f16700Schasinglulu1:	read	AMEVCNTR00_EL0		/* index 0 */
50*91f16700Schasinglulu	read	AMEVCNTR01_EL0		/* index 1 */
51*91f16700Schasinglulu	read	AMEVCNTR02_EL0		/* index 2 */
52*91f16700Schasinglulu	read	AMEVCNTR03_EL0		/* index 3 */
53*91f16700Schasingluluendfunc amu_group0_cnt_read_internal
54*91f16700Schasinglulu
55*91f16700Schasinglulu/*
56*91f16700Schasinglulu * void amu_group0_cnt_write_internal(int idx, uint64_t val);
57*91f16700Schasinglulu *
58*91f16700Schasinglulu * Given `idx`, write `val` to the corresponding AMU counter.
59*91f16700Schasinglulu */
60*91f16700Schasinglulufunc amu_group0_cnt_write_internal
61*91f16700Schasinglulu	adr	x2, 1f
62*91f16700Schasinglulu#if ENABLE_ASSERTIONS
63*91f16700Schasinglulu	/*
64*91f16700Schasinglulu	 * It can be dangerous to call this function with an
65*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
66*91f16700Schasinglulu	 */
67*91f16700Schasinglulu	tst	x0, #~3
68*91f16700Schasinglulu	ASM_ASSERT(eq)
69*91f16700Schasinglulu#endif
70*91f16700Schasinglulu	/*
71*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
72*91f16700Schasinglulu	 * in the table below.
73*91f16700Schasinglulu	 */
74*91f16700Schasinglulu	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
75*91f16700Schasinglulu#if ENABLE_BTI
76*91f16700Schasinglulu	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
77*91f16700Schasinglulu#endif
78*91f16700Schasinglulu	br	x2
79*91f16700Schasinglulu
80*91f16700Schasinglulu1:	write	AMEVCNTR00_EL0		/* index 0 */
81*91f16700Schasinglulu	write	AMEVCNTR01_EL0		/* index 1 */
82*91f16700Schasinglulu	write	AMEVCNTR02_EL0		/* index 2 */
83*91f16700Schasinglulu	write	AMEVCNTR03_EL0		/* index 3 */
84*91f16700Schasingluluendfunc amu_group0_cnt_write_internal
85*91f16700Schasinglulu
86*91f16700Schasinglulu#if ENABLE_AMU_AUXILIARY_COUNTERS
87*91f16700Schasinglulu/*
88*91f16700Schasinglulu * uint64_t amu_group1_cnt_read_internal(int idx);
89*91f16700Schasinglulu *
90*91f16700Schasinglulu * Given `idx`, read the corresponding AMU counter
91*91f16700Schasinglulu * and return it in `x0`.
92*91f16700Schasinglulu */
93*91f16700Schasinglulufunc amu_group1_cnt_read_internal
94*91f16700Schasinglulu	adr	x1, 1f
95*91f16700Schasinglulu#if ENABLE_ASSERTIONS
96*91f16700Schasinglulu	/*
97*91f16700Schasinglulu	 * It can be dangerous to call this function with an
98*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
99*91f16700Schasinglulu	 */
100*91f16700Schasinglulu	tst	x0, #~0xF
101*91f16700Schasinglulu	ASM_ASSERT(eq)
102*91f16700Schasinglulu#endif
103*91f16700Schasinglulu	/*
104*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
105*91f16700Schasinglulu	 * in the table below.
106*91f16700Schasinglulu	 */
107*91f16700Schasinglulu	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
108*91f16700Schasinglulu#if ENABLE_BTI
109*91f16700Schasinglulu	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
110*91f16700Schasinglulu#endif
111*91f16700Schasinglulu	br	x1
112*91f16700Schasinglulu
113*91f16700Schasinglulu1:	read	AMEVCNTR10_EL0		/* index 0 */
114*91f16700Schasinglulu	read	AMEVCNTR11_EL0		/* index 1 */
115*91f16700Schasinglulu	read	AMEVCNTR12_EL0		/* index 2 */
116*91f16700Schasinglulu	read	AMEVCNTR13_EL0		/* index 3 */
117*91f16700Schasinglulu	read	AMEVCNTR14_EL0		/* index 4 */
118*91f16700Schasinglulu	read	AMEVCNTR15_EL0		/* index 5 */
119*91f16700Schasinglulu	read	AMEVCNTR16_EL0		/* index 6 */
120*91f16700Schasinglulu	read	AMEVCNTR17_EL0		/* index 7 */
121*91f16700Schasinglulu	read	AMEVCNTR18_EL0		/* index 8 */
122*91f16700Schasinglulu	read	AMEVCNTR19_EL0		/* index 9 */
123*91f16700Schasinglulu	read	AMEVCNTR1A_EL0		/* index 10 */
124*91f16700Schasinglulu	read	AMEVCNTR1B_EL0		/* index 11 */
125*91f16700Schasinglulu	read	AMEVCNTR1C_EL0		/* index 12 */
126*91f16700Schasinglulu	read	AMEVCNTR1D_EL0		/* index 13 */
127*91f16700Schasinglulu	read	AMEVCNTR1E_EL0		/* index 14 */
128*91f16700Schasinglulu	read	AMEVCNTR1F_EL0		/* index 15 */
129*91f16700Schasingluluendfunc amu_group1_cnt_read_internal
130*91f16700Schasinglulu
131*91f16700Schasinglulu/*
132*91f16700Schasinglulu * void amu_group1_cnt_write_internal(int idx, uint64_t val);
133*91f16700Schasinglulu *
134*91f16700Schasinglulu * Given `idx`, write `val` to the corresponding AMU counter.
135*91f16700Schasinglulu */
136*91f16700Schasinglulufunc amu_group1_cnt_write_internal
137*91f16700Schasinglulu	adr	x2, 1f
138*91f16700Schasinglulu#if ENABLE_ASSERTIONS
139*91f16700Schasinglulu	/*
140*91f16700Schasinglulu	 * It can be dangerous to call this function with an
141*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
142*91f16700Schasinglulu	 */
143*91f16700Schasinglulu	tst	x0, #~0xF
144*91f16700Schasinglulu	ASM_ASSERT(eq)
145*91f16700Schasinglulu#endif
146*91f16700Schasinglulu	/*
147*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
148*91f16700Schasinglulu	 * in the table below.
149*91f16700Schasinglulu	 */
150*91f16700Schasinglulu	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
151*91f16700Schasinglulu#if ENABLE_BTI
152*91f16700Schasinglulu	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
153*91f16700Schasinglulu#endif
154*91f16700Schasinglulu	br	x2
155*91f16700Schasinglulu
156*91f16700Schasinglulu1:	write	AMEVCNTR10_EL0		/* index 0 */
157*91f16700Schasinglulu	write	AMEVCNTR11_EL0		/* index 1 */
158*91f16700Schasinglulu	write	AMEVCNTR12_EL0		/* index 2 */
159*91f16700Schasinglulu	write	AMEVCNTR13_EL0		/* index 3 */
160*91f16700Schasinglulu	write	AMEVCNTR14_EL0		/* index 4 */
161*91f16700Schasinglulu	write	AMEVCNTR15_EL0		/* index 5 */
162*91f16700Schasinglulu	write	AMEVCNTR16_EL0		/* index 6 */
163*91f16700Schasinglulu	write	AMEVCNTR17_EL0		/* index 7 */
164*91f16700Schasinglulu	write	AMEVCNTR18_EL0		/* index 8 */
165*91f16700Schasinglulu	write	AMEVCNTR19_EL0		/* index 9 */
166*91f16700Schasinglulu	write	AMEVCNTR1A_EL0		/* index 10 */
167*91f16700Schasinglulu	write	AMEVCNTR1B_EL0		/* index 11 */
168*91f16700Schasinglulu	write	AMEVCNTR1C_EL0		/* index 12 */
169*91f16700Schasinglulu	write	AMEVCNTR1D_EL0		/* index 13 */
170*91f16700Schasinglulu	write	AMEVCNTR1E_EL0		/* index 14 */
171*91f16700Schasinglulu	write	AMEVCNTR1F_EL0		/* index 15 */
172*91f16700Schasingluluendfunc amu_group1_cnt_write_internal
173*91f16700Schasinglulu
174*91f16700Schasinglulu/*
175*91f16700Schasinglulu * void amu_group1_set_evtype_internal(int idx, unsigned int val);
176*91f16700Schasinglulu *
177*91f16700Schasinglulu * Program the AMU event type register indexed by `idx`
178*91f16700Schasinglulu * with the value `val`.
179*91f16700Schasinglulu */
180*91f16700Schasinglulufunc amu_group1_set_evtype_internal
181*91f16700Schasinglulu	adr	x2, 1f
182*91f16700Schasinglulu#if ENABLE_ASSERTIONS
183*91f16700Schasinglulu	/*
184*91f16700Schasinglulu	 * It can be dangerous to call this function with an
185*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
186*91f16700Schasinglulu	 */
187*91f16700Schasinglulu	tst	x0, #~0xF
188*91f16700Schasinglulu	ASM_ASSERT(eq)
189*91f16700Schasinglulu
190*91f16700Schasinglulu	/* val should be between [0, 65535] */
191*91f16700Schasinglulu	tst	x1, #~0xFFFF
192*91f16700Schasinglulu	ASM_ASSERT(eq)
193*91f16700Schasinglulu#endif
194*91f16700Schasinglulu	/*
195*91f16700Schasinglulu	 * Given `idx` calculate address of msr/ret instruction pair
196*91f16700Schasinglulu	 * in the table below.
197*91f16700Schasinglulu	 */
198*91f16700Schasinglulu	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
199*91f16700Schasinglulu#if ENABLE_BTI
200*91f16700Schasinglulu	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
201*91f16700Schasinglulu#endif
202*91f16700Schasinglulu	br	x2
203*91f16700Schasinglulu
204*91f16700Schasinglulu1:	write	AMEVTYPER10_EL0		/* index 0 */
205*91f16700Schasinglulu	write	AMEVTYPER11_EL0		/* index 1 */
206*91f16700Schasinglulu	write	AMEVTYPER12_EL0		/* index 2 */
207*91f16700Schasinglulu	write	AMEVTYPER13_EL0		/* index 3 */
208*91f16700Schasinglulu	write	AMEVTYPER14_EL0		/* index 4 */
209*91f16700Schasinglulu	write	AMEVTYPER15_EL0		/* index 5 */
210*91f16700Schasinglulu	write	AMEVTYPER16_EL0		/* index 6 */
211*91f16700Schasinglulu	write	AMEVTYPER17_EL0		/* index 7 */
212*91f16700Schasinglulu	write	AMEVTYPER18_EL0		/* index 8 */
213*91f16700Schasinglulu	write	AMEVTYPER19_EL0		/* index 9 */
214*91f16700Schasinglulu	write	AMEVTYPER1A_EL0		/* index 10 */
215*91f16700Schasinglulu	write	AMEVTYPER1B_EL0		/* index 11 */
216*91f16700Schasinglulu	write	AMEVTYPER1C_EL0		/* index 12 */
217*91f16700Schasinglulu	write	AMEVTYPER1D_EL0		/* index 13 */
218*91f16700Schasinglulu	write	AMEVTYPER1E_EL0		/* index 14 */
219*91f16700Schasinglulu	write	AMEVTYPER1F_EL0		/* index 15 */
220*91f16700Schasingluluendfunc amu_group1_set_evtype_internal
221*91f16700Schasinglulu#endif
222*91f16700Schasinglulu
223*91f16700Schasinglulu/*
224*91f16700Schasinglulu * Accessor functions for virtual offset registers added with FEAT_AMUv1p1
225*91f16700Schasinglulu */
226*91f16700Schasinglulu
227*91f16700Schasinglulu/*
228*91f16700Schasinglulu * uint64_t amu_group0_voffset_read_internal(int idx);
229*91f16700Schasinglulu *
230*91f16700Schasinglulu * Given `idx`, read the corresponding AMU virtual offset register
231*91f16700Schasinglulu * and return it in `x0`.
232*91f16700Schasinglulu */
233*91f16700Schasinglulufunc amu_group0_voffset_read_internal
234*91f16700Schasinglulu	adr	x1, 1f
235*91f16700Schasinglulu#if ENABLE_ASSERTIONS
236*91f16700Schasinglulu	/*
237*91f16700Schasinglulu	 * It can be dangerous to call this function with an
238*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
239*91f16700Schasinglulu	 */
240*91f16700Schasinglulu	tst	x0, #~3
241*91f16700Schasinglulu	ASM_ASSERT(eq)
242*91f16700Schasinglulu	/* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */
243*91f16700Schasinglulu	cmp	x0, #1
244*91f16700Schasinglulu	ASM_ASSERT(ne)
245*91f16700Schasinglulu#endif
246*91f16700Schasinglulu	/*
247*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
248*91f16700Schasinglulu	 * in the table below.
249*91f16700Schasinglulu	 */
250*91f16700Schasinglulu	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
251*91f16700Schasinglulu#if ENABLE_BTI
252*91f16700Schasinglulu	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
253*91f16700Schasinglulu#endif
254*91f16700Schasinglulu	br	x1
255*91f16700Schasinglulu
256*91f16700Schasinglulu1:	read	AMEVCNTVOFF00_EL2	/* index 0 */
257*91f16700Schasinglulu	.skip	8			/* AMEVCNTVOFF01_EL2 does not exist */
258*91f16700Schasinglulu#if ENABLE_BTI
259*91f16700Schasinglulu	.skip	4
260*91f16700Schasinglulu#endif
261*91f16700Schasinglulu	read	AMEVCNTVOFF02_EL2	/* index 2 */
262*91f16700Schasinglulu	read	AMEVCNTVOFF03_EL2	/* index 3 */
263*91f16700Schasingluluendfunc amu_group0_voffset_read_internal
264*91f16700Schasinglulu
265*91f16700Schasinglulu/*
266*91f16700Schasinglulu * void amu_group0_voffset_write_internal(int idx, uint64_t val);
267*91f16700Schasinglulu *
268*91f16700Schasinglulu * Given `idx`, write `val` to the corresponding AMU virtual offset register.
269*91f16700Schasinglulu */
270*91f16700Schasinglulufunc amu_group0_voffset_write_internal
271*91f16700Schasinglulu	adr	x2, 1f
272*91f16700Schasinglulu#if ENABLE_ASSERTIONS
273*91f16700Schasinglulu	/*
274*91f16700Schasinglulu	 * It can be dangerous to call this function with an
275*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
276*91f16700Schasinglulu	 */
277*91f16700Schasinglulu	tst	x0, #~3
278*91f16700Schasinglulu	ASM_ASSERT(eq)
279*91f16700Schasinglulu	/* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */
280*91f16700Schasinglulu	cmp	x0, #1
281*91f16700Schasinglulu	ASM_ASSERT(ne)
282*91f16700Schasinglulu#endif
283*91f16700Schasinglulu	/*
284*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
285*91f16700Schasinglulu	 * in the table below.
286*91f16700Schasinglulu	 */
287*91f16700Schasinglulu	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
288*91f16700Schasinglulu#if ENABLE_BTI
289*91f16700Schasinglulu	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
290*91f16700Schasinglulu#endif
291*91f16700Schasinglulu	br	x2
292*91f16700Schasinglulu
293*91f16700Schasinglulu1:	write	AMEVCNTVOFF00_EL2	/* index 0 */
294*91f16700Schasinglulu	.skip	8			/* AMEVCNTVOFF01_EL2 does not exist */
295*91f16700Schasinglulu#if ENABLE_BTI
296*91f16700Schasinglulu	.skip	4
297*91f16700Schasinglulu#endif
298*91f16700Schasinglulu	write	AMEVCNTVOFF02_EL2	/* index 2 */
299*91f16700Schasinglulu	write	AMEVCNTVOFF03_EL2	/* index 3 */
300*91f16700Schasingluluendfunc amu_group0_voffset_write_internal
301*91f16700Schasinglulu
302*91f16700Schasinglulu#if ENABLE_AMU_AUXILIARY_COUNTERS
303*91f16700Schasinglulu/*
304*91f16700Schasinglulu * uint64_t amu_group1_voffset_read_internal(int idx);
305*91f16700Schasinglulu *
306*91f16700Schasinglulu * Given `idx`, read the corresponding AMU virtual offset register
307*91f16700Schasinglulu * and return it in `x0`.
308*91f16700Schasinglulu */
309*91f16700Schasinglulufunc amu_group1_voffset_read_internal
310*91f16700Schasinglulu	adr	x1, 1f
311*91f16700Schasinglulu#if ENABLE_ASSERTIONS
312*91f16700Schasinglulu	/*
313*91f16700Schasinglulu	 * It can be dangerous to call this function with an
314*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
315*91f16700Schasinglulu	 */
316*91f16700Schasinglulu	tst	x0, #~0xF
317*91f16700Schasinglulu	ASM_ASSERT(eq)
318*91f16700Schasinglulu#endif
319*91f16700Schasinglulu	/*
320*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
321*91f16700Schasinglulu	 * in the table below.
322*91f16700Schasinglulu	 */
323*91f16700Schasinglulu	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
324*91f16700Schasinglulu#if ENABLE_BTI
325*91f16700Schasinglulu	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
326*91f16700Schasinglulu#endif
327*91f16700Schasinglulu	br	x1
328*91f16700Schasinglulu
329*91f16700Schasinglulu1:	read	AMEVCNTVOFF10_EL2	/* index 0 */
330*91f16700Schasinglulu	read	AMEVCNTVOFF11_EL2	/* index 1 */
331*91f16700Schasinglulu	read	AMEVCNTVOFF12_EL2	/* index 2 */
332*91f16700Schasinglulu	read	AMEVCNTVOFF13_EL2	/* index 3 */
333*91f16700Schasinglulu	read	AMEVCNTVOFF14_EL2	/* index 4 */
334*91f16700Schasinglulu	read	AMEVCNTVOFF15_EL2	/* index 5 */
335*91f16700Schasinglulu	read	AMEVCNTVOFF16_EL2	/* index 6 */
336*91f16700Schasinglulu	read	AMEVCNTVOFF17_EL2	/* index 7 */
337*91f16700Schasinglulu	read	AMEVCNTVOFF18_EL2	/* index 8 */
338*91f16700Schasinglulu	read	AMEVCNTVOFF19_EL2	/* index 9 */
339*91f16700Schasinglulu	read	AMEVCNTVOFF1A_EL2	/* index 10 */
340*91f16700Schasinglulu	read	AMEVCNTVOFF1B_EL2	/* index 11 */
341*91f16700Schasinglulu	read	AMEVCNTVOFF1C_EL2	/* index 12 */
342*91f16700Schasinglulu	read	AMEVCNTVOFF1D_EL2	/* index 13 */
343*91f16700Schasinglulu	read	AMEVCNTVOFF1E_EL2	/* index 14 */
344*91f16700Schasinglulu	read	AMEVCNTVOFF1F_EL2	/* index 15 */
345*91f16700Schasingluluendfunc amu_group1_voffset_read_internal
346*91f16700Schasinglulu
347*91f16700Schasinglulu/*
348*91f16700Schasinglulu * void amu_group1_voffset_write_internal(int idx, uint64_t val);
349*91f16700Schasinglulu *
350*91f16700Schasinglulu * Given `idx`, write `val` to the corresponding AMU virtual offset register.
351*91f16700Schasinglulu */
352*91f16700Schasinglulufunc amu_group1_voffset_write_internal
353*91f16700Schasinglulu	adr	x2, 1f
354*91f16700Schasinglulu#if ENABLE_ASSERTIONS
355*91f16700Schasinglulu	/*
356*91f16700Schasinglulu	 * It can be dangerous to call this function with an
357*91f16700Schasinglulu	 * out of bounds index.  Ensure `idx` is valid.
358*91f16700Schasinglulu	 */
359*91f16700Schasinglulu	tst	x0, #~0xF
360*91f16700Schasinglulu	ASM_ASSERT(eq)
361*91f16700Schasinglulu#endif
362*91f16700Schasinglulu	/*
363*91f16700Schasinglulu	 * Given `idx` calculate address of mrs/ret instruction pair
364*91f16700Schasinglulu	 * in the table below.
365*91f16700Schasinglulu	 */
366*91f16700Schasinglulu	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
367*91f16700Schasinglulu#if ENABLE_BTI
368*91f16700Schasinglulu	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
369*91f16700Schasinglulu#endif
370*91f16700Schasinglulu	br	x2
371*91f16700Schasinglulu
372*91f16700Schasinglulu1:	write	AMEVCNTVOFF10_EL2	/* index 0 */
373*91f16700Schasinglulu	write	AMEVCNTVOFF11_EL2	/* index 1 */
374*91f16700Schasinglulu	write	AMEVCNTVOFF12_EL2	/* index 2 */
375*91f16700Schasinglulu	write	AMEVCNTVOFF13_EL2	/* index 3 */
376*91f16700Schasinglulu	write	AMEVCNTVOFF14_EL2	/* index 4 */
377*91f16700Schasinglulu	write	AMEVCNTVOFF15_EL2	/* index 5 */
378*91f16700Schasinglulu	write	AMEVCNTVOFF16_EL2	/* index 6 */
379*91f16700Schasinglulu	write	AMEVCNTVOFF17_EL2	/* index 7 */
380*91f16700Schasinglulu	write	AMEVCNTVOFF18_EL2	/* index 8 */
381*91f16700Schasinglulu	write	AMEVCNTVOFF19_EL2	/* index 9 */
382*91f16700Schasinglulu	write	AMEVCNTVOFF1A_EL2	/* index 10 */
383*91f16700Schasinglulu	write	AMEVCNTVOFF1B_EL2	/* index 11 */
384*91f16700Schasinglulu	write	AMEVCNTVOFF1C_EL2	/* index 12 */
385*91f16700Schasinglulu	write	AMEVCNTVOFF1D_EL2	/* index 13 */
386*91f16700Schasinglulu	write	AMEVCNTVOFF1E_EL2	/* index 14 */
387*91f16700Schasinglulu	write	AMEVCNTVOFF1F_EL2	/* index 15 */
388*91f16700Schasingluluendfunc amu_group1_voffset_write_internal
389*91f16700Schasinglulu#endif
390