blob: a30754691acc8fecc2d58b000bd83cd61ff9f7b1 [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>
AlexeiFedorov3a739332023-04-13 13:54:04 +01007#include <attestation_token.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00008#include <bitmap.h>
9#include <buffer.h>
10#include <gic.h>
11#include <granule.h>
12#include <memory_alloc.h>
13#include <realm.h>
14#include <ripas.h>
15#include <smc.h>
16#include <status.h>
17#include <stddef.h>
18#include <string.h>
19#include <table.h>
20
21/*
22 * For prototyping we assume 4K pages
23 */
24#define BLOCK_L2_SIZE (GRANULE_SIZE * S2TTES_PER_S2TT)
25
26/*
27 * The maximum number of bits supported by the RMM for a stage 2 translation
28 * output address (including stage 2 table entries).
29 */
30#define S2TTE_OA_BITS 48
31
AlexeiFedorovc53b1f72023-07-04 15:37:03 +010032#define DESC_TYPE_MASK 3UL
33#define S2TTE_Lx_INVALID 0UL
34#define S2TTE_L012_BLOCK 1UL
35#define S2TTE_L012_TABLE 3UL
36#define S2TTE_L3_PAGE 3UL
Soby Mathewb4c6df42022-11-09 11:13:29 +000037
38/*
39 * The following constants for the mapping attributes (S2_TTE_MEMATTR_*)
40 * assume that HCR_EL2.FWB is set.
41 */
42#define S2TTE_MEMATTR_SHIFT 2
43#define S2TTE_MEMATTR_MASK (0x7UL << S2TTE_MEMATTR_SHIFT)
44#define S2TTE_MEMATTR_FWB_NORMAL_WB ((1UL << 4) | (2UL << 2))
45#define S2TTE_MEMATTR_FWB_RESERVED ((1UL << 4) | (0UL << 2))
46
47#define S2TTE_AP_SHIFT 6
48#define S2TTE_AP_MASK (3UL << S2TTE_AP_SHIFT)
49#define S2TTE_AP_RW (3UL << S2TTE_AP_SHIFT)
50
51#define S2TTE_SH_SHIFT 8
52#define S2TTE_SH_MASK (3UL << S2TTE_SH_SHIFT)
53#define S2TTE_SH_NS (0UL << S2TTE_SH_SHIFT)
54#define S2TTE_SH_RESERVED (1UL << S2TTE_SH_SHIFT)
55#define S2TTE_SH_OS (2UL << S2TTE_SH_SHIFT)
56#define S2TTE_SH_IS (3UL << S2TTE_SH_SHIFT) /* Inner Shareable */
57
58/*
59 * We set HCR_EL2.FWB So we set bit[4] to 1 and bits[3:2] to 2 and force
60 * everyting to be Normal Write-Back
61 */
62#define S2TTE_MEMATTR_FWB_NORMAL_WB ((1UL << 4) | (2UL << 2))
63#define S2TTE_AF (1UL << 10)
64#define S2TTE_XN (2UL << 53)
65#define S2TTE_NS (1UL << 55)
66
67#define S2TTE_ATTRS (S2TTE_MEMATTR_FWB_NORMAL_WB | S2TTE_AP_RW | \
68 S2TTE_SH_IS | S2TTE_AF)
69
70#define S2TTE_TABLE S2TTE_L012_TABLE
71#define S2TTE_BLOCK (S2TTE_ATTRS | S2TTE_L012_BLOCK)
72#define S2TTE_PAGE (S2TTE_ATTRS | S2TTE_L3_PAGE)
73#define S2TTE_BLOCK_NS (S2TTE_NS | S2TTE_XN | S2TTE_AF | S2TTE_L012_BLOCK)
74#define S2TTE_PAGE_NS (S2TTE_NS | S2TTE_XN | S2TTE_AF | S2TTE_L3_PAGE)
AlexeiFedorovc53b1f72023-07-04 15:37:03 +010075#define S2TTE_INVALID S2TTE_Lx_INVALID
Soby Mathewb4c6df42022-11-09 11:13:29 +000076
77/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +010078 * The type of stage 2 translation table entry (s2tte) is defined by:
79 * 1. Table level where it resides
80 * 2. DESC_TYPE field[1:0]
AlexeiFedorovc53b1f72023-07-04 15:37:03 +010081 * 4. HIPAS field [4:2]
82 * 4. RIPAS field [6:5]
AlexeiFedorov5ceff352023-04-12 16:17:00 +010083 * 5. NS field [55]
Soby Mathewb4c6df42022-11-09 11:13:29 +000084 *
AlexeiFedorov63614ea2023-07-14 17:07:20 +010085 * ======================================================================================
86 * s2tte type level DESC_TYPE[1:0] HIPAS[4:2] RIPAS[6:5] NS OA alignment
87 * ======================================================================================
88 * unassigned_empty any invalid[0] unassigned[0] empty[0] 0 n/a
89 * --------------------------------------------------------------------------------------
90 * unassigned_ram any invalid[0] unassigned[0] ram[1] 0 n/a
91 * --------------------------------------------------------------------------------------
92 * unassigned_destroyed any invalid[0] unassigned[0] destroyed[2] 0 n/a
93 * --------------------------------------------------------------------------------------
94 * assigned_empty 2,3 invalid[0] assigned[1] empty[0] 0 to level
95 * --------------------------------------------------------------------------------------
96 * assigned_ram 3 page[3] n/a n/a 0 to level
97 * 2 block[1] n/a n/a 0 to level
98 * --------------------------------------------------------------------------------------
99 * assigned_destroyed any invalid[0] assigned[1] destroyed[2] 0 n/a
100 * ======================================================================================
101 * unassigned_ns any invalid[0] unassigned[0] n/a 1 n/a
102 * --------------------------------------------------------------------------------------
103 * assigned_ns 3 page[3] n/a n/a 1 to level
104 * 2 block[1] n/a n/a 1 to level
105 * ======================================================================================
106 * table <=2 table[3] n/a n/a n/a to 4K
107 * ======================================================================================
Soby Mathewb4c6df42022-11-09 11:13:29 +0000108 */
109
110#define S2TTE_INVALID_HIPAS_SHIFT 2
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100111#define S2TTE_INVALID_HIPAS_WIDTH 3
Soby Mathewb4c6df42022-11-09 11:13:29 +0000112#define S2TTE_INVALID_HIPAS_MASK MASK(S2TTE_INVALID_HIPAS)
113
114#define S2TTE_INVALID_HIPAS_UNASSIGNED (INPLACE(S2TTE_INVALID_HIPAS, 0))
115#define S2TTE_INVALID_HIPAS_ASSIGNED (INPLACE(S2TTE_INVALID_HIPAS, 1))
Soby Mathewb4c6df42022-11-09 11:13:29 +0000116
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100117#define S2TTE_INVALID_RIPAS_SHIFT 5
118#define S2TTE_INVALID_RIPAS_WIDTH 2
Soby Mathewb4c6df42022-11-09 11:13:29 +0000119#define S2TTE_INVALID_RIPAS_MASK MASK(S2TTE_INVALID_RIPAS)
120
121#define S2TTE_INVALID_RIPAS_EMPTY (INPLACE(S2TTE_INVALID_RIPAS, 0))
122#define S2TTE_INVALID_RIPAS_RAM (INPLACE(S2TTE_INVALID_RIPAS, 1))
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100123#define S2TTE_INVALID_RIPAS_DESTROYED (INPLACE(S2TTE_INVALID_RIPAS, 2))
Soby Mathewb4c6df42022-11-09 11:13:29 +0000124
Soby Mathewb4c6df42022-11-09 11:13:29 +0000125#define S2TTE_INVALID_UNPROTECTED 0x0UL
126
127#define NR_RTT_LEVELS 4
128
129/*
130 * Invalidates S2 TLB entries from [ipa, ipa + size] region tagged with `vmid`.
131 */
132static void stage2_tlbi_ipa(const struct realm_s2_context *s2_ctx,
133 unsigned long ipa,
134 unsigned long size)
135{
136 /*
137 * Notes:
138 *
139 * - This follows the description provided in the Arm ARM on
140 * "Invalidation of TLB entries from stage 2 translations".
141 *
142 * - @TODO: Provide additional information to this primitive so that
143 * we can utilize:
144 * - The TTL level hint, see FEAT_TTL,
145 * - Final level lookup only invalidation,
146 * - Address range invalidation.
147 */
148
149 /*
150 * Save the current content of vttb_el2.
151 */
152 unsigned long old_vttbr_el2 = read_vttbr_el2();
153
154 /*
155 * Make 'vmid' the `current vmid`. Note that the tlbi instructions
156 * bellow target the TLB entries that match the `current vmid`.
157 */
158 write_vttbr_el2(INPLACE(VTTBR_EL2_VMID, s2_ctx->vmid));
159 isb();
160
161 /*
162 * Invalidate entries in S2 TLB caches that
163 * match both `ipa` & the `current vmid`.
164 */
165 while (size != 0UL) {
166 tlbiipas2e1is(ipa >> 12);
167 size -= GRANULE_SIZE;
168 ipa += GRANULE_SIZE;
169 }
170 dsb(ish);
171
172 /*
173 * The architecture does not require TLB invalidation by IPA to affect
174 * combined Stage-1 + Stage-2 TLBs. Therefore we must invalidate all of
175 * Stage-1 (tagged with the `current vmid`) after invalidating Stage-2.
176 */
177 tlbivmalle1is();
178 dsb(ish);
179 isb();
180
181 /*
182 * Restore the old content of vttb_el2.
183 */
184 write_vttbr_el2(old_vttbr_el2);
185 isb();
186}
187
188/*
189 * Invalidate S2 TLB entries with "addr" IPA.
190 * Call this function after:
191 * 1. A L3 page desc has been removed.
192 */
193void invalidate_page(const struct realm_s2_context *s2_ctx, unsigned long addr)
194{
195 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
196}
197
198/*
199 * Invalidate S2 TLB entries with "addr" IPA.
200 * Call this function after:
201 * 1. A L2 block desc has been removed, or
202 * 2a. A L2 table desc has been removed, where
203 * 2b. All S2TTEs in L3 table that the L2 table desc was pointed to were invalid.
204 */
205void invalidate_block(const struct realm_s2_context *s2_ctx, unsigned long addr)
206{
207 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
208}
209
210/*
211 * Invalidate S2 TLB entries with "addr" IPA.
212 * Call this function after:
213 * 1a. A L2 table desc has been removed, where
214 * 1b. Some S2TTEs in the table that the L2 table desc was pointed to were valid.
215 */
216void invalidate_pages_in_block(const struct realm_s2_context *s2_ctx, unsigned long addr)
217{
218 stage2_tlbi_ipa(s2_ctx, addr, BLOCK_L2_SIZE);
219}
220
221/*
222 * Return the index of the entry describing @addr in the translation table at
223 * level @level. This only works for non-concatenated page tables, so should
224 * not be called to get the index for the starting level.
225 *
226 * See the library pseudocode
227 * aarch64/translation/vmsa_addrcalc/AArch64.TTEntryAddress on which this is
228 * modeled.
229 */
230static unsigned long s2_addr_to_idx(unsigned long addr, long level)
231{
232 int levels = RTT_PAGE_LEVEL - level;
233 int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
234
235 addr >>= lsb;
236 addr &= (1UL << S2TTE_STRIDE) - 1;
237 return addr;
238}
239
240/*
241 * Return the index of the entry describing @addr in the translation table
242 * starting level. This may return an index >= S2TTES_PER_S2TT when the
243 * combination of @start_level and @ipa_bits implies concatenated
244 * stage 2 tables.
245 *
246 * See the library pseudocode
247 * aarch64/translation/vmsa_addrcalc/AArch64.S2SLTTEntryAddress on which
248 * this is modeled.
249 */
250static unsigned long s2_sl_addr_to_idx(unsigned long addr, int start_level,
251 unsigned long ipa_bits)
252{
253 int levels = RTT_PAGE_LEVEL - start_level;
254 int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
255
256 addr &= (1UL << ipa_bits) - 1UL;
257 addr >>= lsb;
258 return addr;
259}
260
261static unsigned long addr_level_mask(unsigned long addr, long level)
262{
263 int levels = RTT_PAGE_LEVEL - level;
264 unsigned int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
265 unsigned int msb = S2TTE_OA_BITS - 1;
266
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100267 return (addr & BIT_MASK_ULL(msb, lsb));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000268}
269
270static inline unsigned long table_entry_to_phys(unsigned long entry)
271{
272 return addr_level_mask(entry, RTT_PAGE_LEVEL);
273}
274
275static inline bool entry_is_table(unsigned long entry)
276{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100277 return ((entry & DESC_TYPE_MASK) == S2TTE_L012_TABLE);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000278}
279
280static unsigned long __table_get_entry(struct granule *g_tbl,
281 unsigned long idx)
282{
283 unsigned long *table, entry;
284
285 table = granule_map(g_tbl, SLOT_RTT);
286 entry = s2tte_read(&table[idx]);
287 buffer_unmap(table);
288
289 return entry;
290}
291
292static struct granule *__find_next_level_idx(struct granule *g_tbl,
293 unsigned long idx)
294{
295 const unsigned long entry = __table_get_entry(g_tbl, idx);
296
297 if (!entry_is_table(entry)) {
298 return NULL;
299 }
300
301 return addr_to_granule(table_entry_to_phys(entry));
302}
303
304static struct granule *__find_lock_next_level(struct granule *g_tbl,
305 unsigned long map_addr,
306 long level)
307{
308 const unsigned long idx = s2_addr_to_idx(map_addr, level);
309 struct granule *g = __find_next_level_idx(g_tbl, idx);
310
311 if (g != NULL) {
312 granule_lock(g, GRANULE_STATE_RTT);
313 }
314
315 return g;
316}
317
318/*
319 * Walk an RTT until level @level using @map_addr.
320 * @g_root is the root (level 0) table and must be locked before the call.
321 * @start_level is the initial lookup level used for the stage 2 translation
322 * tables which may depend on the configuration of the realm, factoring in the
323 * IPA size of the realm and the desired starting level (within the limits
324 * defined by the Armv8 VMSA including options for stage 2 table concatenation).
325 * The function uses hand-over-hand locking to avoid race conditions and allow
326 * concurrent access to RTT tree which is not part of the current walk; when a
327 * next level table is reached it is locked before releasing previously locked
328 * table.
329 * The walk stops when either:
330 * - The entry found is a leaf entry (not an RTT Table entry), or
331 * - Level @level is reached.
332 *
333 * On return:
334 * - rtt_walk::last_level is the last level that has been reached by the walk.
335 * - rtt_walk.g_llt points to the TABLE granule at level @rtt_walk::level.
336 * The granule is locked.
337 * - rtt_walk::index is the entry index at rtt_walk.g_llt for @map_addr.
338 */
339void rtt_walk_lock_unlock(struct granule *g_root,
340 int start_level,
341 unsigned long ipa_bits,
342 unsigned long map_addr,
343 long level,
344 struct rtt_walk *wi)
345{
346 struct granule *g_tbls[NR_RTT_LEVELS] = { NULL };
347 unsigned long sl_idx;
348 int i, last_level;
349
350 assert(start_level >= MIN_STARTING_LEVEL);
351 assert(level >= start_level);
352 assert(map_addr < (1UL << ipa_bits));
353 assert(wi != NULL);
354
355 /* Handle concatenated starting level (SL) tables */
356 sl_idx = s2_sl_addr_to_idx(map_addr, start_level, ipa_bits);
357 if (sl_idx >= S2TTES_PER_S2TT) {
358 unsigned int tt_num = (sl_idx >> S2TTE_STRIDE);
359 struct granule *g_concat_root = g_root + tt_num;
360
361 granule_lock(g_concat_root, GRANULE_STATE_RTT);
362 granule_unlock(g_root);
363 g_root = g_concat_root;
364 }
365
366 g_tbls[start_level] = g_root;
367 for (i = start_level; i < level; i++) {
368 /*
369 * Lock next RTT level. Correct locking order is guaranteed
370 * because reference is obtained from a locked granule
371 * (previous level). Also, hand-over-hand locking/unlocking is
372 * used to avoid race conditions.
373 */
374 g_tbls[i + 1] = __find_lock_next_level(g_tbls[i], map_addr, i);
375 if (g_tbls[i + 1] == NULL) {
376 last_level = i;
377 goto out;
378 }
379 granule_unlock(g_tbls[i]);
380 }
381
382 last_level = level;
383out:
384 wi->last_level = last_level;
385 wi->g_llt = g_tbls[last_level];
386 wi->index = s2_addr_to_idx(map_addr, last_level);
387}
388
389/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100390 * Creates an unassigned_empty s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000391 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100392unsigned long s2tte_create_unassigned_empty(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000393{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100394 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_EMPTY);
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100395}
396
397/*
398 * Creates an unassigned_ram s2tte.
399 */
400unsigned long s2tte_create_unassigned_ram(void)
401{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100402 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_RAM);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000403}
404
405/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100406 * Creates an unassigned_destroyed s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000407 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100408unsigned long s2tte_create_unassigned_destroyed(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000409{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100410 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_DESTROYED);
411}
412
413/*
414 * Creates an invalid s2tte with output address @pa, HIPAS=ASSIGNED and
415 * RIPAS=DESTROYED, at level @level.
416 */
417unsigned long s2tte_create_assigned_destroyed(unsigned long pa, long level)
418{
419 assert(level >= RTT_MIN_BLOCK_LEVEL);
420 assert(addr_is_level_aligned(pa, level));
421 return (pa | S2TTE_INVALID_HIPAS_ASSIGNED | S2TTE_INVALID_RIPAS_DESTROYED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000422}
423
424/*
425 * Creates an invalid s2tte with output address @pa, HIPAS=ASSIGNED and
426 * RIPAS=EMPTY, at level @level.
427 */
428unsigned long s2tte_create_assigned_empty(unsigned long pa, long level)
429{
430 assert(level >= RTT_MIN_BLOCK_LEVEL);
431 assert(addr_is_level_aligned(pa, level));
432 return (pa | S2TTE_INVALID_HIPAS_ASSIGNED | S2TTE_INVALID_RIPAS_EMPTY);
433}
434
435/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100436 * Creates an assigned_ram s2tte with output address @pa.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000437 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100438unsigned long s2tte_create_assigned_ram(unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000439{
440 assert(level >= RTT_MIN_BLOCK_LEVEL);
441 assert(addr_is_level_aligned(pa, level));
442 if (level == RTT_PAGE_LEVEL) {
443 return (pa | S2TTE_PAGE);
444 }
445 return (pa | S2TTE_BLOCK);
446}
447
448/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100449 * Creates an unassigned_ns s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000450 */
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100451unsigned long s2tte_create_unassigned_ns(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000452{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100453 return (S2TTE_NS | S2TTE_INVALID_HIPAS_UNASSIGNED |
454 S2TTE_INVALID_UNPROTECTED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000455}
456
457/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100458 * Creates an assigned_ns s2tte at level @level.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000459 *
460 * The following S2 TTE fields are provided through @s2tte argument:
461 * - The physical address
462 * - MemAttr
463 * - S2AP
464 * - Shareability
465 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100466unsigned long s2tte_create_assigned_ns(unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000467{
468 assert(level >= RTT_MIN_BLOCK_LEVEL);
469 if (level == RTT_PAGE_LEVEL) {
470 return (s2tte | S2TTE_PAGE_NS);
471 }
472 return (s2tte | S2TTE_BLOCK_NS);
473}
474
475/*
476 * Validate the portion of NS S2TTE that is provided by the host.
477 */
478bool host_ns_s2tte_is_valid(unsigned long s2tte, long level)
479{
480 unsigned long mask = addr_level_mask(~0UL, level) |
481 S2TTE_MEMATTR_MASK |
482 S2TTE_AP_MASK |
483 S2TTE_SH_MASK;
484
485 /*
486 * Test that all fields that are not controlled by the host are zero
487 * and that the output address is correctly aligned. Note that
488 * the host is permitted to map any physical address outside PAR.
489 */
490 if ((s2tte & ~mask) != 0UL) {
491 return false;
492 }
493
494 /*
495 * Only one value masked by S2TTE_MEMATTR_MASK is invalid/reserved.
496 */
497 if ((s2tte & S2TTE_MEMATTR_MASK) == S2TTE_MEMATTR_FWB_RESERVED) {
498 return false;
499 }
500
501 /*
502 * Only one value masked by S2TTE_SH_MASK is invalid/reserved.
503 */
504 if ((s2tte & S2TTE_SH_MASK) == S2TTE_SH_RESERVED) {
505 return false;
506 }
507
508 /*
509 * Note that all the values that are masked by S2TTE_AP_MASK are valid.
510 */
511 return true;
512}
513
514/*
515 * Returns the portion of NS S2TTE that is set by the host.
516 */
517unsigned long host_ns_s2tte(unsigned long s2tte, long level)
518{
519 unsigned long mask = addr_level_mask(~0UL, level) |
520 S2TTE_MEMATTR_MASK |
521 S2TTE_AP_MASK |
522 S2TTE_SH_MASK;
523 return (s2tte & mask);
524}
525
526/*
527 * Creates a table s2tte at level @level with output address @pa.
528 */
529unsigned long s2tte_create_table(unsigned long pa, long level)
530{
531 assert(level < RTT_PAGE_LEVEL);
532 assert(GRANULE_ALIGNED(pa));
533
534 return (pa | S2TTE_TABLE);
535}
536
537/*
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100538 * Returns true if s2tte has defined ripas value, namely if it is one of:
539 * - unassigned_empty
540 * - unassigned_ram
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100541 * - unassigned_destroyed
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100542 * - assigned_empty
543 * - assigned_ram
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100544 * - assigned_destroyed
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100545 */
546bool s2tte_has_ripas(unsigned long s2tte, long level)
547{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100548 return (((s2tte & S2TTE_NS) == 0UL) && !s2tte_is_table(s2tte, level));
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100549}
550
551/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000552 * Returns true if @s2tte has HIPAS=@hipas.
553 */
554static bool s2tte_has_hipas(unsigned long s2tte, unsigned long hipas)
555{
556 unsigned long desc_type = s2tte & DESC_TYPE_MASK;
557 unsigned long invalid_desc_hipas = s2tte & S2TTE_INVALID_HIPAS_MASK;
558
AlexeiFedorov63614ea2023-07-14 17:07:20 +0100559 return ((desc_type == S2TTE_INVALID) && (invalid_desc_hipas == hipas));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000560}
561
562/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100563 * Returns true if @s2tte has HIPAS=UNASSIGNED and RIPAS=@ripas.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000564 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100565static bool s2tte_has_unassigned_ripas(unsigned long s2tte, unsigned long ripas)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000566{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100567 return (((s2tte & S2TTE_INVALID_RIPAS_MASK) == ripas) &&
568 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED));
569}
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100570
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100571/*
572 * Returns true if @s2tte has HIPAS=ASSIGNED and RIPAS=@ripas.
573 */
574static bool s2tte_has_assigned_ripas(unsigned long s2tte, unsigned long ripas)
575{
576 return (((s2tte & S2TTE_INVALID_RIPAS_MASK) == ripas) &&
577 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_ASSIGNED));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100578}
579
580/*
AlexeiFedorov0f9cd1f2023-07-10 17:04:58 +0100581 * Returns true if @s2tte has HIPAS=UNASSIGNED.
582 */
583bool s2tte_is_unassigned(unsigned long s2tte)
584{
585 return s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED);
586}
587
588/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100589 * Returns true if @s2tte is an unassigned_empty.
590 */
591bool s2tte_is_unassigned_empty(unsigned long s2tte)
592{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100593 return (((s2tte & S2TTE_NS) == 0UL) &&
594 s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_EMPTY));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100595}
596
597/*
598 * Returns true if @s2tte is an unassigned_ram.
599 */
600bool s2tte_is_unassigned_ram(unsigned long s2tte)
601{
602 return s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_RAM);
603}
604
605/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100606 * Returns true if @s2tte is unassigned_ns.
607 */
608bool s2tte_is_unassigned_ns(unsigned long s2tte)
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 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100617bool s2tte_is_unassigned_destroyed(unsigned long s2tte)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000618{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100619 return s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_DESTROYED);
620}
621
622/*
623 * Returns true if @s2tte is an assigned_destroyed.
624 */
625bool s2tte_is_assigned_destroyed(unsigned long s2tte, long level)
626{
627 (void)level;
628
629 return s2tte_has_assigned_ripas(s2tte, S2TTE_INVALID_RIPAS_DESTROYED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000630}
631
632/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100633 * Returns true if @s2tte is an assigned_empty.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000634 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100635bool s2tte_is_assigned_empty(unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000636{
637 (void)level;
638
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100639 return s2tte_has_assigned_ripas(s2tte, S2TTE_INVALID_RIPAS_EMPTY);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000640}
641
642static bool s2tte_check(unsigned long s2tte, long level, unsigned long ns)
643{
644 unsigned long desc_type;
645
646 if ((s2tte & S2TTE_NS) != ns) {
647 return false;
648 }
649
650 desc_type = s2tte & DESC_TYPE_MASK;
651
652 /* Only pages at L3 and valid blocks at L2 allowed */
653 if (((level == RTT_PAGE_LEVEL) && (desc_type == S2TTE_L3_PAGE)) ||
AlexeiFedorov80c2f042022-11-25 14:54:46 +0000654 ((level == RTT_MIN_BLOCK_LEVEL) && (desc_type == S2TTE_L012_BLOCK))) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000655 return true;
656 }
657
658 return false;
659}
660
661/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100662 * Returns true if @s2tte is an assigned_ram.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000663 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100664bool s2tte_is_assigned_ram(unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000665{
666 return s2tte_check(s2tte, level, 0UL);
667}
668
669/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100670 * Returns true if @s2tte is an assigned_ns s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000671 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100672bool s2tte_is_assigned_ns(unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000673{
674 return s2tte_check(s2tte, level, S2TTE_NS);
675}
676
677/*
678 * Returns true if @s2tte is a table at level @level.
679 */
680bool s2tte_is_table(unsigned long s2tte, long level)
681{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100682 return ((level < RTT_PAGE_LEVEL) &&
683 ((s2tte & DESC_TYPE_MASK) == S2TTE_L012_TABLE));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000684}
685
686/*
687 * Returns RIPAS of @s2tte.
688 *
689 * Caller should ensure that HIPAS=UNASSIGNED or HIPAS=ASSIGNED.
690 * The s2tte must be not valid/invalid descriptor.
691 */
692enum ripas s2tte_get_ripas(unsigned long s2tte)
693{
694 unsigned long desc_ripas = s2tte & S2TTE_INVALID_RIPAS_MASK;
695
696 /*
697 * If valid s2tte descriptor is passed, then ensure S2AP[0]
698 * bit is 1 (S2AP is set to RW for lower EL), which corresponds
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100699 * to RIPAS_RAM (bits[6:5] = b01) on a valid descriptor.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000700 */
AlexeiFedorov63614ea2023-07-14 17:07:20 +0100701 if (((s2tte & DESC_TYPE_MASK) != S2TTE_INVALID) &&
Soby Mathewb4c6df42022-11-09 11:13:29 +0000702 (desc_ripas != S2TTE_INVALID_RIPAS_RAM)) {
703 assert(false);
704 }
705
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100706 switch (desc_ripas) {
707 case S2TTE_INVALID_RIPAS_EMPTY:
Yousuf A62808152022-10-31 10:35:42 +0000708 return RIPAS_EMPTY;
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100709 case S2TTE_INVALID_RIPAS_RAM:
710 return RIPAS_RAM;
711 default:
712 assert(desc_ripas == S2TTE_INVALID_RIPAS_DESTROYED);
713 return RIPAS_DESTROYED;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000714 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000715}
716
717/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100718 * Populates @s2tt with unassigned_empty s2ttes.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000719 *
720 * The granule is populated before it is made a table,
721 * hence, don't use s2tte_write for access.
722 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100723void s2tt_init_unassigned_empty(unsigned long *s2tt)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000724{
725 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100726 s2tt[i] = s2tte_create_unassigned_empty();
727 }
728
729 dsb(ish);
730}
731
732/*
733 * Populates @s2tt with unassigned_ram s2ttes.
734 *
735 * The granule is populated before it is made a table,
736 * hence, don't use s2tte_write for access.
737 */
738void s2tt_init_unassigned_ram(unsigned long *s2tt)
739{
740 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
741 s2tt[i] = s2tte_create_unassigned_ram();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000742 }
743
744 dsb(ish);
745}
746
747/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100748 * Populates @s2tt with unassigned_ns s2ttes.
749 *
750 * The granule is populated before it is made a table,
751 * hence, don't use s2tte_write for access.
752 */
753void s2tt_init_unassigned_ns(unsigned long *s2tt)
754{
755 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
756 s2tt[i] = s2tte_create_unassigned_ns();
757 }
758
759 dsb(ish);
760}
761
762/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000763 * Populates @s2tt with s2ttes which have HIPAS=DESTROYED.
764 *
765 * The granule is populated before it is made a table,
766 * hence, don't use s2tte_write for access.
767 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100768void s2tt_init_unassigned_destroyed(unsigned long *s2tt)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000769{
770 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100771 s2tt[i] = s2tte_create_unassigned_destroyed();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000772 }
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100773 dsb(ish);
774}
Soby Mathewb4c6df42022-11-09 11:13:29 +0000775
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100776/*
777 * Populates @s2tt with HIPAS=ASSIGNED, RIPAS=DESTROYED s2ttes that refer to a
778 * contiguous memory block starting at @pa, and mapped at level @level.
779 *
780 * The granule is populated before it is made a table,
781 * hence, don't use s2tte_write for access.
782 */
783void s2tt_init_assigned_destroyed(unsigned long *s2tt, unsigned long pa, long level)
784{
785 const unsigned long map_size = s2tte_map_size(level);
786
787 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
788 s2tt[i] = s2tte_create_assigned_destroyed(pa, level);
789 pa += map_size;
790 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000791 dsb(ish);
792}
793
794unsigned long s2tte_map_size(int level)
795{
796 int levels, lsb;
797
798 assert(level <= RTT_PAGE_LEVEL);
799
800 levels = RTT_PAGE_LEVEL - level;
801 lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100802 return (1UL << lsb);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000803}
804
805/*
806 * Populates @s2tt with HIPAS=ASSIGNED, RIPAS=EMPTY s2ttes that refer to a
807 * contiguous memory block starting at @pa, and mapped at level @level.
808 *
809 * The granule is populated before it is made a table,
810 * hence, don't use s2tte_write for access.
811 */
812void s2tt_init_assigned_empty(unsigned long *s2tt, unsigned long pa, long level)
813{
814 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000815
AlexeiFedorov3a739332023-04-13 13:54:04 +0100816 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000817 s2tt[i] = s2tte_create_assigned_empty(pa, level);
818 pa += map_size;
819 }
820 dsb(ish);
821}
822
823/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100824 * Populates @s2tt with assigned_ram s2ttes that refer to a
Soby Mathewb4c6df42022-11-09 11:13:29 +0000825 * contiguous memory block starting at @pa, and mapped at level @level.
826 *
827 * The granule is populated before it is made a table,
828 * hence, don't use s2tte_write for access.
829 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100830void s2tt_init_assigned_ram(unsigned long *s2tt, unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000831{
832 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000833
AlexeiFedorov3a739332023-04-13 13:54:04 +0100834 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
835 s2tt[i] = s2tte_create_assigned_ram(pa, level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000836 pa += map_size;
837 }
838 dsb(ish);
839}
840
841/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100842 * Populates @s2tt with assigned_ns s2ttes that refer to a
Soby Mathewb4c6df42022-11-09 11:13:29 +0000843 * contiguous memory block starting at @pa, and mapped at level @level.
844 *
845 * The granule is populated before it is made a table,
846 * hence, don't use s2tte_write for access.
847 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100848void s2tt_init_assigned_ns(unsigned long *s2tt, unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000849{
850 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000851
AlexeiFedorov3a739332023-04-13 13:54:04 +0100852 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
853 s2tt[i] = s2tte_create_assigned_ns(pa, level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000854 pa += map_size;
855 }
856 dsb(ish);
857}
858
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100859/*
860 * Returns true if s2tte has 'output address' field, namely, if it is one of:
861 * - assigned_empty
862 * - assigned_ram
863 * - assigned_ns
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100864 * - assigned_destroyed
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100865 * - table
866 */
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100867bool s2tte_has_pa(unsigned long s2tte, long level)
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100868{
869 unsigned long desc_type = s2tte & DESC_TYPE_MASK;
870
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100871 return ((desc_type != S2TTE_INVALID) || /* block, page or table */
872 s2tte_is_assigned_empty(s2tte, level) ||
873 s2tte_is_assigned_destroyed(s2tte, level));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100874}
875
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100876/*
877 * Returns true if s2tte is a live RTTE entry. i.e.,
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100878 * HIPAS is ASSIGNED.
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100879 *
880 * NOTE: For now, only the RTTE with PA are live.
881 * This could change with EXPORT/IMPORT support.
882 */
883bool s2tte_is_live(unsigned long s2tte, long level)
884{
885 return s2tte_has_pa(s2tte, level);
886}
887
Soby Mathewb4c6df42022-11-09 11:13:29 +0000888/* Returns physical address of a page entry or block */
889unsigned long s2tte_pa(unsigned long s2tte, long level)
890{
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100891 if (!s2tte_has_pa(s2tte, level)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000892 assert(false);
893 }
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100894
895 if (s2tte_is_table(s2tte, level)) {
896 return addr_level_mask(s2tte, RTT_PAGE_LEVEL);
897 }
898
Soby Mathewb4c6df42022-11-09 11:13:29 +0000899 return addr_level_mask(s2tte, level);
900}
901
902/* Returns physical address of a table entry */
903unsigned long s2tte_pa_table(unsigned long s2tte, long level)
904{
905 assert(s2tte_is_table(s2tte, level));
906 return addr_level_mask(s2tte, RTT_PAGE_LEVEL);
907}
908
909bool addr_is_level_aligned(unsigned long addr, long level)
910{
911 return (addr == addr_level_mask(addr, level));
912}
913
914typedef bool (*s2tte_type_checker)(unsigned long s2tte);
915
916static bool __table_is_uniform_block(unsigned long *table,
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100917 s2tte_type_checker s2tte_is_x)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000918{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100919 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
920 unsigned long s2tte = s2tte_read(&table[i]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000921
922 if (!s2tte_is_x(s2tte)) {
923 return false;
924 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000925 }
926
927 return true;
928}
929
930/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100931 * Returns true if all s2ttes in @table are unassigned_empty.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000932 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100933bool table_is_unassigned_empty_block(unsigned long *table)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000934{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100935 return __table_is_uniform_block(table, s2tte_is_unassigned_empty);
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100936}
937
938/*
939 * Returns true if all s2ttes in @table are unassigned_ram.
940 */
941bool table_is_unassigned_ram_block(unsigned long *table)
942{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100943 return __table_is_uniform_block(table, s2tte_is_unassigned_ram);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000944}
945
946/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100947 * Returns true if all s2ttes in @table are unassigned_ns
948 */
949bool table_is_unassigned_ns_block(unsigned long *table)
950{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100951 return __table_is_uniform_block(table, s2tte_is_unassigned_ns);
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100952}
953
954/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100955 * Returns true if all s2ttes in @table are unassigned_destroyed
Soby Mathewb4c6df42022-11-09 11:13:29 +0000956 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100957bool table_is_unassigned_destroyed_block(unsigned long *table)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000958{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100959 return __table_is_uniform_block(table, s2tte_is_unassigned_destroyed);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000960}
961
962typedef bool (*s2tte_type_level_checker)(unsigned long s2tte, long level);
963
964static bool __table_maps_block(unsigned long *table,
965 long level,
966 s2tte_type_level_checker s2tte_is_x)
967{
968 unsigned long base_pa;
969 unsigned long map_size = s2tte_map_size(level);
970 unsigned long s2tte = s2tte_read(&table[0]);
971 unsigned int i;
972
973 if (!s2tte_is_x(s2tte, level)) {
974 return false;
975 }
976
977 base_pa = s2tte_pa(s2tte, level);
978 if (!addr_is_level_aligned(base_pa, level - 1L)) {
979 return false;
980 }
981
982 for (i = 1U; i < S2TTES_PER_S2TT; i++) {
983 unsigned long expected_pa = base_pa + (i * map_size);
984
985 s2tte = s2tte_read(&table[i]);
986
987 if (!s2tte_is_x(s2tte, level)) {
988 return false;
989 }
990
991 if (s2tte_pa(s2tte, level) != expected_pa) {
992 return false;
993 }
994 }
995
996 return true;
997}
998
999/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001000 * Returns true if all s2ttes are assigned_empty
Soby Mathewb4c6df42022-11-09 11:13:29 +00001001 * and refer to a contiguous block of granules aligned to @level - 1.
1002 */
AlexeiFedorov3a739332023-04-13 13:54:04 +01001003bool table_maps_assigned_empty_block(unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001004{
AlexeiFedorov3a739332023-04-13 13:54:04 +01001005 return __table_maps_block(table, level, s2tte_is_assigned_empty);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001006}
1007
1008/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001009 * Returns true if all s2ttes are assigned_ram and
Soby Mathewb4c6df42022-11-09 11:13:29 +00001010 * refer to a contiguous block of granules aligned to @level - 1.
1011 */
AlexeiFedorov3a739332023-04-13 13:54:04 +01001012bool table_maps_assigned_ram_block(unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001013{
AlexeiFedorov3a739332023-04-13 13:54:04 +01001014 return __table_maps_block(table, level, s2tte_is_assigned_ram);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001015}
1016
1017/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001018 * Returns true if all s2ttes in @table are assigned_ns s2ttes and
Soby Mathewb4c6df42022-11-09 11:13:29 +00001019 * refer to a contiguous block of granules aligned to @level - 1.
AlexeiFedorov3a739332023-04-13 13:54:04 +01001020 *
1021 * @pre: @table maps IPA outside PAR.
Soby Mathewb4c6df42022-11-09 11:13:29 +00001022 */
AlexeiFedorov3a739332023-04-13 13:54:04 +01001023bool table_maps_assigned_ns_block(unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001024{
AlexeiFedorov3a739332023-04-13 13:54:04 +01001025 return __table_maps_block(table, level, s2tte_is_assigned_ns);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001026}
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001027
1028/*
1029 * Scan the RTT @s2tt (which is @wi.level), from the entry (@wi.index) and
AlexeiFedorov3ebd4622023-07-18 16:27:39 +01001030 * skip the non-live entries (i.e., HIPAS=UNASSIGNED).
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001031 * In other words, the scanning stops when a live RTTE is encountered or we
1032 * reach the end of this RTT.
1033 *
1034 * For now an RTTE can be considered non-live if it doesn't have a PA.
1035 * NOTE: This would change with EXPORT/IMPORT where we may have metadata stored
1036 * in the RTTE.
1037 *
1038 * @addr is not necessarily aligned to the wi.last_level (e.g., if we were called
1039 * with RMI_ERROR_RTT).
1040 *
1041 * Returns:
1042 * - If the entry @wi.index is live, returns @addr.
1043 * - If none of the entries in the @s2tt are "live", returns the address of the
1044 * first entry in the next table.
1045 * - Otherwise, the address of the first live entry in @s2tt
1046 */
1047unsigned long skip_non_live_entries(unsigned long addr,
1048 unsigned long *s2tt,
1049 const struct rtt_walk *wi)
1050{
1051 unsigned int i, index = wi->index;
1052 long level = wi->last_level;
1053 unsigned long map_size;
1054
1055 /*
1056 * If the entry for the map_addr is live,
1057 * return @addr.
1058 */
1059 if (s2tte_is_live(s2tte_read(&s2tt[index]), level)) {
1060 return addr;
1061 }
1062
1063 /*
1064 * Align the address DOWN to the map_size, as expected for the @level,
1065 * so that we can compute the correct address by using the index.
1066 */
1067 map_size = s2tte_map_size(level);
1068 addr &= ~(map_size - 1UL);
1069
1070 /* Skip the "index" */
1071 for (i = index + 1U; i < S2TTES_PER_S2TT; i++) {
1072 unsigned long s2tte = s2tte_read(&s2tt[i]);
1073
1074 if (s2tte_is_live(s2tte, level)) {
1075 break;
1076 }
1077 }
1078
AlexeiFedorovc53b1f72023-07-04 15:37:03 +01001079 return (addr + (i - index) * map_size);
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001080}