blob: 098cf4cf28bac64e32e4190953fd811d4936f086 [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 Ganapathy0bbdc2d2023-04-05 15:30:18 +010013#include <lib/extensions/sve.h>
14
15#include <host_realm_sve.h>
16#include <host_shared_data.h>
17
Arunachalam Ganapathyc1136a82023-04-12 15:24:44 +010018#define RL_SVE_OP_ARRAYSIZE 512U
19#define SVE_TEST_ITERATIONS 4U
20
21static int rl_sve_op_1[RL_SVE_OP_ARRAYSIZE];
22static int rl_sve_op_2[RL_SVE_OP_ARRAYSIZE];
23
Arunachalam Ganapathy03589972023-08-30 11:04:51 +010024static sve_z_regs_t rl_sve_z_regs_write;
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +010025
Arunachalam Ganapathy73949a22023-06-05 12:01:05 +010026static int volatile realm_got_undef_abort;
27
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010028/* Returns the maximum supported VL. This test is called only by sve Realm */
29bool test_realm_sve_rdvl(void)
30{
Shruti Gupta550e3e82023-08-16 13:20:11 +010031 host_shared_data_t *sd = realm_get_my_shared_structure();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010032 struct sve_cmd_rdvl *output;
33
34 assert(is_armv8_2_sve_present());
35
36 output = (struct sve_cmd_rdvl *)sd->realm_cmd_output_buffer;
37 memset((void *)output, 0, sizeof(struct sve_cmd_rdvl));
38
39 sve_config_vq(SVE_VQ_ARCH_MAX);
Arunachalam Ganapathy03589972023-08-30 11:04:51 +010040 output->rdvl = sve_rdvl_1();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010041
42 return true;
43}
44
45/*
46 * Reads and returns the ID_AA64PFR0_EL1 and ID_AA64ZFR0_EL1 registers
47 * This test could be called from sve or non-sve Realm
48 */
49bool test_realm_sve_read_id_registers(void)
50{
Shruti Gupta550e3e82023-08-16 13:20:11 +010051 host_shared_data_t *sd = realm_get_my_shared_structure();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010052 struct sve_cmd_id_regs *output;
53
54 output = (struct sve_cmd_id_regs *)sd->realm_cmd_output_buffer;
55 memset((void *)output, 0, sizeof(struct sve_cmd_id_regs));
56
57 realm_printf("Realm: reading ID registers: ID_AA64PFR0_EL1, "
58 " ID_AA64ZFR0_EL1\n");
59 output->id_aa64pfr0_el1 = read_id_aa64pfr0_el1();
60 output->id_aa64zfr0_el1 = read_id_aa64zfr0_el1();
61
62 return true;
63}
64
65/*
66 * Probes all VLs and return the bitmap with the bit set for each corresponding
67 * valid VQ. This test is called only by sve Realm
68 */
69bool test_realm_sve_probe_vl(void)
70{
Shruti Gupta550e3e82023-08-16 13:20:11 +010071 host_shared_data_t *sd = realm_get_my_shared_structure();
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +010072 struct sve_cmd_probe_vl *output;
73
74 assert(is_armv8_2_sve_present());
75
76 output = (struct sve_cmd_probe_vl *)&sd->realm_cmd_output_buffer;
77 memset((void *)output, 0, sizeof(struct sve_cmd_probe_vl));
78
79 /* Probe all VLs */
80 output->vl_bitmap = sve_probe_vl(SVE_VQ_ARCH_MAX);
81
82 return true;
83}
Arunachalam Ganapathyc1136a82023-04-12 15:24:44 +010084
85bool test_realm_sve_ops(void)
86{
87 int val, i;
88
89 assert(is_armv8_2_sve_present());
90
91 /* get at random value to do sve_subtract */
92 val = rand();
93 for (i = 0; i < RL_SVE_OP_ARRAYSIZE; i++) {
94 rl_sve_op_1[i] = val - i;
95 rl_sve_op_2[i] = 1;
96 }
97
98 for (i = 0; i < SVE_TEST_ITERATIONS; i++) {
99 /* Config Realm with random SVE length */
100 sve_config_vq(SVE_GET_RANDOM_VQ);
101
102 /* Perform SVE operations, without world switch */
103 sve_subtract_arrays(rl_sve_op_1, rl_sve_op_1, rl_sve_op_2,
104 RL_SVE_OP_ARRAYSIZE);
105 }
106
107 /* Check result of SVE operations. */
108 for (i = 0; i < RL_SVE_OP_ARRAYSIZE; i++) {
109 if (rl_sve_op_1[i] != (val - i - SVE_TEST_ITERATIONS)) {
110 realm_printf("Realm: SVE ops failed\n");
111 return false;
112 }
113 }
114
115 return true;
116}
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +0100117
118/* Fill SVE Z registers with known pattern */
119bool test_realm_sve_fill_regs(void)
120{
121 uint32_t vl;
122
123 assert(is_armv8_2_sve_present());
124
125 /* Config Realm with max SVE length */
126 sve_config_vq(SVE_VQ_ARCH_MAX);
Arunachalam Ganapathy03589972023-08-30 11:04:51 +0100127 vl = sve_rdvl_1();
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +0100128
Arunachalam Ganapathy03589972023-08-30 11:04:51 +0100129 memset((void *)&rl_sve_z_regs_write, 0xcd, vl * SVE_NUM_VECTORS);
130 sve_z_regs_write(&rl_sve_z_regs_write);
Arunachalam Ganapathy5270d012023-04-19 14:53:42 +0100131
132 return true;
133}
Arunachalam Ganapathy73949a22023-06-05 12:01:05 +0100134
135static bool realm_sync_exception_handler(void)
136{
137 uint64_t esr_el1 = read_esr_el1();
138
139 if (EC_BITS(esr_el1) == EC_UNKNOWN) {
140 realm_printf("Realm: received undefined abort. "
141 "esr_el1: 0x%llx elr_el1: 0x%llx\n",
142 esr_el1, read_elr_el1());
143 realm_got_undef_abort++;
144 }
145
146 return true;
147}
148
149/* Check if Realm gets undefined abort when it accesses SVE functionality */
150bool test_realm_sve_undef_abort(void)
151{
152 realm_got_undef_abort = 0UL;
153
154 /* install exception handler to catch undef abort */
155 register_custom_sync_exception_handler(&realm_sync_exception_handler);
156 (void)sve_rdvl_1();
157 unregister_custom_sync_exception_handler();
158
159 if (realm_got_undef_abort == 0UL) {
160 return false;
161 }
162
163 return true;
164}