blob: 80ac31f5f378bff028cddb2f08cd0fc74218bef2 [file] [log] [blame]
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +01001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <arch_features.h>
7#include <assert.h>
8#include <errno.h>
9#include <host_utils.h>
10#include <limits.h>
11#include <ripas.h>
12#include <s2tt.h>
13#include <s2tt_pvt_defs.h>
14#include <s2tt_test_helpers.h>
15#include <stdbool.h>
16#include <stdlib.h>
17#include <string.h>
18#include <test_helpers.h>
19#include <utils_def.h>
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +010020#include <xlat_defs.h>
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +010021
22static bool lpa2_enabled;
23
24/*
25 * Helper function to perform any system register initialization
26 * needed for the tests.
27 */
28static void s2tt_test_helpers_arch_init(bool lpa2_en)
29{
30 unsigned int retval __unused;
31 uint64_t id_aa64mmfr0_el0 = INPLACE(ID_AA64MMFR0_EL1_TGRAN4_2,
32 ID_AA64MMFR0_EL1_TGRAN4_2_TGRAN4);
33
34 /*
35 * Enable the platform. We don't need support for several CPUs
36 * on this testsuite, so keep it disabled for simplicity.
37 */
38 test_helpers_rmm_start(false);
39
40 /*
41 * Reset the sysreg state so that we can setup
42 * custom values for the tests
43 */
44 host_util_zero_sysregs_and_cbs();
45
46 /* Setup id_aa64mmfr0_el1 */
47 if (lpa2_en == true) {
48 id_aa64mmfr0_el0 |= INPLACE(ID_AA64MMFR0_EL1_PARANGE, 6UL) |
49 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
50 ID_AA64MMFR0_EL1_TGRAN4_LPA2);
51 } else {
52 id_aa64mmfr0_el0 |= INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5UL) |
53 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
54 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED);
55 }
56 lpa2_enabled = lpa2_en;
57
58 retval = host_util_set_default_sysreg_cb("id_aa64mmfr0_el1",
59 id_aa64mmfr0_el0);
60
61 assert(retval == 0);
62
63 /* Make sure current cpu id is 0 (primary processor) */
64 host_util_set_cpuid(0U);
65
66 test_helpers_expect_assert_fail(false);
67}
68
69void s2tt_test_helpers_setup(bool lpa2)
70{
71 test_helpers_init();
72 s2tt_test_helpers_arch_init(lpa2);
73}
74
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +010075unsigned long s2tt_test_helpers_lvl_mask(long level)
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +010076{
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +010077 assert(level <= S2TT_TEST_HELPERS_MAX_LVL);
78
79 unsigned int levels = (unsigned int)(S2TT_TEST_HELPERS_MAX_LVL - level);
80 unsigned int lsb = GRANULE_SHIFT + (levels * S2TTE_STRIDE);
81 unsigned int msb = arch_feat_get_pa_width() - 1U;
82
83 return BIT_MASK_ULL(msb, lsb);
84}
85
86unsigned long s2tt_test_helpers_s2tte_oa_mask(void)
87{
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +010088 unsigned long mask = s2tt_test_helpers_lvl_mask(
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +010089 S2TT_TEST_HELPERS_MAX_LVL);
90
91 if (is_feat_lpa2_4k_2_present() == true) {
92 mask |= MASK(S2TT_TEST_MSB);
93 mask &= ~MASK(S2TT_TEST_OA_MSB);
94 }
95
96 return mask;
97}
98
99unsigned long s2tt_test_helpers_s2tte_to_pa(unsigned long s2tte, long level)
100{
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100101 unsigned long pa = s2tte & s2tt_test_helpers_lvl_mask(level);
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100102
103 if (is_feat_lpa2_4k_2_present() == true) {
104 pa &= ~MASK(S2TT_TEST_MSB);
105 pa |= INPLACE(S2TT_TEST_OA_MSB, EXTRACT(S2TT_TEST_MSB, s2tte));
106 }
107
108 return pa;
109}
110
111unsigned long s2tt_test_helpers_pa_to_s2tte(unsigned long pa, long level)
112{
113 unsigned long s2tte;
114
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100115 pa &= s2tt_test_helpers_lvl_mask(level);
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100116
117 if (is_feat_lpa2_4k_2_present() == true) {
118 s2tte = pa | INPLACE(S2TT_TEST_MSB, EXTRACT(S2TT_TEST_OA_MSB, pa));
119 s2tte &= ~MASK(S2TT_TEST_OA_MSB);
120 } else {
121 s2tte = pa;
122 }
123
124 return s2tte;
125}
126
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100127unsigned long s2tt_test_helpers_gen_addr(long level, bool aligned)
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100128{
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100129 unsigned int levels, lsb;
130 unsigned long addr;
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100131
132 /*
133 * We allow to get addresses aligned to one level below the minimum
134 * so we can use that address to create a table @level starting
135 * at such address.
136 */
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100137 assert(level >= s2tt_test_helpers_min_table_lvl() - 1);
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100138 assert(level <= S2TT_TEST_HELPERS_MAX_LVL);
139
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100140 levels = S2TT_TEST_HELPERS_MAX_LVL - level;
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100141 lsb = GRANULE_SHIFT + (levels * S2TTE_STRIDE);
142
143 do {
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100144 unsigned int shift = (level <= S2TT_TEST_HELPERS_MIN_LVL_LPA2) ?
145 LM1_XLAT_ADDRESS_SHIFT : L0_XLAT_ADDRESS_SHIFT;
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100146
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100147 addr = test_helpers_get_rand_in_range((1UL << lsb), ULONG_MAX);
148 addr &= ((1UL << shift) - 1UL);
149 } while (addr == 0UL);
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100150
Javier Almansa Sobrino9810a8e2024-06-03 15:17:25 +0100151 return aligned ? (addr & s2tt_test_helpers_lvl_mask(level)) : addr;
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100152}
153
154unsigned long s2tt_test_helpers_s2tte_to_attrs(unsigned long tte, bool ns)
155{
156 unsigned long attrs_mask;
157
158 if (ns == true) {
159 attrs_mask = S2TTE_NS_ATTR_RMM | S2TT_DESC_TYPE_MASK;
160 attrs_mask |= (is_feat_lpa2_4k_2_present() == true) ?
161 S2TTE_NS_ATTR_LPA2_MASK :
162 S2TTE_NS_ATTR_MASK;
163 } else {
164 attrs_mask = ((is_feat_lpa2_4k_2_present() == true) ?
165 S2TTE_ATTRS_LPA2_MASK :
166 S2TTE_ATTRS_MASK) | S2TT_DESC_TYPE_MASK;
167 }
168
169 return tte & attrs_mask;
170}
171
172unsigned long s2tt_test_helpers_gen_ns_attrs(bool host, bool reserved)
173{
174 unsigned long attrs;
175 bool done;
176
177 if (host == true) {
178 /* Generate a random set of attributes coming from the host */
179 do {
180 bool inv_attrs;
181
182 attrs = test_helpers_get_rand_in_range(0UL, ULONG_MAX);
183
184 attrs &= (is_feat_lpa2_4k_2_present() == true) ?
185 S2TTE_NS_ATTR_LPA2_MASK :
186 S2TTE_NS_ATTR_MASK;
187
188 /* Find out if we are done or not */
189 inv_attrs = ((attrs & S2TTE_MEMATTR_MASK) ==
190 S2TTE_MEMATTR_FWB_RESERVED);
191
192 if (is_feat_lpa2_4k_2_present() == false) {
193 inv_attrs |= ((attrs & S2TTE_SH_MASK) !=
194 S2TTE_SH_IS);
195 }
196 done = (reserved == inv_attrs);
197 } while (!done);
198 } else {
199 /* Setup the NS TTE attributes that don't come from the host */
200 attrs = S2TTE_NS_ATTR_RMM;
201 }
202
203 return attrs;
204}
205
206unsigned long s2tt_test_helpers_gen_attrs(bool invalid, long level)
207{
208 unsigned long attrs = (is_feat_lpa2_4k_2_present() == true) ?
209 S2TTE_ATTRS_LPA2 : S2TTE_ATTRS;
210
211 if (invalid == true) {
212 return attrs | S2TT_TEST_INVALID_DESC;
213 }
214
215 return ((level == S2TT_TEST_HELPERS_MAX_LVL) ?
216 S2TT_TEST_PAGE_DESC : S2TT_TEST_BLOCK_DESC) | attrs;
217}
218
219long s2tt_test_helpers_min_table_lvl(void)
220{
221 if (is_feat_lpa2_4k_2_present() == true) {
222 return S2TT_TEST_HELPERS_MIN_LVL_LPA2;
223 }
224
225 return S2TT_TEST_HELPERS_MIN_LVL;
226}
227
228long s2tt_test_helpers_min_block_lvl(void)
229{
230 return S2TT_MIN_BLOCK_LEVEL;
231}
232
233unsigned long s2tt_test_helpers_get_entry_va_space_size(long level)
234{
235 assert(level >= s2tt_test_helpers_min_table_lvl());
236 assert(level <= S2TT_TEST_HELPERS_MAX_LVL);
237
238 unsigned long levels = S2TT_TEST_HELPERS_MAX_LVL - level;
239
240 return 1UL << (GRANULE_SHIFT + (S2TTE_STRIDE * levels));
241}
242
243unsigned long s2tt_test_helpers_get_idx_from_addr(unsigned long addr,
244 long level)
245{
246 assert(level >= s2tt_test_helpers_min_table_lvl());
247 assert(level <= S2TT_TEST_HELPERS_MAX_LVL);
248 assert((addr & ~((1UL << arch_feat_get_pa_width()) - 1UL)) == 0UL);
249
250 unsigned int levels = (unsigned int)(S2TT_TEST_HELPERS_MAX_LVL - level);
251 unsigned int lsb = GRANULE_SHIFT + (levels * S2TTE_STRIDE);
252
253 return (addr >> lsb) & ((1UL << S2TTE_STRIDE) - 1UL);
254}
255
256bool s2tt_test_helpers_lpa2_enabled(void)
257{
258 return lpa2_enabled;
259}
260
261unsigned long s2tt_test_create_assigned(const struct s2tt_context *s2tt_ctx,
262 unsigned long pa, long level,
263 unsigned long ripas)
264{
265 if (ripas == S2TTE_INVALID_RIPAS_EMPTY) {
266 return s2tte_create_assigned_empty(s2tt_ctx, pa, level);
267 } else if (ripas == S2TTE_INVALID_RIPAS_DESTROYED) {
268 return s2tte_create_assigned_destroyed(s2tt_ctx, pa, level);
269 } else if (ripas == S2TTE_INVALID_RIPAS_RAM) {
270 return s2tte_create_assigned_ram(s2tt_ctx, pa, level);
271 }
272
273 return s2tte_create_assigned_ns(s2tt_ctx, pa, level);
274}
275
276unsigned long s2tt_test_create_unassigned(const struct s2tt_context *s2tt_ctx,
277 unsigned long ripas)
278{
279 if (ripas == S2TTE_INVALID_RIPAS_EMPTY) {
280 return s2tte_create_unassigned_empty(s2tt_ctx);
281 } else if (ripas == S2TTE_INVALID_RIPAS_DESTROYED) {
282 return s2tte_create_unassigned_destroyed(s2tt_ctx);
283 } else if (ripas == S2TTE_INVALID_RIPAS_RAM) {
284 return s2tte_create_unassigned_ram(s2tt_ctx);
285 }
286
287 return s2tte_create_unassigned_ns(s2tt_ctx);
288}