blob: 1036d8b68d38480650a5f5dd4792223dd9030fc1 [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
Soby Mathew217748d2024-10-02 11:02:19 +0100158 if (ns) {
159 attrs_mask = S2TTE_NS_ATTR_RMM | S2TT_DESC_TYPE_MASK | S2TTE_NS_ATTR_MASK;
160 if (!is_feat_lpa2_4k_2_present()) {
161 attrs_mask |= S2TTE_SH_MASK;
162 }
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100163 } 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);
Soby Mathew217748d2024-10-02 11:02:19 +0100183 attrs &= S2TTE_NS_ATTR_MASK;
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100184
185 /* Find out if we are done or not */
186 inv_attrs = ((attrs & S2TTE_MEMATTR_MASK) ==
187 S2TTE_MEMATTR_FWB_RESERVED);
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100188 done = (reserved == inv_attrs);
189 } while (!done);
190 } else {
191 /* Setup the NS TTE attributes that don't come from the host */
192 attrs = S2TTE_NS_ATTR_RMM;
193 }
194
195 return attrs;
196}
197
198unsigned long s2tt_test_helpers_gen_attrs(bool invalid, long level)
199{
200 unsigned long attrs = (is_feat_lpa2_4k_2_present() == true) ?
201 S2TTE_ATTRS_LPA2 : S2TTE_ATTRS;
202
203 if (invalid == true) {
204 return attrs | S2TT_TEST_INVALID_DESC;
205 }
206
207 return ((level == S2TT_TEST_HELPERS_MAX_LVL) ?
208 S2TT_TEST_PAGE_DESC : S2TT_TEST_BLOCK_DESC) | attrs;
209}
210
211long s2tt_test_helpers_min_table_lvl(void)
212{
213 if (is_feat_lpa2_4k_2_present() == true) {
214 return S2TT_TEST_HELPERS_MIN_LVL_LPA2;
215 }
216
217 return S2TT_TEST_HELPERS_MIN_LVL;
218}
219
220long s2tt_test_helpers_min_block_lvl(void)
221{
222 return S2TT_MIN_BLOCK_LEVEL;
223}
224
AlexeiFedorovddcf3362025-06-02 17:36:20 +0100225long s2tt_test_helpers_min_dev_block_lvl(void)
226{
227 return S2TT_MIN_DEV_BLOCK_LEVEL;
228}
229
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100230unsigned long s2tt_test_helpers_get_entry_va_space_size(long level)
231{
232 assert(level >= s2tt_test_helpers_min_table_lvl());
233 assert(level <= S2TT_TEST_HELPERS_MAX_LVL);
234
235 unsigned long levels = S2TT_TEST_HELPERS_MAX_LVL - level;
236
237 return 1UL << (GRANULE_SHIFT + (S2TTE_STRIDE * levels));
238}
239
240unsigned long s2tt_test_helpers_get_idx_from_addr(unsigned long addr,
241 long level)
242{
243 assert(level >= s2tt_test_helpers_min_table_lvl());
244 assert(level <= S2TT_TEST_HELPERS_MAX_LVL);
245 assert((addr & ~((1UL << arch_feat_get_pa_width()) - 1UL)) == 0UL);
246
247 unsigned int levels = (unsigned int)(S2TT_TEST_HELPERS_MAX_LVL - level);
248 unsigned int lsb = GRANULE_SHIFT + (levels * S2TTE_STRIDE);
249
250 return (addr >> lsb) & ((1UL << S2TTE_STRIDE) - 1UL);
251}
252
253bool s2tt_test_helpers_lpa2_enabled(void)
254{
255 return lpa2_enabled;
256}
257
258unsigned long s2tt_test_create_assigned(const struct s2tt_context *s2tt_ctx,
259 unsigned long pa, long level,
260 unsigned long ripas)
261{
262 if (ripas == S2TTE_INVALID_RIPAS_EMPTY) {
263 return s2tte_create_assigned_empty(s2tt_ctx, pa, level);
264 } else if (ripas == S2TTE_INVALID_RIPAS_DESTROYED) {
265 return s2tte_create_assigned_destroyed(s2tt_ctx, pa, level);
266 } else if (ripas == S2TTE_INVALID_RIPAS_RAM) {
267 return s2tte_create_assigned_ram(s2tt_ctx, pa, level);
268 }
269
270 return s2tte_create_assigned_ns(s2tt_ctx, pa, level);
271}
272
AlexeiFedorovddcf3362025-06-02 17:36:20 +0100273unsigned long s2tt_test_create_assigned_dev_dev(const struct s2tt_context *s2tt_ctx,
274 unsigned long pa, long level)
275{
276 unsigned long attr = S2TTE_TEST_DEV_ATTRS;
277
278 /* Add Shareability bits if FEAT_LPA2 is not enabled */
279 if (!s2tt_ctx->enable_lpa2) {
280 attr |= S2TTE_TEST_DEV_SH;
281 }
282 return s2tte_create_assigned_dev_dev(s2tt_ctx, (pa | attr), level);
283}
284
285unsigned long s2tt_test_create_assigned_dev(const struct s2tt_context *s2tt_ctx,
286 unsigned long pa, long level,
287 unsigned long ripas)
288{
289 if (ripas == S2TTE_INVALID_RIPAS_EMPTY) {
290 return s2tte_create_assigned_dev_empty(s2tt_ctx, pa, level);
291 } else if (ripas == S2TTE_INVALID_RIPAS_DESTROYED) {
292 return s2tte_create_assigned_dev_destroyed(s2tt_ctx, pa, level);
293 } else if (ripas == S2TTE_INVALID_RIPAS_DEV) {
294 return s2tt_test_create_assigned_dev_dev(s2tt_ctx, pa, level);
295 }
296
297 assert(false);
298 return 0UL;
299}
300
301void s2tt_test_init_assigned_dev_dev(const struct s2tt_context *s2tt_ctx,
302 unsigned long *s2tt, unsigned long pa,
303 long level)
304{
305 unsigned long attr = S2TTE_TEST_DEV_ATTRS;
306
307 /* Add Shareability bits if FEAT_LPA2 is not enabled */
308 if (!s2tt_ctx->enable_lpa2) {
309 attr |= S2TTE_TEST_DEV_SH;
310 }
311
312 s2tt_init_assigned_dev_dev(s2tt_ctx, s2tt, (attr | pa), pa, level);
313}
314
Javier Almansa Sobrino4389c342024-04-10 12:12:13 +0100315unsigned long s2tt_test_create_unassigned(const struct s2tt_context *s2tt_ctx,
316 unsigned long ripas)
317{
318 if (ripas == S2TTE_INVALID_RIPAS_EMPTY) {
319 return s2tte_create_unassigned_empty(s2tt_ctx);
320 } else if (ripas == S2TTE_INVALID_RIPAS_DESTROYED) {
321 return s2tte_create_unassigned_destroyed(s2tt_ctx);
322 } else if (ripas == S2TTE_INVALID_RIPAS_RAM) {
323 return s2tte_create_unassigned_ram(s2tt_ctx);
324 }
325
326 return s2tte_create_unassigned_ns(s2tt_ctx);
327}