blob: 2c0e38f00e880cd48afc3f1e6dd3f723f965ac61 [file] [log] [blame]
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +01001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_features.h>
8#include <arch_helpers.h>
9#include <assert.h>
10#include <debug.h>
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010011#include <lib/extensions/fpu.h>
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010012#include <lib/extensions/sve.h>
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010013#include <tftf_lib.h>
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010014
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010015static uint8_t zero_mem[512];
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010016
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010017#define sve_traps_save_disable(flags) \
18 do { \
19 if (IS_IN_EL2()) { \
20 flags = read_cptr_el2(); \
21 write_cptr_el2(flags & ~(CPTR_EL2_TZ_BIT)); \
22 } else { \
23 flags = read_cpacr_el1(); \
24 write_cpacr_el1(flags | \
25 CPACR_EL1_ZEN(CPACR_EL1_ZEN_TRAP_NONE));\
26 } \
27 isb(); \
28 } while (false)
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +010029
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010030#define sve_traps_restore(flags) \
31 do { \
32 if (IS_IN_EL2()) { \
33 write_cptr_el2(flags); \
34 } else { \
35 write_cpacr_el1(flags); \
36 } \
37 isb(); \
38 } while (false)
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010039
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010040static void config_vq(uint8_t sve_vq)
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010041{
42 u_register_t zcr_elx;
43
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010044 if (IS_IN_EL2()) {
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010045 zcr_elx = read_zcr_el2();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010046 zcr_elx &= ~(MASK(ZCR_EL2_SVE_VL));
47 zcr_elx |= INPLACE(ZCR_EL2_SVE_VL, sve_vq);
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010048 write_zcr_el2(zcr_elx);
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010049 } else {
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010050 zcr_elx = read_zcr_el1();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010051 zcr_elx &= ~(MASK(ZCR_EL1_SVE_VL));
52 zcr_elx |= INPLACE(ZCR_EL1_SVE_VL, sve_vq);
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010053 write_zcr_el1(zcr_elx);
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010054 }
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +010055 isb();
56}
57
58/* Returns the SVE implemented VL in bytes (constrained by ZCR_EL3.LEN) */
59uint64_t sve_rdvl_1(void)
60{
61 uint64_t vl;
62 unsigned long flags;
63
64 sve_traps_save_disable(flags);
65
66 __asm__ volatile(
67 ".arch_extension sve\n"
68 "rdvl %0, #1;"
69 ".arch_extension nosve\n"
70 : "=r" (vl)
71 );
72
73 sve_traps_restore(flags);
74 return vl;
75}
76
77uint64_t sve_read_zcr_elx(void)
78{
79 unsigned long flags;
80 uint64_t rval;
81
82 sve_traps_save_disable(flags);
83
84 if (IS_IN_EL2()) {
85 rval = read_zcr_el2();
86 } else {
87 rval = read_zcr_el1();
88 }
89
90 sve_traps_restore(flags);
91
92 return rval;
93}
94
95void sve_write_zcr_elx(uint64_t rval)
96{
97 unsigned long flags;
98
99 sve_traps_save_disable(flags);
100
101 if (IS_IN_EL2()) {
102 write_zcr_el2(rval);
103 } else {
104 write_zcr_el1(rval);
105 }
106 isb();
107
108 sve_traps_restore(flags);
109
110 return;
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100111}
112
113/* Set the SVE vector length in the current EL's ZCR_ELx register */
114void sve_config_vq(uint8_t sve_vq)
115{
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100116 unsigned long flags;
117
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100118 assert(is_armv8_2_sve_present());
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100119 sve_traps_save_disable(flags);
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100120
121 /* cap vq to arch supported max value */
122 if (sve_vq > SVE_VQ_ARCH_MAX) {
123 sve_vq = SVE_VQ_ARCH_MAX;
124 }
125
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100126 config_vq(sve_vq);
127
128 sve_traps_restore(flags);
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100129}
130
131/*
132 * Probes all valid vector length upto 'sve_max_vq'. Configures ZCR_ELx with 0
133 * to 'sve_max_vq'. And for each step, call sve_rdvl to get the vector length.
134 * Convert the vector length to VQ and set the bit corresponding to the VQ.
135 * Returns:
136 * bitmap corresponding to each support VL
137 */
138uint32_t sve_probe_vl(uint8_t sve_max_vq)
139{
140 uint32_t vl_bitmap = 0;
141 uint8_t vq, rdvl_vq;
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100142 unsigned long flags;
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100143
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100144 sve_traps_save_disable(flags);
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100145
146 /* cap vq to arch supported max value */
147 if (sve_max_vq > SVE_VQ_ARCH_MAX) {
148 sve_max_vq = SVE_VQ_ARCH_MAX;
149 }
150
151 for (vq = 0; vq <= sve_max_vq; vq++) {
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100152 config_vq(vq);
Arunachalam Ganapathy03589972023-08-30 11:04:51 +0100153 rdvl_vq = SVE_VL_TO_VQ(sve_rdvl_1());
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100154 if (vl_bitmap & BIT_32(rdvl_vq)) {
155 continue;
156 }
157 vl_bitmap |= BIT_32(rdvl_vq);
158 }
159
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100160 sve_traps_restore(flags);
161
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100162 return vl_bitmap;
163}
Arunachalam Ganapathyd179ddc2023-04-12 10:41:42 +0100164
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100165/*
166 * Write SVE Z[0-31] registers passed in 'z_regs' for Normal SVE or Streaming
167 * SVE mode
168 */
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100169static void z_regs_write(const sve_z_regs_t *z_regs)
Arunachalam Ganapathyd179ddc2023-04-12 10:41:42 +0100170{
Arunachalam Ganapathyd179ddc2023-04-12 10:41:42 +0100171 __asm__ volatile(
172 ".arch_extension sve\n"
173 fill_sve_helper(0)
174 fill_sve_helper(1)
175 fill_sve_helper(2)
176 fill_sve_helper(3)
177 fill_sve_helper(4)
178 fill_sve_helper(5)
179 fill_sve_helper(6)
180 fill_sve_helper(7)
181 fill_sve_helper(8)
182 fill_sve_helper(9)
183 fill_sve_helper(10)
184 fill_sve_helper(11)
185 fill_sve_helper(12)
186 fill_sve_helper(13)
187 fill_sve_helper(14)
188 fill_sve_helper(15)
189 fill_sve_helper(16)
190 fill_sve_helper(17)
191 fill_sve_helper(18)
192 fill_sve_helper(19)
193 fill_sve_helper(20)
194 fill_sve_helper(21)
195 fill_sve_helper(22)
196 fill_sve_helper(23)
197 fill_sve_helper(24)
198 fill_sve_helper(25)
199 fill_sve_helper(26)
200 fill_sve_helper(27)
201 fill_sve_helper(28)
202 fill_sve_helper(29)
203 fill_sve_helper(30)
204 fill_sve_helper(31)
205 ".arch_extension nosve\n"
Arunachalam Ganapathy03589972023-08-30 11:04:51 +0100206 : : "r" (z_regs));
Arunachalam Ganapathyd179ddc2023-04-12 10:41:42 +0100207}
208
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100209/*
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100210 * Write SVE Z[0-31] registers passed in 'z_regs' for Normal SVE or Streaming
211 * SVE mode
212 */
213void sve_z_regs_write(const sve_z_regs_t *z_regs)
214{
215 unsigned long flags;
216
217 sve_traps_save_disable(flags);
218 z_regs_write(z_regs);
219 sve_traps_restore(flags);
220}
221
222/*
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100223 * Read SVE Z[0-31] and store it in 'zregs' for Normal SVE or Streaming SVE mode
224 */
Arunachalam Ganapathy03589972023-08-30 11:04:51 +0100225void sve_z_regs_read(sve_z_regs_t *z_regs)
Arunachalam Ganapathyd179ddc2023-04-12 10:41:42 +0100226{
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100227 unsigned long flags;
228
229 sve_traps_save_disable(flags);
230
Arunachalam Ganapathyd179ddc2023-04-12 10:41:42 +0100231 __asm__ volatile(
232 ".arch_extension sve\n"
233 read_sve_helper(0)
234 read_sve_helper(1)
235 read_sve_helper(2)
236 read_sve_helper(3)
237 read_sve_helper(4)
238 read_sve_helper(5)
239 read_sve_helper(6)
240 read_sve_helper(7)
241 read_sve_helper(8)
242 read_sve_helper(9)
243 read_sve_helper(10)
244 read_sve_helper(11)
245 read_sve_helper(12)
246 read_sve_helper(13)
247 read_sve_helper(14)
248 read_sve_helper(15)
249 read_sve_helper(16)
250 read_sve_helper(17)
251 read_sve_helper(18)
252 read_sve_helper(19)
253 read_sve_helper(20)
254 read_sve_helper(21)
255 read_sve_helper(22)
256 read_sve_helper(23)
257 read_sve_helper(24)
258 read_sve_helper(25)
259 read_sve_helper(26)
260 read_sve_helper(27)
261 read_sve_helper(28)
262 read_sve_helper(29)
263 read_sve_helper(30)
264 read_sve_helper(31)
265 ".arch_extension nosve\n"
Arunachalam Ganapathy03589972023-08-30 11:04:51 +0100266 : : "r" (z_regs));
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100267
268 sve_traps_restore(flags);
Arunachalam Ganapathyd179ddc2023-04-12 10:41:42 +0100269}
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100270
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100271static void p_regs_write(const sve_p_regs_t *p_regs)
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100272{
273 __asm__ volatile(
274 ".arch_extension sve\n"
275 fill_sve_p_helper(0)
276 fill_sve_p_helper(1)
277 fill_sve_p_helper(2)
278 fill_sve_p_helper(3)
279 fill_sve_p_helper(4)
280 fill_sve_p_helper(5)
281 fill_sve_p_helper(6)
282 fill_sve_p_helper(7)
283 fill_sve_p_helper(8)
284 fill_sve_p_helper(9)
285 fill_sve_p_helper(10)
286 fill_sve_p_helper(11)
287 fill_sve_p_helper(12)
288 fill_sve_p_helper(13)
289 fill_sve_p_helper(14)
290 fill_sve_p_helper(15)
291 ".arch_extension nosve\n"
292 : : "r" (p_regs));
293}
294
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100295/*
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100296 * Write SVE P[0-15] registers passed in 'p_regs' for Normal SVE or Streaming
297 * SVE mode
298 */
299void sve_p_regs_write(const sve_p_regs_t *p_regs)
300{
301 unsigned long flags;
302
303 sve_traps_save_disable(flags);
304 p_regs_write(p_regs);
305 sve_traps_restore(flags);
306}
307
308/*
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100309 * Read SVE P[0-15] registers and store it in 'p_regs' for Normal SVE or
310 * Streaming SVE mode
311 */
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100312void sve_p_regs_read(sve_p_regs_t *p_regs)
313{
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100314 unsigned long flags;
315
316 sve_traps_save_disable(flags);
317
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100318 __asm__ volatile(
319 ".arch_extension sve\n"
320 read_sve_p_helper(0)
321 read_sve_p_helper(1)
322 read_sve_p_helper(2)
323 read_sve_p_helper(3)
324 read_sve_p_helper(4)
325 read_sve_p_helper(5)
326 read_sve_p_helper(6)
327 read_sve_p_helper(7)
328 read_sve_p_helper(8)
329 read_sve_p_helper(9)
330 read_sve_p_helper(10)
331 read_sve_p_helper(11)
332 read_sve_p_helper(12)
333 read_sve_p_helper(13)
334 read_sve_p_helper(14)
335 read_sve_p_helper(15)
336 ".arch_extension nosve\n"
337 : : "r" (p_regs));
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100338
339 sve_traps_restore(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100340}
341
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100342static void ffr_regs_write(const sve_ffr_regs_t *ffr_regs)
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100343{
344 uint8_t sve_p_reg[SVE_P_REG_LEN_BYTES];
345
346 /* Save p0. Load 'ffr_regs' to p0 and write FFR. Restore p0 */
347 __asm__ volatile(
348 ".arch_extension sve\n"
349 " str p0, [%1]\n"
350 " ldr p0, [%0]\n"
351 " wrffr p0.B\n"
352 " ldr p0, [%1]\n"
353 ".arch_extension nosve\n"
354 :
355 : "r" (ffr_regs), "r" (sve_p_reg)
356 : "memory");
357}
358
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100359/*
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100360 * Write SVE FFR registers passed in 'ffr_regs' for Normal SVE or Streaming SVE
361 * mode
362 */
363void sve_ffr_regs_write(const sve_ffr_regs_t *ffr_regs)
364{
365 unsigned long flags;
366
367 sve_traps_save_disable(flags);
368 ffr_regs_write(ffr_regs);
369 sve_traps_restore(flags);
370}
371
372/*
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100373 * Read SVE FFR registers and store it in 'ffr_regs' for Normal SVE or Streaming
374 * SVE mode
375 */
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100376void sve_ffr_regs_read(sve_ffr_regs_t *ffr_regs)
377{
378 uint8_t sve_p_reg[SVE_P_REG_LEN_BYTES];
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100379 unsigned long flags;
380
381 sve_traps_save_disable(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100382
383 /* Save p0. Read FFR to p0 and save p0 (ffr) to 'ffr_regs'. Restore p0 */
384 __asm__ volatile(
385 ".arch_extension sve\n"
386 " str p0, [%1]\n"
387 " rdffr p0.B\n"
388 " str p0, [%0]\n"
389 " ldr p0, [%1]\n"
390 ".arch_extension nosve\n"
391 :
392 : "r" (ffr_regs), "r" (sve_p_reg)
393 : "memory");
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100394
395 sve_traps_restore(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100396}
397
398/*
399 * Generate random values and write it to 'z_regs', then write it to SVE Z
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100400 * registers for Normal SVE or Streaming SVE mode.
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100401 */
402void sve_z_regs_write_rand(sve_z_regs_t *z_regs)
403{
404 uint32_t rval;
405 uint32_t z_size;
406 uint8_t *z_reg;
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100407 unsigned long flags;
408
409 sve_traps_save_disable(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100410
411 z_size = (uint32_t)sve_rdvl_1();
412
413 /* Write Z regs */
414 rval = rand();
415 memset((void *)z_regs, 0, sizeof(sve_z_regs_t));
416 for (uint32_t i = 0U; i < SVE_NUM_VECTORS; i++) {
417 z_reg = (uint8_t *)z_regs + (i * z_size);
418
419 memset((void *)z_reg, rval * (i + 1), z_size);
420 }
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100421 z_regs_write(z_regs);
422
423 sve_traps_restore(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100424}
425
426/*
427 * Generate random values and write it to 'p_regs', then write it to SVE P
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100428 * registers for Normal SVE or Streaming SVE mode.
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100429 */
430void sve_p_regs_write_rand(sve_p_regs_t *p_regs)
431{
432 uint32_t p_size;
433 uint8_t *p_reg;
434 uint32_t rval;
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100435 unsigned long flags;
436
437 sve_traps_save_disable(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100438
439 p_size = (uint32_t)sve_rdvl_1() / 8;
440
441 /* Write P regs */
442 rval = rand();
443 memset((void *)p_regs, 0, sizeof(sve_p_regs_t));
444 for (uint32_t i = 0U; i < SVE_NUM_P_REGS; i++) {
445 p_reg = (uint8_t *)p_regs + (i * p_size);
446
447 memset((void *)p_reg, rval * (i + 1), p_size);
448 }
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100449 p_regs_write(p_regs);
450
451 sve_traps_restore(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100452}
453
454/*
455 * Generate random values and write it to 'ffr_regs', then write it to SVE FFR
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100456 * registers for Normal SVE or Streaming SVE mode.
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100457 */
458void sve_ffr_regs_write_rand(sve_ffr_regs_t *ffr_regs)
459{
460 uint32_t ffr_size;
461 uint8_t *ffr_reg;
462 uint32_t rval;
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100463 unsigned long flags;
464
465 sve_traps_save_disable(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100466
467 ffr_size = (uint32_t)sve_rdvl_1() / 8;
468
469 rval = rand();
470 memset((void *)ffr_regs, 0, sizeof(sve_ffr_regs_t));
471 for (uint32_t i = 0U; i < SVE_NUM_FFR_REGS; i++) {
472 ffr_reg = (uint8_t *)ffr_regs + (i * ffr_size);
473
474 memset((void *)ffr_reg, rval * (i + 1), ffr_size);
475 }
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100476 ffr_regs_write(ffr_regs);
477
478 sve_traps_restore(flags);
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100479}
480
481/*
482 * Compare Z registers passed in 's1' (old values) with 's2' (new values).
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100483 * This routine works for Normal SVE or Streaming SVE mode.
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100484 *
485 * Returns:
486 * 0 : All Z[0-31] registers in 's1' and 's2' are equal
487 * nonzero : Sets the Nth bit of the Z register that is not equal
488 */
489uint64_t sve_z_regs_compare(const sve_z_regs_t *s1, const sve_z_regs_t *s2)
490{
491 uint32_t z_size;
492 uint64_t cmp_bitmap = 0UL;
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100493 bool sve_hint;
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100494
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100495 /*
496 * 'rdvl' returns Streaming SVE VL if PSTATE.SM=1 else returns normal
497 * SVE VL
498 */
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100499 z_size = (uint32_t)sve_rdvl_1();
500
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100501 /* Ignore sve_hint for Streaming SVE mode */
502 if (is_feat_sme_supported() && sme_smstat_sm()) {
503 sve_hint = false;
504 } else {
505 sve_hint = tftf_smc_get_sve_hint();
506 }
507
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100508 for (uint32_t i = 0U; i < SVE_NUM_VECTORS; i++) {
509 uint8_t *s1_z = (uint8_t *)s1 + (i * z_size);
510 uint8_t *s2_z = (uint8_t *)s2 + (i * z_size);
511
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100512 /*
513 * For Z register the comparison is successful when
514 * 1. whole Z register of 's1' and 's2' is equal or
515 * 2. sve_hint is set and the lower 128 bits of 's1' and 's2' is
516 * equal and remaining upper bits of 's2' is zero
517 */
518 if ((memcmp(s1_z, s2_z, z_size) == 0) ||
519 (sve_hint && (z_size > FPU_Q_SIZE) &&
520 (memcmp(s1_z, s2_z, FPU_Q_SIZE) == 0) &&
521 (memcmp(s2_z + FPU_Q_SIZE, zero_mem,
522 z_size - FPU_Q_SIZE) == 0))) {
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100523 continue;
524 }
525
526 cmp_bitmap |= BIT_64(i);
527 VERBOSE("SVE Z_%u mismatch\n", i);
528 }
529
530 return cmp_bitmap;
531}
532
533/*
534 * Compare P registers passed in 's1' (old values) with 's2' (new values).
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100535 * This routine works for Normal SVE or Streaming SVE mode.
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100536 *
537 * Returns:
538 * 0 : All P[0-15] registers in 's1' and 's2' are equal
539 * nonzero : Sets the Nth bit of the P register that is not equal
540 */
541uint64_t sve_p_regs_compare(const sve_p_regs_t *s1, const sve_p_regs_t *s2)
542{
543 uint32_t p_size;
544 uint64_t cmp_bitmap = 0UL;
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100545 bool sve_hint;
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100546
547 /* Size of one predicate register 1/8 of Z register */
548 p_size = (uint32_t)sve_rdvl_1() / 8U;
549
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100550 /* Ignore sve_hint for Streaming SVE mode */
551 if (is_feat_sme_supported() && sme_smstat_sm()) {
552 sve_hint = false;
553 } else {
554 sve_hint = tftf_smc_get_sve_hint();
555 }
556
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100557 for (uint32_t i = 0U; i < SVE_NUM_P_REGS; i++) {
558 uint8_t *s1_p = (uint8_t *)s1 + (i * p_size);
559 uint8_t *s2_p = (uint8_t *)s2 + (i * p_size);
560
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100561 /*
562 * For P register the comparison is successful when
563 * 1. whole P register of 's1' and 's2' is equal or
564 * 2. sve_hint is set and the P register of 's2' is zero
565 */
566 if ((memcmp(s1_p, s2_p, p_size) == 0) ||
567 (sve_hint && (memcmp(s2_p, zero_mem, p_size) == 0))) {
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100568 continue;
569 }
570
571 cmp_bitmap |= BIT_64(i);
572 VERBOSE("SVE P_%u mismatch\n", i);
573 }
574
575 return cmp_bitmap;
576}
577
578/*
579 * Compare FFR register passed in 's1' (old values) with 's2' (new values).
Arunachalam Ganapathy5b68e202023-06-06 16:31:19 +0100580 * This routine works for Normal SVE or Streaming SVE mode.
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100581 *
582 * Returns:
583 * 0 : FFR register in 's1' and 's2' are equal
584 * nonzero : FFR register is not equal
585 */
586uint64_t sve_ffr_regs_compare(const sve_ffr_regs_t *s1, const sve_ffr_regs_t *s2)
587{
588 uint32_t ffr_size;
589 uint64_t cmp_bitmap = 0UL;
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100590 bool sve_hint;
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100591
592 /* Size of one FFR register 1/8 of Z register */
593 ffr_size = (uint32_t)sve_rdvl_1() / 8U;
594
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100595 /* Ignore sve_hint for Streaming SVE mode */
596 if (is_feat_sme_supported() && sme_smstat_sm()) {
597 sve_hint = false;
598 } else {
599 sve_hint = tftf_smc_get_sve_hint();
600 }
601
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100602 for (uint32_t i = 0U; i < SVE_NUM_FFR_REGS; i++) {
603 uint8_t *s1_ffr = (uint8_t *)s1 + (i * ffr_size);
604 uint8_t *s2_ffr = (uint8_t *)s2 + (i * ffr_size);
605
Arunachalam Ganapathy417edca2023-09-05 17:44:24 +0100606 /*
607 * For FFR register the comparison is successful when
608 * 1. whole FFR register of 's1' and 's2' is equal or
609 * 2. sve_hint is set and the FFR register of 's2' is zero
610 */
611 if ((memcmp(s1_ffr, s2_ffr, ffr_size) == 0) ||
612 (sve_hint && (memcmp(s2_ffr, zero_mem, ffr_size) == 0))) {
Arunachalam Ganapathyfa05bd92023-08-30 14:36:53 +0100613 continue;
614 }
615
616 cmp_bitmap |= BIT_64(i);
617 VERBOSE("SVE FFR_%u mismatch:\n", i);
618 }
619
620 return cmp_bitmap;
621}