blob: 730bed549dedfd4e53fd12341fd8431fc81e24cf [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <arch_helpers.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00007#include <bitmap.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00008#include <granule.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00009#include <ripas.h>
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +010010#include <s2tt.h>
11#include <s2tt_pvt_defs.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000012#include <smc.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000013#include <stddef.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000014
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +010015/* TODO: Fix this when introducing LPA2 support */
16COMPILER_ASSERT(S2TT_MIN_STARTING_LEVEL >= 0);
Soby Mathewb4c6df42022-11-09 11:13:29 +000017
18/*
19 * Invalidates S2 TLB entries from [ipa, ipa + size] region tagged with `vmid`.
20 */
Javier Almansa Sobrino2eb98b02023-12-18 18:10:55 +000021static void stage2_tlbi_ipa(const struct s2tt_context *s2_ctx,
Soby Mathewb4c6df42022-11-09 11:13:29 +000022 unsigned long ipa,
23 unsigned long size)
24{
25 /*
26 * Notes:
27 *
28 * - This follows the description provided in the Arm ARM on
29 * "Invalidation of TLB entries from stage 2 translations".
30 *
31 * - @TODO: Provide additional information to this primitive so that
32 * we can utilize:
33 * - The TTL level hint, see FEAT_TTL,
34 * - Final level lookup only invalidation,
35 * - Address range invalidation.
36 */
37
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +010038 assert(s2_ctx != NULL);
39
Soby Mathewb4c6df42022-11-09 11:13:29 +000040 /*
41 * Save the current content of vttb_el2.
42 */
43 unsigned long old_vttbr_el2 = read_vttbr_el2();
44
45 /*
46 * Make 'vmid' the `current vmid`. Note that the tlbi instructions
47 * bellow target the TLB entries that match the `current vmid`.
48 */
49 write_vttbr_el2(INPLACE(VTTBR_EL2_VMID, s2_ctx->vmid));
50 isb();
51
52 /*
53 * Invalidate entries in S2 TLB caches that
54 * match both `ipa` & the `current vmid`.
55 */
56 while (size != 0UL) {
57 tlbiipas2e1is(ipa >> 12);
58 size -= GRANULE_SIZE;
59 ipa += GRANULE_SIZE;
60 }
61 dsb(ish);
62
63 /*
64 * The architecture does not require TLB invalidation by IPA to affect
65 * combined Stage-1 + Stage-2 TLBs. Therefore we must invalidate all of
66 * Stage-1 (tagged with the `current vmid`) after invalidating Stage-2.
67 */
68 tlbivmalle1is();
69 dsb(ish);
70 isb();
71
72 /*
73 * Restore the old content of vttb_el2.
74 */
75 write_vttbr_el2(old_vttbr_el2);
76 isb();
77}
78
79/*
80 * Invalidate S2 TLB entries with "addr" IPA.
81 * Call this function after:
82 * 1. A L3 page desc has been removed.
83 */
Javier Almansa Sobrino2eb98b02023-12-18 18:10:55 +000084void s2tt_invalidate_page(const struct s2tt_context *s2_ctx, unsigned long addr)
Soby Mathewb4c6df42022-11-09 11:13:29 +000085{
86 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
87}
88
89/*
90 * Invalidate S2 TLB entries with "addr" IPA.
91 * Call this function after:
92 * 1. A L2 block desc has been removed, or
93 * 2a. A L2 table desc has been removed, where
94 * 2b. All S2TTEs in L3 table that the L2 table desc was pointed to were invalid.
95 */
Javier Almansa Sobrino2eb98b02023-12-18 18:10:55 +000096void s2tt_invalidate_block(const struct s2tt_context *s2_ctx, unsigned long addr)
Soby Mathewb4c6df42022-11-09 11:13:29 +000097{
98 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
99}
100
101/*
102 * Invalidate S2 TLB entries with "addr" IPA.
103 * Call this function after:
104 * 1a. A L2 table desc has been removed, where
105 * 1b. Some S2TTEs in the table that the L2 table desc was pointed to were valid.
106 */
Javier Almansa Sobrino2eb98b02023-12-18 18:10:55 +0000107void s2tt_invalidate_pages_in_block(const struct s2tt_context *s2_ctx,
108 unsigned long addr)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000109{
110 stage2_tlbi_ipa(s2_ctx, addr, BLOCK_L2_SIZE);
111}
112
113/*
114 * Return the index of the entry describing @addr in the translation table at
115 * level @level. This only works for non-concatenated page tables, so should
116 * not be called to get the index for the starting level.
117 *
118 * See the library pseudocode
119 * aarch64/translation/vmsa_addrcalc/AArch64.TTEntryAddress on which this is
120 * modeled.
121 */
122static unsigned long s2_addr_to_idx(unsigned long addr, long level)
123{
AlexeiFedorovbb1f1c82023-08-25 10:44:49 +0100124 unsigned int levels, lsb;
125
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100126 levels = (unsigned int)(S2TT_PAGE_LEVEL - level);
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100127 lsb = (levels * S2TTE_STRIDE) + GRANULE_SHIFT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000128
129 addr >>= lsb;
AlexeiFedorovbb1f1c82023-08-25 10:44:49 +0100130 addr &= (1UL << S2TTE_STRIDE) - 1UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000131 return addr;
132}
133
134/*
135 * Return the index of the entry describing @addr in the translation table
136 * starting level. This may return an index >= S2TTES_PER_S2TT when the
137 * combination of @start_level and @ipa_bits implies concatenated
138 * stage 2 tables.
139 *
140 * See the library pseudocode
141 * aarch64/translation/vmsa_addrcalc/AArch64.S2SLTTEntryAddress on which
142 * this is modeled.
143 */
144static unsigned long s2_sl_addr_to_idx(unsigned long addr, int start_level,
145 unsigned long ipa_bits)
146{
AlexeiFedorovbb1f1c82023-08-25 10:44:49 +0100147 unsigned int levels, lsb;
148
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100149 levels = (unsigned int)(S2TT_PAGE_LEVEL - start_level);
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100150 lsb = (levels * S2TTE_STRIDE) + GRANULE_SHIFT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000151
152 addr &= (1UL << ipa_bits) - 1UL;
153 addr >>= lsb;
154 return addr;
155}
156
AlexeiFedorov7641a812023-08-22 14:31:27 +0100157static unsigned long addr_level_mask(unsigned long addr, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000158{
AlexeiFedorovbb1f1c82023-08-25 10:44:49 +0100159 unsigned int levels, lsb, msb;
160
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100161 assert(level <= S2TT_PAGE_LEVEL);
162 assert(level >= S2TT_MIN_STARTING_LEVEL);
AlexeiFedorovbb1f1c82023-08-25 10:44:49 +0100163
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100164 levels = (unsigned int)(S2TT_PAGE_LEVEL - level);
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100165 lsb = (levels * S2TTE_STRIDE) + GRANULE_SHIFT;
AlexeiFedorovbb1f1c82023-08-25 10:44:49 +0100166 msb = S2TTE_OA_BITS - 1U;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000167
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100168 return (addr & BIT_MASK_ULL(msb, lsb));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000169}
170
Soby Mathewb4c6df42022-11-09 11:13:29 +0000171static inline bool entry_is_table(unsigned long entry)
172{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100173 return ((entry & S2TT_DESC_TYPE_MASK) == S2TTE_L012_TABLE);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000174}
175
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000176static unsigned long table_get_entry(const struct s2tt_context *s2_ctx,
177 struct granule *g_tbl,
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100178 unsigned long idx)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000179{
180 unsigned long *table, entry;
181
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000182 (void)s2_ctx;
183
Soby Mathewb4c6df42022-11-09 11:13:29 +0000184 table = granule_map(g_tbl, SLOT_RTT);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100185 assert(table != NULL);
186
Soby Mathewb4c6df42022-11-09 11:13:29 +0000187 entry = s2tte_read(&table[idx]);
188 buffer_unmap(table);
189
190 return entry;
191}
192
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100193#define table_entry_to_phys(tte) addr_level_mask(tte, S2TT_PAGE_LEVEL)
194
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000195static struct granule *find_next_level_idx(const struct s2tt_context *s2_ctx,
196 struct granule *g_tbl,
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100197 unsigned long idx)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000198{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000199 const unsigned long entry = table_get_entry(s2_ctx, g_tbl, idx);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000200
201 if (!entry_is_table(entry)) {
202 return NULL;
203 }
204
205 return addr_to_granule(table_entry_to_phys(entry));
206}
207
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000208static struct granule *find_lock_next_level(const struct s2tt_context *s2_ctx,
209 struct granule *g_tbl,
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100210 unsigned long map_addr,
211 long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000212{
213 const unsigned long idx = s2_addr_to_idx(map_addr, level);
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000214 struct granule *g = find_next_level_idx(s2_ctx, g_tbl, idx);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000215
216 if (g != NULL) {
217 granule_lock(g, GRANULE_STATE_RTT);
218 }
219
220 return g;
221}
222
223/*
224 * Walk an RTT until level @level using @map_addr.
225 * @g_root is the root (level 0) table and must be locked before the call.
226 * @start_level is the initial lookup level used for the stage 2 translation
227 * tables which may depend on the configuration of the realm, factoring in the
228 * IPA size of the realm and the desired starting level (within the limits
229 * defined by the Armv8 VMSA including options for stage 2 table concatenation).
230 * The function uses hand-over-hand locking to avoid race conditions and allow
231 * concurrent access to RTT tree which is not part of the current walk; when a
232 * next level table is reached it is locked before releasing previously locked
233 * table.
234 * The walk stops when either:
235 * - The entry found is a leaf entry (not an RTT Table entry), or
236 * - Level @level is reached.
237 *
238 * On return:
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100239 * - s2tt_walk::last_level is the last level that has been reached by the walk.
240 * - s2tt_walk.g_llt points to the TABLE granule at level @s2tt_walk::level.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000241 * The granule is locked.
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000242 * - s2tt_walk::index is the entry index at s2tt_walk.g_llt for @map_addr.i
243 *
244 * NOTE: This function expects that the root table on the s2 context is
245 * already locked.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000246 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000247void s2tt_walk_lock_unlock(const struct s2tt_context *s2_ctx,
248 unsigned long map_addr,
249 long level,
250 struct s2tt_walk *wi)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000251{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100252 struct granule *g_tbls[NR_RTT_LEVELS] = { (struct granule *)NULL };
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000253 struct granule *g_root;
254 unsigned long sl_idx, ipa_bits;
255 int i, start_level, last_level;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000256
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000257 assert(s2_ctx != NULL);
258
259 start_level = s2_ctx->s2_starting_level;
260 ipa_bits = s2_ctx->ipa_bits;
261
Soby Mathewb4c6df42022-11-09 11:13:29 +0000262 assert(level >= start_level);
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100263 assert(level <= S2TT_PAGE_LEVEL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000264 assert(map_addr < (1UL << ipa_bits));
265 assert(wi != NULL);
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000266
267 g_root = s2_ctx->g_rtt;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000268
269 /* Handle concatenated starting level (SL) tables */
270 sl_idx = s2_sl_addr_to_idx(map_addr, start_level, ipa_bits);
271 if (sl_idx >= S2TTES_PER_S2TT) {
AlexeiFedorov4faab852023-08-30 15:06:49 +0100272 unsigned int tt_num = (unsigned int)(sl_idx >> S2TTE_STRIDE);
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100273 struct granule *g_concat_root;
274
275 assert(tt_num < S2TTE_MAX_CONCAT_TABLES);
276
277 g_concat_root = (struct granule *)((uintptr_t)g_root +
AlexeiFedorov3f5d6272023-10-23 16:27:37 +0100278 (tt_num * sizeof(struct granule)));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000279
280 granule_lock(g_concat_root, GRANULE_STATE_RTT);
281 granule_unlock(g_root);
282 g_root = g_concat_root;
283 }
284
285 g_tbls[start_level] = g_root;
286 for (i = start_level; i < level; i++) {
287 /*
288 * Lock next RTT level. Correct locking order is guaranteed
289 * because reference is obtained from a locked granule
290 * (previous level). Also, hand-over-hand locking/unlocking is
291 * used to avoid race conditions.
292 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000293 g_tbls[i + 1] = find_lock_next_level(s2_ctx, g_tbls[i],
294 map_addr, i);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000295 if (g_tbls[i + 1] == NULL) {
296 last_level = i;
297 goto out;
298 }
299 granule_unlock(g_tbls[i]);
300 }
301
AlexeiFedorov4faab852023-08-30 15:06:49 +0100302 last_level = (int)level;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000303out:
304 wi->last_level = last_level;
305 wi->g_llt = g_tbls[last_level];
306 wi->index = s2_addr_to_idx(map_addr, last_level);
307}
308
309/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100310 * Creates an unassigned_empty s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000311 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000312unsigned long s2tte_create_unassigned_empty(const struct s2tt_context *s2_ctx)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000313{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000314 (void)s2_ctx;
315
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100316 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_EMPTY);
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100317}
318
319/*
320 * Creates an unassigned_ram s2tte.
321 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000322unsigned long s2tte_create_unassigned_ram(const struct s2tt_context *s2_ctx)
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100323{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000324 (void)s2_ctx;
325
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100326 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_RAM);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000327}
328
329/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100330 * Creates an unassigned_destroyed s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000331 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000332unsigned long s2tte_create_unassigned_destroyed(const struct s2tt_context *s2_ctx)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000333{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000334 (void)s2_ctx;
335
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100336 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_DESTROYED);
337}
338
339/*
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100340 * Creates an unassigned_ns s2tte.
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100341 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000342unsigned long s2tte_create_unassigned_ns(const struct s2tt_context *s2_ctx)
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100343{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000344 (void)s2_ctx;
345
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100346 return (S2TTE_NS | S2TTE_INVALID_HIPAS_UNASSIGNED |
347 S2TTE_INVALID_UNPROTECTED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000348}
349
350/*
351 * Creates an invalid s2tte with output address @pa, HIPAS=ASSIGNED and
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100352 * RIPAS=@s2tte_ripas, at level @level.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000353 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000354static unsigned long s2tte_create_assigned(const struct s2tt_context *s2_ctx,
355 unsigned long pa, long level,
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100356 unsigned long s2tte_ripas)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000357{
Chuyue Luo5ef71d92023-10-24 14:29:20 +0100358 (void)level;
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000359 (void)s2_ctx;
Chuyue Luo5ef71d92023-10-24 14:29:20 +0100360
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100361 assert(level >= S2TT_MIN_BLOCK_LEVEL);
362 assert(level <= S2TT_PAGE_LEVEL);
363 assert(s2tte_ripas <= S2TTE_INVALID_RIPAS_DESTROYED);
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000364 assert(s2tte_is_addr_lvl_aligned(s2_ctx, pa, level));
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100365
366 if (s2tte_ripas == S2TTE_INVALID_RIPAS_RAM) {
367 if (level == S2TT_PAGE_LEVEL) {
368 return (pa | S2TTE_PAGE);
369 }
370 return (pa | S2TTE_BLOCK);
371 }
372
373 return (pa | S2TTE_INVALID_HIPAS_ASSIGNED | s2tte_ripas);
374}
375
376/*
377 * Creates and invalid s2tte with output address @pa, HIPAS=ASSIGNED and
378 * RIPAS=DESTROYED at level @level.
379 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000380unsigned long s2tte_create_assigned_destroyed(const struct s2tt_context *s2_ctx,
381 unsigned long pa, long level)
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100382{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000383 return s2tte_create_assigned(s2_ctx, pa, level,
384 S2TTE_INVALID_RIPAS_DESTROYED);
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100385}
386
387/*
388 * Creates an invalid s2tte with output address @pa, HIPAS=ASSIGNED and
389 * RIPAS=EMPTY at level @level.
390 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000391unsigned long s2tte_create_assigned_empty(const struct s2tt_context *s2_ctx,
392 unsigned long pa, long level)
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100393{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000394 return s2tte_create_assigned(s2_ctx, pa, level,
395 S2TTE_INVALID_RIPAS_EMPTY);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000396}
397
398/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100399 * Creates an assigned_ram s2tte with output address @pa.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000400 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000401unsigned long s2tte_create_assigned_ram(const struct s2tt_context *s2_ctx,
402 unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000403{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000404 return s2tte_create_assigned(s2_ctx, pa, level,
405 S2TTE_INVALID_RIPAS_RAM);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000406}
407
408/*
Javier Almansa Sobrino84a1b162023-09-26 17:32:44 +0100409 * Creates an assigned s2tte with output address @pa and the same
410 * RIPAS as passed on @s2tte.
411 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000412unsigned long s2tte_create_assigned_unchanged(const struct s2tt_context *s2_ctx,
413 unsigned long s2tte,
Javier Almansa Sobrino84a1b162023-09-26 17:32:44 +0100414 unsigned long pa,
415 long level)
416{
417 unsigned long current_ripas = s2tte & S2TTE_INVALID_RIPAS_MASK;
418
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000419 return s2tte_create_assigned(s2_ctx, pa, level, current_ripas);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000420}
421
422/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100423 * Creates an assigned_ns s2tte at level @level.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000424 *
425 * The following S2 TTE fields are provided through @s2tte argument:
426 * - The physical address
427 * - MemAttr
428 * - S2AP
429 * - Shareability
430 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000431unsigned long s2tte_create_assigned_ns(const struct s2tt_context *s2_ctx,
432 unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000433{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100434 unsigned long new_s2tte = s2tte & ~S2TT_DESC_TYPE_MASK;
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +0100435
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000436 (void)s2_ctx;
437
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100438 assert(level >= S2TT_MIN_BLOCK_LEVEL);
439 assert(level <= S2TT_PAGE_LEVEL);
440 assert((s2tte & S2TTE_NS_ATTR_RMM) == 0UL);
441
442 if (level == S2TT_PAGE_LEVEL) {
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +0100443 return (new_s2tte | S2TTE_PAGE_NS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000444 }
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +0100445 return (new_s2tte | S2TTE_BLOCK_NS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000446}
447
448/*
449 * Validate the portion of NS S2TTE that is provided by the host.
450 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000451bool host_ns_s2tte_is_valid(const struct s2tt_context *s2_ctx,
452 unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000453{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100454
Soby Mathewb4c6df42022-11-09 11:13:29 +0000455 unsigned long mask = addr_level_mask(~0UL, level) |
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100456 S2TTE_NS_ATTR_HOST_MASK;
457
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000458 (void)s2_ctx;
459
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100460 assert(level >= S2TT_MIN_BLOCK_LEVEL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000461
462 /*
463 * Test that all fields that are not controlled by the host are zero
464 * and that the output address is correctly aligned. Note that
465 * the host is permitted to map any physical address outside PAR.
466 */
467 if ((s2tte & ~mask) != 0UL) {
468 return false;
469 }
470
471 /*
472 * Only one value masked by S2TTE_MEMATTR_MASK is invalid/reserved.
473 */
474 if ((s2tte & S2TTE_MEMATTR_MASK) == S2TTE_MEMATTR_FWB_RESERVED) {
475 return false;
476 }
477
478 /*
479 * Only one value masked by S2TTE_SH_MASK is invalid/reserved.
480 */
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100481 if ((s2tte & S2TTE_SH_MASK) != S2TTE_SH_IS) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000482 return false;
483 }
484
485 /*
486 * Note that all the values that are masked by S2TTE_AP_MASK are valid.
487 */
488 return true;
489}
490
491/*
492 * Returns the portion of NS S2TTE that is set by the host.
493 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000494unsigned long host_ns_s2tte(const struct s2tt_context *s2_ctx,
495 unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000496{
497 unsigned long mask = addr_level_mask(~0UL, level) |
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100498 S2TTE_NS_ATTR_HOST_MASK;
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000499 (void)s2_ctx;
500
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100501 assert(level >= S2TT_MIN_BLOCK_LEVEL);
502
Soby Mathewb4c6df42022-11-09 11:13:29 +0000503 return (s2tte & mask);
504}
505
506/*
507 * Creates a table s2tte at level @level with output address @pa.
508 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000509unsigned long s2tte_create_table(const struct s2tt_context *s2_ctx,
510 unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000511{
Chuyue Luo5ef71d92023-10-24 14:29:20 +0100512 (void)level;
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000513 (void)s2_ctx;
Chuyue Luo5ef71d92023-10-24 14:29:20 +0100514
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100515 assert(level < S2TT_PAGE_LEVEL);
516 assert(level >= S2TT_MIN_STARTING_LEVEL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000517 assert(GRANULE_ALIGNED(pa));
518
519 return (pa | S2TTE_TABLE);
520}
521
522/*
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100523 * Returns true if s2tte has defined ripas value, namely if it is one of:
524 * - unassigned_empty
525 * - unassigned_ram
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100526 * - unassigned_destroyed
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100527 * - assigned_empty
528 * - assigned_ram
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100529 * - assigned_destroyed
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100530 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000531bool s2tte_has_ripas(const struct s2tt_context *s2_ctx,
532 unsigned long s2tte, long level)
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100533{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000534 return (((s2tte & S2TTE_NS) == 0UL) && !s2tte_is_table(s2_ctx,
535 s2tte, level));
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100536}
537
538/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000539 * Returns true if @s2tte has HIPAS=@hipas.
540 */
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100541static inline bool s2tte_has_hipas(unsigned long s2tte, unsigned long hipas)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000542{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100543 unsigned long desc_type = s2tte & S2TT_DESC_TYPE_MASK;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000544 unsigned long invalid_desc_hipas = s2tte & S2TTE_INVALID_HIPAS_MASK;
545
AlexeiFedorov63614ea2023-07-14 17:07:20 +0100546 return ((desc_type == S2TTE_INVALID) && (invalid_desc_hipas == hipas));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000547}
548
549/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100550 * Returns true if @s2tte has HIPAS=UNASSIGNED and RIPAS=@ripas.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000551 */
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100552static inline bool s2tte_has_unassigned_ripas(unsigned long s2tte,
553 unsigned long ripas)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000554{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100555 return (((s2tte & S2TTE_INVALID_RIPAS_MASK) == ripas) &&
556 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED));
557}
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100558
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100559/*
560 * Returns true if @s2tte has HIPAS=ASSIGNED and RIPAS=@ripas.
561 */
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100562static inline bool s2tte_has_assigned_ripas(unsigned long s2tte,
563 unsigned long ripas)
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100564{
565 return (((s2tte & S2TTE_INVALID_RIPAS_MASK) == ripas) &&
566 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_ASSIGNED));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100567}
568
569/*
AlexeiFedorov0f9cd1f2023-07-10 17:04:58 +0100570 * Returns true if @s2tte has HIPAS=UNASSIGNED.
571 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000572bool s2tte_is_unassigned(const struct s2tt_context *s2_ctx, unsigned long s2tte)
AlexeiFedorov0f9cd1f2023-07-10 17:04:58 +0100573{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000574 (void)s2_ctx;
575
AlexeiFedorov0f9cd1f2023-07-10 17:04:58 +0100576 return s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED);
577}
578
579/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100580 * Returns true if @s2tte is an unassigned_empty.
581 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000582bool s2tte_is_unassigned_empty(const struct s2tt_context *s2_ctx,
583 unsigned long s2tte)
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100584{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000585 (void)s2_ctx;
586
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100587 return (((s2tte & S2TTE_NS) == 0UL) &&
588 s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_EMPTY));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100589}
590
591/*
592 * Returns true if @s2tte is an unassigned_ram.
593 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000594bool s2tte_is_unassigned_ram(const struct s2tt_context *s2_ctx,
595 unsigned long s2tte)
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100596{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000597 (void)s2_ctx;
598
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100599 return s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_RAM);
600}
601
602/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100603 * Returns true if @s2tte is unassigned_ns.
604 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000605bool s2tte_is_unassigned_ns(const struct s2tt_context *s2_ctx,
606 unsigned long s2tte)
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100607{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000608 (void)s2_ctx;
609
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100610 return (((s2tte & S2TTE_NS) != 0UL) &&
611 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000612}
613
614/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100615 * Returns true if @s2tte has RIPAS=DESTROYED.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000616 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000617bool s2tte_is_unassigned_destroyed(const struct s2tt_context *s2_ctx,
618 unsigned long s2tte)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000619{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000620 (void)s2_ctx;
621
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100622 return s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_DESTROYED);
623}
624
625/*
626 * Returns true if @s2tte is an assigned_destroyed.
627 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000628bool s2tte_is_assigned_destroyed(const struct s2tt_context *s2_ctx,
629 unsigned long s2tte, long level)
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100630{
631 (void)level;
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000632 (void)s2_ctx;
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100633
634 return s2tte_has_assigned_ripas(s2tte, S2TTE_INVALID_RIPAS_DESTROYED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000635}
636
637/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100638 * Returns true if @s2tte is an assigned_empty.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000639 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000640bool s2tte_is_assigned_empty(const struct s2tt_context *s2_ctx,
641 unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000642{
643 (void)level;
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000644 (void)s2_ctx;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000645
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100646 return s2tte_has_assigned_ripas(s2tte, S2TTE_INVALID_RIPAS_EMPTY);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000647}
648
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000649static bool s2tte_check(const struct s2tt_context *s2_ctx, unsigned long s2tte,
650 long level, unsigned long ns)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000651{
652 unsigned long desc_type;
653
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000654 (void)s2_ctx;
655
Soby Mathewb4c6df42022-11-09 11:13:29 +0000656 if ((s2tte & S2TTE_NS) != ns) {
657 return false;
658 }
659
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100660 desc_type = s2tte & S2TT_DESC_TYPE_MASK;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000661
662 /* Only pages at L3 and valid blocks at L2 allowed */
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100663 if (((level == S2TT_PAGE_LEVEL) && (desc_type == S2TTE_L3_PAGE)) ||
664 ((level == S2TT_MIN_BLOCK_LEVEL) && (desc_type == S2TTE_L012_BLOCK))) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000665 return true;
666 }
667
668 return false;
669}
670
671/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100672 * Returns true if @s2tte is an assigned_ram.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000673 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000674bool s2tte_is_assigned_ram(const struct s2tt_context *s2_ctx,
675 unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000676{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000677 return s2tte_check(s2_ctx, s2tte, level, 0UL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000678}
679
680/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100681 * Returns true if @s2tte is an assigned_ns s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000682 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000683bool s2tte_is_assigned_ns(const struct s2tt_context *s2_ctx,
684 unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000685{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000686 return s2tte_check(s2_ctx, s2tte, level, S2TTE_NS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000687}
688
689/*
690 * Returns true if @s2tte is a table at level @level.
691 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000692bool s2tte_is_table(const struct s2tt_context *s2_ctx, unsigned long s2tte,
693 long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000694{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000695 (void)s2_ctx;
696
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100697 return ((level < S2TT_PAGE_LEVEL) &&
698 ((s2tte & S2TT_DESC_TYPE_MASK) == S2TTE_L012_TABLE));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000699}
700
701/*
702 * Returns RIPAS of @s2tte.
703 *
704 * Caller should ensure that HIPAS=UNASSIGNED or HIPAS=ASSIGNED.
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100705 * The s2tte, if valid, should correspond to RIPAS_RAM.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000706 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000707enum ripas s2tte_get_ripas(const struct s2tt_context *s2_ctx, unsigned long s2tte)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000708{
709 unsigned long desc_ripas = s2tte & S2TTE_INVALID_RIPAS_MASK;
710
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000711 (void)s2_ctx;
712
Soby Mathewb4c6df42022-11-09 11:13:29 +0000713 /*
714 * If valid s2tte descriptor is passed, then ensure S2AP[0]
715 * bit is 1 (S2AP is set to RW for lower EL), which corresponds
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100716 * to RIPAS_RAM (bits[6:5] = b01) on a valid descriptor.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000717 */
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100718 assert(((s2tte & S2TT_DESC_TYPE_MASK) == S2TTE_INVALID) ||
719 (desc_ripas == S2TTE_INVALID_RIPAS_RAM));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000720
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100721 assert(EXTRACT(S2TTE_INVALID_HIPAS, s2tte) <=
722 EXTRACT(S2TTE_INVALID_HIPAS, S2TTE_INVALID_HIPAS_ASSIGNED));
723
724 desc_ripas = desc_ripas >> S2TTE_INVALID_RIPAS_SHIFT;
725
726 assert(desc_ripas <= (unsigned int)RIPAS_DESTROYED);
727
728 return (enum ripas)desc_ripas;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000729}
730
731/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100732 * Populates @s2tt with unassigned_empty s2ttes.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000733 *
734 * The granule is populated before it is made a table,
735 * hence, don't use s2tte_write for access.
736 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000737void s2tt_init_unassigned_empty(const struct s2tt_context *s2_ctx,
738 unsigned long *s2tt)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000739{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100740 assert(s2tt != NULL);
741
742 unsigned long s2tte =
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000743 s2tte_create_unassigned_empty(s2_ctx);
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100744
Soby Mathewb4c6df42022-11-09 11:13:29 +0000745 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100746 s2tt[i] = s2tte;
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100747 }
748
749 dsb(ish);
750}
751
752/*
753 * Populates @s2tt with unassigned_ram s2ttes.
754 *
755 * The granule is populated before it is made a table,
756 * hence, don't use s2tte_write for access.
757 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000758void s2tt_init_unassigned_ram(const struct s2tt_context *s2_ctx,
759 unsigned long *s2tt)
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100760{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100761 assert(s2tt != NULL);
762
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000763 unsigned long s2tte = s2tte_create_unassigned_ram(s2_ctx);
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100764
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100765 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100766 s2tt[i] = s2tte;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000767 }
768
769 dsb(ish);
770}
771
772/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100773 * Populates @s2tt with unassigned_ns s2ttes.
774 *
775 * The granule is populated before it is made a table,
776 * hence, don't use s2tte_write for access.
777 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000778void s2tt_init_unassigned_ns(const struct s2tt_context *s2_ctx,
779 unsigned long *s2tt)
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100780{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100781 assert(s2tt != NULL);
782
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000783 unsigned long s2tte = s2tte_create_unassigned_ns(s2_ctx);
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100784
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100785 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100786 s2tt[i] = s2tte;
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100787 }
788
789 dsb(ish);
790}
791
792/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000793 * Populates @s2tt with s2ttes which have HIPAS=DESTROYED.
794 *
795 * The granule is populated before it is made a table,
796 * hence, don't use s2tte_write for access.
797 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000798void s2tt_init_unassigned_destroyed(const struct s2tt_context *s2_ctx,
799 unsigned long *s2tt)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000800{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100801 assert(s2tt != NULL);
802
803 unsigned long s2tte =
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000804 s2tte_create_unassigned_destroyed(s2_ctx);
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100805
Soby Mathewb4c6df42022-11-09 11:13:29 +0000806 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100807 s2tt[i] = s2tte;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000808 }
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100809 dsb(ish);
810}
Soby Mathewb4c6df42022-11-09 11:13:29 +0000811
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100812/*
813 * Populates @s2tt with HIPAS=ASSIGNED, RIPAS=DESTROYED s2ttes that refer to a
814 * contiguous memory block starting at @pa, and mapped at level @level.
815 *
816 * The granule is populated before it is made a table,
817 * hence, don't use s2tte_write for access.
818 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000819void s2tt_init_assigned_destroyed(const struct s2tt_context *s2_ctx,
820 unsigned long *s2tt, unsigned long pa,
821 long level)
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100822{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100823 assert(level >= S2TT_MIN_BLOCK_LEVEL);
824 assert(level <= S2TT_PAGE_LEVEL);
825 assert(s2tt != NULL);
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000826 assert(s2tte_is_addr_lvl_aligned(s2_ctx, pa, level));
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100827
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100828 const unsigned long map_size = s2tte_map_size(level);
829
830 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000831 s2tt[i] = s2tte_create_assigned_destroyed(s2_ctx, pa, level);
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100832 pa += map_size;
833 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000834 dsb(ish);
835}
836
Soby Mathewb4c6df42022-11-09 11:13:29 +0000837/*
838 * Populates @s2tt with HIPAS=ASSIGNED, RIPAS=EMPTY s2ttes that refer to a
839 * contiguous memory block starting at @pa, and mapped at level @level.
840 *
841 * The granule is populated before it is made a table,
842 * hence, don't use s2tte_write for access.
843 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000844void s2tt_init_assigned_empty(const struct s2tt_context *s2_ctx,
845 unsigned long *s2tt, unsigned long pa,
846 long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000847{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100848 assert(level >= S2TT_MIN_BLOCK_LEVEL);
849 assert(level <= S2TT_PAGE_LEVEL);
850 assert(s2tt != NULL);
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000851 assert(s2tte_is_addr_lvl_aligned(s2_ctx, pa, level));
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100852
Soby Mathewb4c6df42022-11-09 11:13:29 +0000853 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000854
AlexeiFedorov3a739332023-04-13 13:54:04 +0100855 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000856 s2tt[i] = s2tte_create_assigned_empty(s2_ctx, pa, level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000857 pa += map_size;
858 }
859 dsb(ish);
860}
861
862/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100863 * Populates @s2tt with assigned_ram s2ttes that refer to a
Soby Mathewb4c6df42022-11-09 11:13:29 +0000864 * contiguous memory block starting at @pa, and mapped at level @level.
865 *
866 * The granule is populated before it is made a table,
867 * hence, don't use s2tte_write for access.
868 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000869void s2tt_init_assigned_ram(const struct s2tt_context *s2_ctx,
870 unsigned long *s2tt, unsigned long pa,
871 long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000872{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100873 assert(level >= S2TT_MIN_BLOCK_LEVEL);
874 assert(level <= S2TT_PAGE_LEVEL);
875 assert(s2tt != NULL);
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000876 assert(s2tte_is_addr_lvl_aligned(s2_ctx, pa, level));
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100877
Soby Mathewb4c6df42022-11-09 11:13:29 +0000878 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000879
AlexeiFedorov3a739332023-04-13 13:54:04 +0100880 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000881 s2tt[i] = s2tte_create_assigned_ram(s2_ctx, pa, level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000882 pa += map_size;
883 }
884 dsb(ish);
885}
886
887/*
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +0100888 * Populates @s2tt with NS attributes @attrs that refer to a
Soby Mathewb4c6df42022-11-09 11:13:29 +0000889 * contiguous memory block starting at @pa, and mapped at level @level.
890 *
891 * The granule is populated before it is made a table,
892 * hence, don't use s2tte_write for access.
893 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000894void s2tt_init_assigned_ns(const struct s2tt_context *s2_ctx,
895 unsigned long *s2tt, unsigned long attrs,
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +0100896 unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000897{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100898 assert(level >= S2TT_MIN_BLOCK_LEVEL);
899 assert(level <= S2TT_PAGE_LEVEL);
900 assert(s2tt != NULL);
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000901 assert(s2tte_is_addr_lvl_aligned(s2_ctx, pa, level));
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100902
Soby Mathewb4c6df42022-11-09 11:13:29 +0000903 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000904
AlexeiFedorov3a739332023-04-13 13:54:04 +0100905 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100906 unsigned long s2tte = attrs & S2TTE_NS_ATTR_HOST_MASK;
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +0100907
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000908 s2tt[i] = s2tte_create_assigned_ns(s2_ctx, s2tte | pa, level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000909 pa += map_size;
910 }
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +0100911
Soby Mathewb4c6df42022-11-09 11:13:29 +0000912 dsb(ish);
913}
914
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100915/*
916 * Returns true if s2tte has 'output address' field, namely, if it is one of:
917 * - assigned_empty
918 * - assigned_ram
919 * - assigned_ns
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100920 * - assigned_destroyed
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100921 * - table
922 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000923static bool s2tte_has_pa(const struct s2tt_context *s2_ctx,
924 unsigned long s2tte, long level)
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100925{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100926 unsigned long desc_type = s2tte & S2TT_DESC_TYPE_MASK;
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100927
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100928 return ((desc_type != S2TTE_INVALID) || /* block, page or table */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000929 s2tte_is_assigned_empty(s2_ctx, s2tte, level) ||
930 s2tte_is_assigned_destroyed(s2_ctx, s2tte, level));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100931}
932
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100933/*
934 * Returns true if s2tte is a live RTTE entry. i.e.,
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100935 * HIPAS is ASSIGNED.
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100936 *
937 * NOTE: For now, only the RTTE with PA are live.
938 * This could change with EXPORT/IMPORT support.
939 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000940static bool s2tte_is_live(const struct s2tt_context *s2_ctx,
941 unsigned long s2tte, long level)
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100942{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000943 return s2tte_has_pa(s2_ctx, s2tte, level);
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100944}
945
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100946/* Returns physical address of a S2TTE */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000947unsigned long s2tte_pa(const struct s2tt_context *s2_ctx, unsigned long s2tte,
948 long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000949{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100950 assert(level <= S2TT_PAGE_LEVEL);
951 assert(level >= S2TT_MIN_STARTING_LEVEL);
952
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000953 if (!s2tte_has_pa(s2_ctx, s2tte, level)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000954 assert(false);
955 }
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100956
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000957 if (s2tte_is_table(s2_ctx, s2tte, level)) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100958 return addr_level_mask(s2tte, S2TT_PAGE_LEVEL);
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100959 }
960
Soby Mathewb4c6df42022-11-09 11:13:29 +0000961 return addr_level_mask(s2tte, level);
962}
963
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000964bool s2tte_is_addr_lvl_aligned(const struct s2tt_context *s2_ctx,
965 unsigned long addr, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000966{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000967 (void)s2_ctx;
968
Soby Mathewb4c6df42022-11-09 11:13:29 +0000969 return (addr == addr_level_mask(addr, level));
970}
971
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000972typedef bool (*s2tte_type_checker)(const struct s2tt_context *s2_ctx,
973 unsigned long s2tte);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000974
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000975static bool table_is_uniform_block(const struct s2tt_context *s2_ctx,
976 unsigned long *table,
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100977 s2tte_type_checker s2tte_is_x)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000978{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100979 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
980 unsigned long s2tte = s2tte_read(&table[i]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000981
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000982 if (!s2tte_is_x(s2_ctx, s2tte)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000983 return false;
984 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000985 }
986
987 return true;
988}
989
990/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100991 * Returns true if all s2ttes in @table are unassigned_empty.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000992 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000993bool s2tt_is_unassigned_empty_block(const struct s2tt_context *s2_ctx,
994 unsigned long *table)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000995{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +0100996 assert(table != NULL);
997
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +0000998 return table_is_uniform_block(s2_ctx, table, s2tte_is_unassigned_empty);
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100999}
1000
1001/*
1002 * Returns true if all s2ttes in @table are unassigned_ram.
1003 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001004bool s2tt_is_unassigned_ram_block(const struct s2tt_context *s2_ctx,
1005 unsigned long *table)
AlexeiFedorovc07a6382023-04-14 11:59:18 +01001006{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001007 assert(table != NULL);
1008
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001009 return table_is_uniform_block(s2_ctx, table, s2tte_is_unassigned_ram);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001010}
1011
1012/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +01001013 * Returns true if all s2ttes in @table are unassigned_ns
1014 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001015bool s2tt_is_unassigned_ns_block(const struct s2tt_context *s2_ctx,
1016 unsigned long *table)
AlexeiFedorov5ceff352023-04-12 16:17:00 +01001017{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001018 assert(table != NULL);
1019
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001020 return table_is_uniform_block(s2_ctx, table, s2tte_is_unassigned_ns);
AlexeiFedorov5ceff352023-04-12 16:17:00 +01001021}
1022
1023/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +01001024 * Returns true if all s2ttes in @table are unassigned_destroyed
Soby Mathewb4c6df42022-11-09 11:13:29 +00001025 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001026bool s2tt_is_unassigned_destroyed_block(const struct s2tt_context *s2_ctx,
1027 unsigned long *table)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001028{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001029 assert(table != NULL);
1030
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001031 return table_is_uniform_block(s2_ctx, table,
1032 s2tte_is_unassigned_destroyed);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001033}
1034
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001035typedef bool (*s2tte_type_level_checker)(const struct s2tt_context *s2_ctx,
1036 unsigned long s2tte, long level);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001037
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001038static bool table_maps_block(const struct s2tt_context *s2_ctx,
1039 unsigned long *table,
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001040 long level,
1041 s2tte_type_level_checker s2tte_is_x,
1042 bool check_ns_attrs)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001043{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001044 assert(table != NULL);
1045
Soby Mathewb4c6df42022-11-09 11:13:29 +00001046 unsigned long base_pa;
1047 unsigned long map_size = s2tte_map_size(level);
1048 unsigned long s2tte = s2tte_read(&table[0]);
1049 unsigned int i;
1050
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001051 if (!s2tte_is_x(s2_ctx, s2tte, level)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +00001052 return false;
1053 }
1054
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001055 base_pa = s2tte_pa(s2_ctx, s2tte, level);
1056 if (!s2tte_is_addr_lvl_aligned(s2_ctx, base_pa, level - 1L)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +00001057 return false;
1058 }
1059
1060 for (i = 1U; i < S2TTES_PER_S2TT; i++) {
1061 unsigned long expected_pa = base_pa + (i * map_size);
1062
1063 s2tte = s2tte_read(&table[i]);
1064
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001065 if (!s2tte_is_x(s2_ctx, s2tte, level)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +00001066 return false;
1067 }
1068
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001069 if (s2tte_pa(s2_ctx, s2tte, level) != expected_pa) {
Soby Mathewb4c6df42022-11-09 11:13:29 +00001070 return false;
1071 }
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +01001072
1073 if (check_ns_attrs) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001074 unsigned long ns_attrs =
1075 s2tte & S2TTE_NS_ATTR_HOST_MASK;
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +01001076
1077 /*
1078 * We match all the attributes in the S2TTE
1079 * except for the AF bit.
1080 */
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001081 if ((s2tte & S2TTE_NS_ATTR_HOST_MASK) != ns_attrs) {
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +01001082 return false;
1083 }
1084 }
Soby Mathewb4c6df42022-11-09 11:13:29 +00001085 }
1086
1087 return true;
1088}
1089
1090/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001091 * Returns true if all s2ttes are assigned_empty
Soby Mathewb4c6df42022-11-09 11:13:29 +00001092 * and refer to a contiguous block of granules aligned to @level - 1.
1093 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001094bool s2tt_maps_assigned_empty_block(const struct s2tt_context *s2_ctx,
1095 unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001096{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001097 return table_maps_block(s2_ctx, table, level,
1098 s2tte_is_assigned_empty, false);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001099}
1100
1101/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001102 * Returns true if all s2ttes are assigned_ram and
Soby Mathewb4c6df42022-11-09 11:13:29 +00001103 * refer to a contiguous block of granules aligned to @level - 1.
1104 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001105bool s2tt_maps_assigned_ram_block(const struct s2tt_context *s2_ctx,
1106 unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001107{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001108 return table_maps_block(s2_ctx, table, level,
1109 s2tte_is_assigned_ram, false);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001110}
1111
1112/*
Javier Almansa Sobrino15fc44e2023-09-29 13:52:04 +01001113 * Returns true if
1114 * - all s2ttes in @table are assigned_ns s2ttes and
1115 * - they refer to a contiguous block of granules aligned to @level - 1 and
1116 * - all the s2tte attributes in @table controlled by the host are identical
AlexeiFedorov3a739332023-04-13 13:54:04 +01001117 *
1118 * @pre: @table maps IPA outside PAR.
Soby Mathewb4c6df42022-11-09 11:13:29 +00001119 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001120bool s2tt_maps_assigned_ns_block(const struct s2tt_context *s2_ctx,
1121 unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001122{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001123 return table_maps_block(s2_ctx, table, level,
1124 s2tte_is_assigned_ns, true);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001125}
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001126
1127/*
AlexeiFedorov3f840a02023-07-19 10:55:05 +01001128 * Returns true if all s2ttes are assigned_destroyed and
1129 * refer to a contiguous block of granules aligned to @level - 1.
1130 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001131bool s2tt_maps_assigned_destroyed_block(const struct s2tt_context *s2_ctx,
1132 unsigned long *table, long level)
AlexeiFedorov3f840a02023-07-19 10:55:05 +01001133{
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001134 return table_maps_block(s2_ctx, table, level,
1135 s2tte_is_assigned_destroyed, false);
AlexeiFedorov3f840a02023-07-19 10:55:05 +01001136}
1137
1138/*
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001139 * Scan the RTT @s2tt (which is @wi.level), from the entry (@wi.index) and
AlexeiFedorov3ebd4622023-07-18 16:27:39 +01001140 * skip the non-live entries (i.e., HIPAS=UNASSIGNED).
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001141 * In other words, the scanning stops when a live RTTE is encountered or we
1142 * reach the end of this RTT.
1143 *
1144 * For now an RTTE can be considered non-live if it doesn't have a PA.
1145 * NOTE: This would change with EXPORT/IMPORT where we may have metadata stored
1146 * in the RTTE.
1147 *
1148 * @addr is not necessarily aligned to the wi.last_level (e.g., if we were called
1149 * with RMI_ERROR_RTT).
1150 *
1151 * Returns:
1152 * - If the entry @wi.index is live, returns @addr.
1153 * - If none of the entries in the @s2tt are "live", returns the address of the
1154 * first entry in the next table.
1155 * - Otherwise, the address of the first live entry in @s2tt
1156 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001157unsigned long s2tt_skip_non_live_entries(const struct s2tt_context *s2_ctx,
1158 unsigned long addr,
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001159 unsigned long *table,
1160 const struct s2tt_walk *wi)
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001161{
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001162 assert(table != NULL);
1163 assert(wi != NULL);
1164 assert(wi->index <= S2TTES_PER_S2TT);
1165 assert(wi->last_level >= S2TT_MIN_STARTING_LEVEL);
1166 assert(wi->last_level <= S2TT_PAGE_LEVEL);
1167
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +01001168 unsigned long i, index = wi->index;
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001169 long level = wi->last_level;
1170 unsigned long map_size;
1171
1172 /*
1173 * If the entry for the map_addr is live,
1174 * return @addr.
1175 */
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001176 if (s2tte_is_live(s2_ctx, s2tte_read(&table[index]), level)) {
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001177 return addr;
1178 }
1179
1180 /*
1181 * Align the address DOWN to the map_size, as expected for the @level,
1182 * so that we can compute the correct address by using the index.
1183 */
1184 map_size = s2tte_map_size(level);
1185 addr &= ~(map_size - 1UL);
1186
1187 /* Skip the "index" */
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +01001188 for (i = index + 1UL; i < S2TTES_PER_S2TT; i++) {
Javier Almansa Sobrino1e1781e2023-10-18 18:25:56 +01001189 unsigned long s2tte = s2tte_read(&table[i]);
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001190
Javier Almansa Sobrino2595cd82024-01-25 18:25:12 +00001191 if (s2tte_is_live(s2_ctx, s2tte, level)) {
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001192 break;
1193 }
1194 }
1195
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +01001196 return (addr + ((i - index) * map_size));
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001197}