blob: 106a84971047c8557922b6af1ac02f57be0d7315 [file] [log] [blame]
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +01001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <arch.h>
7#include <arch_features.h>
8#include <arch_helpers.h>
9#include <assert.h>
10#include <debug.h>
Arunachalam Ganapathyc1136a82023-04-12 15:24:44 +010011#include <stdlib.h>
Arunachalam Ganapathy73949a22023-06-05 12:01:05 +010012#include <sync.h>
Arunachalam Ganapathyf3697172023-09-04 15:04:46 +010013#include <lib/extensions/fpu.h>
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010014#include <lib/extensions/sve.h>
15
Arunachalam Ganapathy1768e592023-05-23 13:28:38 +010016#include <host_realm_simd.h>
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010017#include <host_shared_data.h>
18
Arunachalam Ganapathyc1136a82023-04-12 15:24:44 +010019#define RL_SVE_OP_ARRAYSIZE 512U
20#define SVE_TEST_ITERATIONS 4U
21
22static int rl_sve_op_1[RL_SVE_OP_ARRAYSIZE];
23static int rl_sve_op_2[RL_SVE_OP_ARRAYSIZE];
24
Arunachalam Ganapathy03589972023-08-30 11:04:51 +010025static sve_z_regs_t rl_sve_z_regs_write;
Arunachalam Ganapathyf3697172023-09-04 15:04:46 +010026static sve_z_regs_t rl_sve_z_regs_read;
27
28static sve_p_regs_t rl_sve_p_regs_write;
29static sve_p_regs_t rl_sve_p_regs_read;
30
31static sve_ffr_regs_t rl_sve_ffr_regs_write;
32static sve_ffr_regs_t rl_sve_ffr_regs_read;
33
34static fpu_cs_regs_t rl_fpu_cs_regs_write;
35static fpu_cs_regs_t rl_fpu_cs_regs_read;
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +010036
Arunachalam Ganapathy73949a22023-06-05 12:01:05 +010037static int volatile realm_got_undef_abort;
38
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010039/* Returns the maximum supported VL. This test is called only by sve Realm */
40bool test_realm_sve_rdvl(void)
41{
Shruti Gupta550e3e82023-08-16 13:20:11 +010042 host_shared_data_t *sd = realm_get_my_shared_structure();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010043 struct sve_cmd_rdvl *output;
44
45 assert(is_armv8_2_sve_present());
46
47 output = (struct sve_cmd_rdvl *)sd->realm_cmd_output_buffer;
48 memset((void *)output, 0, sizeof(struct sve_cmd_rdvl));
49
50 sve_config_vq(SVE_VQ_ARCH_MAX);
Arunachalam Ganapathy03589972023-08-30 11:04:51 +010051 output->rdvl = sve_rdvl_1();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010052
53 return true;
54}
55
56/*
57 * Reads and returns the ID_AA64PFR0_EL1 and ID_AA64ZFR0_EL1 registers
58 * This test could be called from sve or non-sve Realm
59 */
60bool test_realm_sve_read_id_registers(void)
61{
Shruti Gupta550e3e82023-08-16 13:20:11 +010062 host_shared_data_t *sd = realm_get_my_shared_structure();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010063 struct sve_cmd_id_regs *output;
64
65 output = (struct sve_cmd_id_regs *)sd->realm_cmd_output_buffer;
66 memset((void *)output, 0, sizeof(struct sve_cmd_id_regs));
67
68 realm_printf("Realm: reading ID registers: ID_AA64PFR0_EL1, "
69 " ID_AA64ZFR0_EL1\n");
70 output->id_aa64pfr0_el1 = read_id_aa64pfr0_el1();
71 output->id_aa64zfr0_el1 = read_id_aa64zfr0_el1();
72
73 return true;
74}
75
76/*
77 * Probes all VLs and return the bitmap with the bit set for each corresponding
78 * valid VQ. This test is called only by sve Realm
79 */
80bool test_realm_sve_probe_vl(void)
81{
Shruti Gupta550e3e82023-08-16 13:20:11 +010082 host_shared_data_t *sd = realm_get_my_shared_structure();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010083 struct sve_cmd_probe_vl *output;
84
85 assert(is_armv8_2_sve_present());
86
87 output = (struct sve_cmd_probe_vl *)&sd->realm_cmd_output_buffer;
88 memset((void *)output, 0, sizeof(struct sve_cmd_probe_vl));
89
90 /* Probe all VLs */
91 output->vl_bitmap = sve_probe_vl(SVE_VQ_ARCH_MAX);
92
93 return true;
94}
Arunachalam Ganapathyc1136a82023-04-12 15:24:44 +010095
96bool test_realm_sve_ops(void)
97{
98 int val, i;
99
100 assert(is_armv8_2_sve_present());
101
102 /* get at random value to do sve_subtract */
103 val = rand();
104 for (i = 0; i < RL_SVE_OP_ARRAYSIZE; i++) {
105 rl_sve_op_1[i] = val - i;
106 rl_sve_op_2[i] = 1;
107 }
108
109 for (i = 0; i < SVE_TEST_ITERATIONS; i++) {
110 /* Config Realm with random SVE length */
111 sve_config_vq(SVE_GET_RANDOM_VQ);
112
113 /* Perform SVE operations, without world switch */
114 sve_subtract_arrays(rl_sve_op_1, rl_sve_op_1, rl_sve_op_2,
115 RL_SVE_OP_ARRAYSIZE);
116 }
117
118 /* Check result of SVE operations. */
119 for (i = 0; i < RL_SVE_OP_ARRAYSIZE; i++) {
120 if (rl_sve_op_1[i] != (val - i - SVE_TEST_ITERATIONS)) {
121 realm_printf("Realm: SVE ops failed\n");
122 return false;
123 }
124 }
125
126 return true;
127}
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +0100128
129/* Fill SVE Z registers with known pattern */
130bool test_realm_sve_fill_regs(void)
131{
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +0100132 assert(is_armv8_2_sve_present());
133
134 /* Config Realm with max SVE length */
135 sve_config_vq(SVE_VQ_ARCH_MAX);
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +0100136
Arunachalam Ganapathyf3697172023-09-04 15:04:46 +0100137 sve_z_regs_write_rand(&rl_sve_z_regs_write);
138 sve_p_regs_write_rand(&rl_sve_p_regs_write);
139 sve_ffr_regs_write_rand(&rl_sve_ffr_regs_write);
140
141 /* fpcr, fpsr common registers */
142 fpu_cs_regs_write_rand(&rl_fpu_cs_regs_write);
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +0100143
144 return true;
145}
Arunachalam Ganapathy73949a22023-06-05 12:01:05 +0100146
Arunachalam Ganapathyf3697172023-09-04 15:04:46 +0100147/* Compare SVE Z registers with last filled in values */
148bool test_realm_sve_cmp_regs(void)
149{
150 bool rc = true;
151 uint64_t bit_map;
152
153 assert(is_armv8_2_sve_present());
154
155 memset(&rl_sve_z_regs_read, 0, sizeof(rl_sve_z_regs_read));
156 memset(&rl_sve_p_regs_read, 0, sizeof(rl_sve_p_regs_read));
157 memset(&rl_sve_ffr_regs_read, 0, sizeof(rl_sve_ffr_regs_read));
158
159 /* Read all SVE registers */
160 sve_z_regs_read(&rl_sve_z_regs_read);
161 sve_p_regs_read(&rl_sve_p_regs_read);
162 sve_ffr_regs_read(&rl_sve_ffr_regs_read);
163
164 /* Compare the read values with last written values */
165 bit_map = sve_z_regs_compare(&rl_sve_z_regs_write, &rl_sve_z_regs_read);
166 if (bit_map) {
167 rc = false;
168 }
169
170 bit_map = sve_p_regs_compare(&rl_sve_p_regs_write, &rl_sve_p_regs_read);
171 if (bit_map) {
172 rc = false;
173 }
174
175 bit_map = sve_ffr_regs_compare(&rl_sve_ffr_regs_write,
176 &rl_sve_ffr_regs_read);
177 if (bit_map) {
178 rc = false;
179 }
180
181 /* fpcr, fpsr common registers */
182 fpu_cs_regs_read(&rl_fpu_cs_regs_read);
183 if (fpu_cs_regs_compare(&rl_fpu_cs_regs_write, &rl_fpu_cs_regs_read)) {
184 ERROR("Realm: FPCR/FPSR mismatch\n");
185 rc = false;
186 }
187
188 return rc;
189}
190
Arunachalam Ganapathy73949a22023-06-05 12:01:05 +0100191static bool realm_sync_exception_handler(void)
192{
193 uint64_t esr_el1 = read_esr_el1();
194
195 if (EC_BITS(esr_el1) == EC_UNKNOWN) {
196 realm_printf("Realm: received undefined abort. "
197 "esr_el1: 0x%llx elr_el1: 0x%llx\n",
198 esr_el1, read_elr_el1());
199 realm_got_undef_abort++;
200 }
201
202 return true;
203}
204
205/* Check if Realm gets undefined abort when it accesses SVE functionality */
206bool test_realm_sve_undef_abort(void)
207{
208 realm_got_undef_abort = 0UL;
209
210 /* install exception handler to catch undef abort */
211 register_custom_sync_exception_handler(&realm_sync_exception_handler);
212 (void)sve_rdvl_1();
213 unregister_custom_sync_exception_handler();
214
215 if (realm_got_undef_abort == 0UL) {
216 return false;
217 }
218
219 return true;
220}
Arunachalam Ganapathy1768e592023-05-23 13:28:38 +0100221
222/* Reads and returns the ID_AA64PFR1_EL1 and ID_AA64SMFR0_EL1 registers */
223bool test_realm_sme_read_id_registers(void)
224{
225 host_shared_data_t *sd = realm_get_my_shared_structure();
226 struct sme_cmd_id_regs *output;
227
228 output = (struct sme_cmd_id_regs *)sd->realm_cmd_output_buffer;
229 memset((void *)output, 0, sizeof(struct sme_cmd_id_regs));
230
231 realm_printf("Realm: reading ID registers: ID_AA64PFR1_EL1, "
232 " ID_AA64SMFR0_EL1\n");
233
234 output->id_aa64pfr1_el1 = read_id_aa64pfr1_el1();
235 output->id_aa64smfr0_el1 = read_id_aa64smfr0_el1();
236
237 return true;
238}
239
240/* Check if Realm gets undefined abort when it access SME functionality */
241bool test_realm_sme_undef_abort(void)
242{
243 realm_got_undef_abort = 0UL;
244
245 /* install exception handler to catch undef abort */
246 register_custom_sync_exception_handler(&realm_sync_exception_handler);
247 (void)read_svcr();
248 unregister_custom_sync_exception_handler();
249
250 if (realm_got_undef_abort == 0UL) {
251 return false;
252 }
253
254 return true;
255}