blob: 44d03dc8dde75bad4beed61f5cd24749eebcb7f7 [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>
8#include <buffer.h>
9#include <gic.h>
10#include <granule.h>
11#include <memory_alloc.h>
12#include <realm.h>
13#include <ripas.h>
14#include <smc.h>
15#include <status.h>
16#include <stddef.h>
17#include <string.h>
18#include <table.h>
19
20/*
21 * For prototyping we assume 4K pages
22 */
23#define BLOCK_L2_SIZE (GRANULE_SIZE * S2TTES_PER_S2TT)
24
25/*
26 * The maximum number of bits supported by the RMM for a stage 2 translation
27 * output address (including stage 2 table entries).
28 */
29#define S2TTE_OA_BITS 48
30
AlexeiFedorovc53b1f72023-07-04 15:37:03 +010031#define DESC_TYPE_MASK 3UL
32#define S2TTE_Lx_INVALID 0UL
33#define S2TTE_L012_BLOCK 1UL
34#define S2TTE_L012_TABLE 3UL
35#define S2TTE_L3_PAGE 3UL
Soby Mathewb4c6df42022-11-09 11:13:29 +000036
37/*
38 * The following constants for the mapping attributes (S2_TTE_MEMATTR_*)
39 * assume that HCR_EL2.FWB is set.
40 */
41#define S2TTE_MEMATTR_SHIFT 2
42#define S2TTE_MEMATTR_MASK (0x7UL << S2TTE_MEMATTR_SHIFT)
43#define S2TTE_MEMATTR_FWB_NORMAL_WB ((1UL << 4) | (2UL << 2))
44#define S2TTE_MEMATTR_FWB_RESERVED ((1UL << 4) | (0UL << 2))
45
46#define S2TTE_AP_SHIFT 6
47#define S2TTE_AP_MASK (3UL << S2TTE_AP_SHIFT)
48#define S2TTE_AP_RW (3UL << S2TTE_AP_SHIFT)
49
50#define S2TTE_SH_SHIFT 8
51#define S2TTE_SH_MASK (3UL << S2TTE_SH_SHIFT)
52#define S2TTE_SH_NS (0UL << S2TTE_SH_SHIFT)
53#define S2TTE_SH_RESERVED (1UL << S2TTE_SH_SHIFT)
54#define S2TTE_SH_OS (2UL << S2TTE_SH_SHIFT)
55#define S2TTE_SH_IS (3UL << S2TTE_SH_SHIFT) /* Inner Shareable */
56
57/*
58 * We set HCR_EL2.FWB So we set bit[4] to 1 and bits[3:2] to 2 and force
59 * everyting to be Normal Write-Back
60 */
61#define S2TTE_MEMATTR_FWB_NORMAL_WB ((1UL << 4) | (2UL << 2))
62#define S2TTE_AF (1UL << 10)
63#define S2TTE_XN (2UL << 53)
64#define S2TTE_NS (1UL << 55)
65
66#define S2TTE_ATTRS (S2TTE_MEMATTR_FWB_NORMAL_WB | S2TTE_AP_RW | \
67 S2TTE_SH_IS | S2TTE_AF)
68
69#define S2TTE_TABLE S2TTE_L012_TABLE
70#define S2TTE_BLOCK (S2TTE_ATTRS | S2TTE_L012_BLOCK)
71#define S2TTE_PAGE (S2TTE_ATTRS | S2TTE_L3_PAGE)
72#define S2TTE_BLOCK_NS (S2TTE_NS | S2TTE_XN | S2TTE_AF | S2TTE_L012_BLOCK)
73#define S2TTE_PAGE_NS (S2TTE_NS | S2TTE_XN | S2TTE_AF | S2TTE_L3_PAGE)
AlexeiFedorovc53b1f72023-07-04 15:37:03 +010074#define S2TTE_INVALID S2TTE_Lx_INVALID
Soby Mathewb4c6df42022-11-09 11:13:29 +000075
76/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +010077 * The type of stage 2 translation table entry (s2tte) is defined by:
78 * 1. Table level where it resides
79 * 2. DESC_TYPE field[1:0]
AlexeiFedorovc53b1f72023-07-04 15:37:03 +010080 * 4. HIPAS field [4:2]
81 * 4. RIPAS field [6:5]
AlexeiFedorov5ceff352023-04-12 16:17:00 +010082 * 5. NS field [55]
Soby Mathewb4c6df42022-11-09 11:13:29 +000083 *
AlexeiFedorov63614ea2023-07-14 17:07:20 +010084 * ======================================================================================
85 * s2tte type level DESC_TYPE[1:0] HIPAS[4:2] RIPAS[6:5] NS OA alignment
86 * ======================================================================================
87 * unassigned_empty any invalid[0] unassigned[0] empty[0] 0 n/a
88 * --------------------------------------------------------------------------------------
89 * unassigned_ram any invalid[0] unassigned[0] ram[1] 0 n/a
90 * --------------------------------------------------------------------------------------
91 * unassigned_destroyed any invalid[0] unassigned[0] destroyed[2] 0 n/a
92 * --------------------------------------------------------------------------------------
93 * assigned_empty 2,3 invalid[0] assigned[1] empty[0] 0 to level
94 * --------------------------------------------------------------------------------------
95 * assigned_ram 3 page[3] n/a n/a 0 to level
96 * 2 block[1] n/a n/a 0 to level
97 * --------------------------------------------------------------------------------------
98 * assigned_destroyed any invalid[0] assigned[1] destroyed[2] 0 n/a
99 * ======================================================================================
100 * unassigned_ns any invalid[0] unassigned[0] n/a 1 n/a
101 * --------------------------------------------------------------------------------------
102 * assigned_ns 3 page[3] n/a n/a 1 to level
103 * 2 block[1] n/a n/a 1 to level
104 * ======================================================================================
105 * table <=2 table[3] n/a n/a n/a to 4K
106 * ======================================================================================
Soby Mathewb4c6df42022-11-09 11:13:29 +0000107 */
108
109#define S2TTE_INVALID_HIPAS_SHIFT 2
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100110#define S2TTE_INVALID_HIPAS_WIDTH 3
Soby Mathewb4c6df42022-11-09 11:13:29 +0000111#define S2TTE_INVALID_HIPAS_MASK MASK(S2TTE_INVALID_HIPAS)
112
113#define S2TTE_INVALID_HIPAS_UNASSIGNED (INPLACE(S2TTE_INVALID_HIPAS, 0))
114#define S2TTE_INVALID_HIPAS_ASSIGNED (INPLACE(S2TTE_INVALID_HIPAS, 1))
Soby Mathewb4c6df42022-11-09 11:13:29 +0000115
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100116#define S2TTE_INVALID_RIPAS_SHIFT 5
117#define S2TTE_INVALID_RIPAS_WIDTH 2
Soby Mathewb4c6df42022-11-09 11:13:29 +0000118#define S2TTE_INVALID_RIPAS_MASK MASK(S2TTE_INVALID_RIPAS)
119
120#define S2TTE_INVALID_RIPAS_EMPTY (INPLACE(S2TTE_INVALID_RIPAS, 0))
121#define S2TTE_INVALID_RIPAS_RAM (INPLACE(S2TTE_INVALID_RIPAS, 1))
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100122#define S2TTE_INVALID_RIPAS_DESTROYED (INPLACE(S2TTE_INVALID_RIPAS, 2))
Soby Mathewb4c6df42022-11-09 11:13:29 +0000123
Soby Mathewb4c6df42022-11-09 11:13:29 +0000124#define S2TTE_INVALID_UNPROTECTED 0x0UL
125
126#define NR_RTT_LEVELS 4
127
128/*
129 * Invalidates S2 TLB entries from [ipa, ipa + size] region tagged with `vmid`.
130 */
131static void stage2_tlbi_ipa(const struct realm_s2_context *s2_ctx,
132 unsigned long ipa,
133 unsigned long size)
134{
135 /*
136 * Notes:
137 *
138 * - This follows the description provided in the Arm ARM on
139 * "Invalidation of TLB entries from stage 2 translations".
140 *
141 * - @TODO: Provide additional information to this primitive so that
142 * we can utilize:
143 * - The TTL level hint, see FEAT_TTL,
144 * - Final level lookup only invalidation,
145 * - Address range invalidation.
146 */
147
148 /*
149 * Save the current content of vttb_el2.
150 */
151 unsigned long old_vttbr_el2 = read_vttbr_el2();
152
153 /*
154 * Make 'vmid' the `current vmid`. Note that the tlbi instructions
155 * bellow target the TLB entries that match the `current vmid`.
156 */
157 write_vttbr_el2(INPLACE(VTTBR_EL2_VMID, s2_ctx->vmid));
158 isb();
159
160 /*
161 * Invalidate entries in S2 TLB caches that
162 * match both `ipa` & the `current vmid`.
163 */
164 while (size != 0UL) {
165 tlbiipas2e1is(ipa >> 12);
166 size -= GRANULE_SIZE;
167 ipa += GRANULE_SIZE;
168 }
169 dsb(ish);
170
171 /*
172 * The architecture does not require TLB invalidation by IPA to affect
173 * combined Stage-1 + Stage-2 TLBs. Therefore we must invalidate all of
174 * Stage-1 (tagged with the `current vmid`) after invalidating Stage-2.
175 */
176 tlbivmalle1is();
177 dsb(ish);
178 isb();
179
180 /*
181 * Restore the old content of vttb_el2.
182 */
183 write_vttbr_el2(old_vttbr_el2);
184 isb();
185}
186
187/*
188 * Invalidate S2 TLB entries with "addr" IPA.
189 * Call this function after:
190 * 1. A L3 page desc has been removed.
191 */
192void invalidate_page(const struct realm_s2_context *s2_ctx, unsigned long addr)
193{
194 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
195}
196
197/*
198 * Invalidate S2 TLB entries with "addr" IPA.
199 * Call this function after:
200 * 1. A L2 block desc has been removed, or
201 * 2a. A L2 table desc has been removed, where
202 * 2b. All S2TTEs in L3 table that the L2 table desc was pointed to were invalid.
203 */
204void invalidate_block(const struct realm_s2_context *s2_ctx, unsigned long addr)
205{
206 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
207}
208
209/*
210 * Invalidate S2 TLB entries with "addr" IPA.
211 * Call this function after:
212 * 1a. A L2 table desc has been removed, where
213 * 1b. Some S2TTEs in the table that the L2 table desc was pointed to were valid.
214 */
215void invalidate_pages_in_block(const struct realm_s2_context *s2_ctx, unsigned long addr)
216{
217 stage2_tlbi_ipa(s2_ctx, addr, BLOCK_L2_SIZE);
218}
219
220/*
221 * Return the index of the entry describing @addr in the translation table at
222 * level @level. This only works for non-concatenated page tables, so should
223 * not be called to get the index for the starting level.
224 *
225 * See the library pseudocode
226 * aarch64/translation/vmsa_addrcalc/AArch64.TTEntryAddress on which this is
227 * modeled.
228 */
229static unsigned long s2_addr_to_idx(unsigned long addr, long level)
230{
231 int levels = RTT_PAGE_LEVEL - level;
232 int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
233
234 addr >>= lsb;
235 addr &= (1UL << S2TTE_STRIDE) - 1;
236 return addr;
237}
238
239/*
240 * Return the index of the entry describing @addr in the translation table
241 * starting level. This may return an index >= S2TTES_PER_S2TT when the
242 * combination of @start_level and @ipa_bits implies concatenated
243 * stage 2 tables.
244 *
245 * See the library pseudocode
246 * aarch64/translation/vmsa_addrcalc/AArch64.S2SLTTEntryAddress on which
247 * this is modeled.
248 */
249static unsigned long s2_sl_addr_to_idx(unsigned long addr, int start_level,
250 unsigned long ipa_bits)
251{
252 int levels = RTT_PAGE_LEVEL - start_level;
253 int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
254
255 addr &= (1UL << ipa_bits) - 1UL;
256 addr >>= lsb;
257 return addr;
258}
259
AlexeiFedorov7641a812023-08-22 14:31:27 +0100260static unsigned long addr_level_mask(unsigned long addr, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000261{
262 int levels = RTT_PAGE_LEVEL - level;
263 unsigned int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
264 unsigned int msb = S2TTE_OA_BITS - 1;
265
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100266 return (addr & BIT_MASK_ULL(msb, lsb));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000267}
268
269static inline unsigned long table_entry_to_phys(unsigned long entry)
270{
271 return addr_level_mask(entry, RTT_PAGE_LEVEL);
272}
273
274static inline bool entry_is_table(unsigned long entry)
275{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100276 return ((entry & DESC_TYPE_MASK) == S2TTE_L012_TABLE);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000277}
278
279static unsigned long __table_get_entry(struct granule *g_tbl,
280 unsigned long idx)
281{
282 unsigned long *table, entry;
283
284 table = granule_map(g_tbl, SLOT_RTT);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100285 assert(table != NULL);
286
Soby Mathewb4c6df42022-11-09 11:13:29 +0000287 entry = s2tte_read(&table[idx]);
288 buffer_unmap(table);
289
290 return entry;
291}
292
293static struct granule *__find_next_level_idx(struct granule *g_tbl,
294 unsigned long idx)
295{
296 const unsigned long entry = __table_get_entry(g_tbl, idx);
297
298 if (!entry_is_table(entry)) {
299 return NULL;
300 }
301
302 return addr_to_granule(table_entry_to_phys(entry));
303}
304
305static struct granule *__find_lock_next_level(struct granule *g_tbl,
306 unsigned long map_addr,
307 long level)
308{
309 const unsigned long idx = s2_addr_to_idx(map_addr, level);
310 struct granule *g = __find_next_level_idx(g_tbl, idx);
311
312 if (g != NULL) {
313 granule_lock(g, GRANULE_STATE_RTT);
314 }
315
316 return g;
317}
318
319/*
320 * Walk an RTT until level @level using @map_addr.
321 * @g_root is the root (level 0) table and must be locked before the call.
322 * @start_level is the initial lookup level used for the stage 2 translation
323 * tables which may depend on the configuration of the realm, factoring in the
324 * IPA size of the realm and the desired starting level (within the limits
325 * defined by the Armv8 VMSA including options for stage 2 table concatenation).
326 * The function uses hand-over-hand locking to avoid race conditions and allow
327 * concurrent access to RTT tree which is not part of the current walk; when a
328 * next level table is reached it is locked before releasing previously locked
329 * table.
330 * The walk stops when either:
331 * - The entry found is a leaf entry (not an RTT Table entry), or
332 * - Level @level is reached.
333 *
334 * On return:
335 * - rtt_walk::last_level is the last level that has been reached by the walk.
336 * - rtt_walk.g_llt points to the TABLE granule at level @rtt_walk::level.
337 * The granule is locked.
338 * - rtt_walk::index is the entry index at rtt_walk.g_llt for @map_addr.
339 */
340void rtt_walk_lock_unlock(struct granule *g_root,
341 int start_level,
342 unsigned long ipa_bits,
343 unsigned long map_addr,
344 long level,
345 struct rtt_walk *wi)
346{
347 struct granule *g_tbls[NR_RTT_LEVELS] = { NULL };
348 unsigned long sl_idx;
349 int i, last_level;
350
351 assert(start_level >= MIN_STARTING_LEVEL);
352 assert(level >= start_level);
353 assert(map_addr < (1UL << ipa_bits));
354 assert(wi != NULL);
355
356 /* Handle concatenated starting level (SL) tables */
357 sl_idx = s2_sl_addr_to_idx(map_addr, start_level, ipa_bits);
358 if (sl_idx >= S2TTES_PER_S2TT) {
359 unsigned int tt_num = (sl_idx >> S2TTE_STRIDE);
360 struct granule *g_concat_root = g_root + tt_num;
361
362 granule_lock(g_concat_root, GRANULE_STATE_RTT);
363 granule_unlock(g_root);
364 g_root = g_concat_root;
365 }
366
367 g_tbls[start_level] = g_root;
368 for (i = start_level; i < level; i++) {
369 /*
370 * Lock next RTT level. Correct locking order is guaranteed
371 * because reference is obtained from a locked granule
372 * (previous level). Also, hand-over-hand locking/unlocking is
373 * used to avoid race conditions.
374 */
375 g_tbls[i + 1] = __find_lock_next_level(g_tbls[i], map_addr, i);
376 if (g_tbls[i + 1] == NULL) {
377 last_level = i;
378 goto out;
379 }
380 granule_unlock(g_tbls[i]);
381 }
382
383 last_level = level;
384out:
385 wi->last_level = last_level;
386 wi->g_llt = g_tbls[last_level];
387 wi->index = s2_addr_to_idx(map_addr, last_level);
388}
389
390/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100391 * Creates an unassigned_empty s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000392 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100393unsigned long s2tte_create_unassigned_empty(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000394{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100395 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_EMPTY);
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100396}
397
398/*
399 * Creates an unassigned_ram s2tte.
400 */
401unsigned long s2tte_create_unassigned_ram(void)
402{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100403 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_RAM);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000404}
405
406/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100407 * Creates an unassigned_destroyed s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000408 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100409unsigned long s2tte_create_unassigned_destroyed(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000410{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100411 return (S2TTE_INVALID_HIPAS_UNASSIGNED | S2TTE_INVALID_RIPAS_DESTROYED);
412}
413
414/*
415 * Creates an invalid s2tte with output address @pa, HIPAS=ASSIGNED and
416 * RIPAS=DESTROYED, at level @level.
417 */
418unsigned long s2tte_create_assigned_destroyed(unsigned long pa, long level)
419{
420 assert(level >= RTT_MIN_BLOCK_LEVEL);
421 assert(addr_is_level_aligned(pa, level));
422 return (pa | S2TTE_INVALID_HIPAS_ASSIGNED | S2TTE_INVALID_RIPAS_DESTROYED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000423}
424
425/*
426 * Creates an invalid s2tte with output address @pa, HIPAS=ASSIGNED and
427 * RIPAS=EMPTY, at level @level.
428 */
429unsigned long s2tte_create_assigned_empty(unsigned long pa, long level)
430{
431 assert(level >= RTT_MIN_BLOCK_LEVEL);
432 assert(addr_is_level_aligned(pa, level));
433 return (pa | S2TTE_INVALID_HIPAS_ASSIGNED | S2TTE_INVALID_RIPAS_EMPTY);
434}
435
436/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100437 * Creates an assigned_ram s2tte with output address @pa.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000438 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100439unsigned long s2tte_create_assigned_ram(unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000440{
441 assert(level >= RTT_MIN_BLOCK_LEVEL);
442 assert(addr_is_level_aligned(pa, level));
443 if (level == RTT_PAGE_LEVEL) {
444 return (pa | S2TTE_PAGE);
445 }
446 return (pa | S2TTE_BLOCK);
447}
448
449/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100450 * Creates an unassigned_ns s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000451 */
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100452unsigned long s2tte_create_unassigned_ns(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000453{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100454 return (S2TTE_NS | S2TTE_INVALID_HIPAS_UNASSIGNED |
455 S2TTE_INVALID_UNPROTECTED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000456}
457
458/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100459 * Creates an assigned_ns s2tte at level @level.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000460 *
461 * The following S2 TTE fields are provided through @s2tte argument:
462 * - The physical address
463 * - MemAttr
464 * - S2AP
465 * - Shareability
466 */
AlexeiFedorov950bd7b2023-08-24 15:25:22 +0100467unsigned long s2tte_create_assigned_ns(unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000468{
469 assert(level >= RTT_MIN_BLOCK_LEVEL);
470 if (level == RTT_PAGE_LEVEL) {
AlexeiFedorov950bd7b2023-08-24 15:25:22 +0100471 return (pa | S2TTE_PAGE_NS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000472 }
AlexeiFedorov950bd7b2023-08-24 15:25:22 +0100473 return (pa | S2TTE_BLOCK_NS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000474}
475
476/*
477 * Validate the portion of NS S2TTE that is provided by the host.
478 */
479bool host_ns_s2tte_is_valid(unsigned long s2tte, long level)
480{
481 unsigned long mask = addr_level_mask(~0UL, level) |
482 S2TTE_MEMATTR_MASK |
483 S2TTE_AP_MASK |
484 S2TTE_SH_MASK;
485
486 /*
487 * Test that all fields that are not controlled by the host are zero
488 * and that the output address is correctly aligned. Note that
489 * the host is permitted to map any physical address outside PAR.
490 */
491 if ((s2tte & ~mask) != 0UL) {
492 return false;
493 }
494
495 /*
496 * Only one value masked by S2TTE_MEMATTR_MASK is invalid/reserved.
497 */
498 if ((s2tte & S2TTE_MEMATTR_MASK) == S2TTE_MEMATTR_FWB_RESERVED) {
499 return false;
500 }
501
502 /*
503 * Only one value masked by S2TTE_SH_MASK is invalid/reserved.
504 */
505 if ((s2tte & S2TTE_SH_MASK) == S2TTE_SH_RESERVED) {
506 return false;
507 }
508
509 /*
510 * Note that all the values that are masked by S2TTE_AP_MASK are valid.
511 */
512 return true;
513}
514
515/*
516 * Returns the portion of NS S2TTE that is set by the host.
517 */
518unsigned long host_ns_s2tte(unsigned long s2tte, long level)
519{
520 unsigned long mask = addr_level_mask(~0UL, level) |
521 S2TTE_MEMATTR_MASK |
522 S2TTE_AP_MASK |
523 S2TTE_SH_MASK;
524 return (s2tte & mask);
525}
526
527/*
528 * Creates a table s2tte at level @level with output address @pa.
529 */
530unsigned long s2tte_create_table(unsigned long pa, long level)
531{
532 assert(level < RTT_PAGE_LEVEL);
533 assert(GRANULE_ALIGNED(pa));
534
535 return (pa | S2TTE_TABLE);
536}
537
538/*
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100539 * Returns true if s2tte has defined ripas value, namely if it is one of:
540 * - unassigned_empty
541 * - unassigned_ram
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100542 * - unassigned_destroyed
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100543 * - assigned_empty
544 * - assigned_ram
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100545 * - assigned_destroyed
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100546 */
547bool s2tte_has_ripas(unsigned long s2tte, long level)
548{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100549 return (((s2tte & S2TTE_NS) == 0UL) && !s2tte_is_table(s2tte, level));
AlexeiFedorov0fb44552023-04-14 15:37:58 +0100550}
551
552/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000553 * Returns true if @s2tte has HIPAS=@hipas.
554 */
555static bool s2tte_has_hipas(unsigned long s2tte, unsigned long hipas)
556{
557 unsigned long desc_type = s2tte & DESC_TYPE_MASK;
558 unsigned long invalid_desc_hipas = s2tte & S2TTE_INVALID_HIPAS_MASK;
559
AlexeiFedorov63614ea2023-07-14 17:07:20 +0100560 return ((desc_type == S2TTE_INVALID) && (invalid_desc_hipas == hipas));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000561}
562
563/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100564 * Returns true if @s2tte has HIPAS=UNASSIGNED and RIPAS=@ripas.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000565 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100566static bool s2tte_has_unassigned_ripas(unsigned long s2tte, unsigned long ripas)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000567{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100568 return (((s2tte & S2TTE_INVALID_RIPAS_MASK) == ripas) &&
569 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED));
570}
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100571
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100572/*
573 * Returns true if @s2tte has HIPAS=ASSIGNED and RIPAS=@ripas.
574 */
575static bool s2tte_has_assigned_ripas(unsigned long s2tte, unsigned long ripas)
576{
577 return (((s2tte & S2TTE_INVALID_RIPAS_MASK) == ripas) &&
578 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_ASSIGNED));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100579}
580
581/*
AlexeiFedorov0f9cd1f2023-07-10 17:04:58 +0100582 * Returns true if @s2tte has HIPAS=UNASSIGNED.
583 */
584bool s2tte_is_unassigned(unsigned long s2tte)
585{
586 return s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED);
587}
588
589/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100590 * Returns true if @s2tte is an unassigned_empty.
591 */
592bool s2tte_is_unassigned_empty(unsigned long s2tte)
593{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100594 return (((s2tte & S2TTE_NS) == 0UL) &&
595 s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_EMPTY));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100596}
597
598/*
599 * Returns true if @s2tte is an unassigned_ram.
600 */
601bool s2tte_is_unassigned_ram(unsigned long s2tte)
602{
603 return s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_RAM);
604}
605
606/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100607 * Returns true if @s2tte is unassigned_ns.
608 */
609bool s2tte_is_unassigned_ns(unsigned long s2tte)
610{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100611 return (((s2tte & S2TTE_NS) != 0UL) &&
612 s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000613}
614
615/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100616 * Returns true if @s2tte has RIPAS=DESTROYED.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000617 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100618bool s2tte_is_unassigned_destroyed(unsigned long s2tte)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000619{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100620 return s2tte_has_unassigned_ripas(s2tte, S2TTE_INVALID_RIPAS_DESTROYED);
621}
622
623/*
624 * Returns true if @s2tte is an assigned_destroyed.
625 */
626bool s2tte_is_assigned_destroyed(unsigned long s2tte, long level)
627{
628 (void)level;
629
630 return s2tte_has_assigned_ripas(s2tte, S2TTE_INVALID_RIPAS_DESTROYED);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000631}
632
633/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100634 * Returns true if @s2tte is an assigned_empty.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000635 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100636bool s2tte_is_assigned_empty(unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000637{
638 (void)level;
639
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100640 return s2tte_has_assigned_ripas(s2tte, S2TTE_INVALID_RIPAS_EMPTY);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000641}
642
643static bool s2tte_check(unsigned long s2tte, long level, unsigned long ns)
644{
645 unsigned long desc_type;
646
647 if ((s2tte & S2TTE_NS) != ns) {
648 return false;
649 }
650
651 desc_type = s2tte & DESC_TYPE_MASK;
652
653 /* Only pages at L3 and valid blocks at L2 allowed */
654 if (((level == RTT_PAGE_LEVEL) && (desc_type == S2TTE_L3_PAGE)) ||
AlexeiFedorov80c2f042022-11-25 14:54:46 +0000655 ((level == RTT_MIN_BLOCK_LEVEL) && (desc_type == S2TTE_L012_BLOCK))) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000656 return true;
657 }
658
659 return false;
660}
661
662/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100663 * Returns true if @s2tte is an assigned_ram.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000664 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100665bool s2tte_is_assigned_ram(unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000666{
667 return s2tte_check(s2tte, level, 0UL);
668}
669
670/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100671 * Returns true if @s2tte is an assigned_ns s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000672 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100673bool s2tte_is_assigned_ns(unsigned long s2tte, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000674{
675 return s2tte_check(s2tte, level, S2TTE_NS);
676}
677
678/*
679 * Returns true if @s2tte is a table at level @level.
680 */
681bool s2tte_is_table(unsigned long s2tte, long level)
682{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100683 return ((level < RTT_PAGE_LEVEL) &&
684 ((s2tte & DESC_TYPE_MASK) == S2TTE_L012_TABLE));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000685}
686
687/*
688 * Returns RIPAS of @s2tte.
689 *
690 * Caller should ensure that HIPAS=UNASSIGNED or HIPAS=ASSIGNED.
691 * The s2tte must be not valid/invalid descriptor.
692 */
693enum ripas s2tte_get_ripas(unsigned long s2tte)
694{
695 unsigned long desc_ripas = s2tte & S2TTE_INVALID_RIPAS_MASK;
696
697 /*
698 * If valid s2tte descriptor is passed, then ensure S2AP[0]
699 * bit is 1 (S2AP is set to RW for lower EL), which corresponds
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100700 * to RIPAS_RAM (bits[6:5] = b01) on a valid descriptor.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000701 */
AlexeiFedorov63614ea2023-07-14 17:07:20 +0100702 if (((s2tte & DESC_TYPE_MASK) != S2TTE_INVALID) &&
Soby Mathewb4c6df42022-11-09 11:13:29 +0000703 (desc_ripas != S2TTE_INVALID_RIPAS_RAM)) {
704 assert(false);
705 }
706
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100707 switch (desc_ripas) {
708 case S2TTE_INVALID_RIPAS_EMPTY:
Yousuf A62808152022-10-31 10:35:42 +0000709 return RIPAS_EMPTY;
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100710 case S2TTE_INVALID_RIPAS_RAM:
711 return RIPAS_RAM;
712 default:
713 assert(desc_ripas == S2TTE_INVALID_RIPAS_DESTROYED);
714 return RIPAS_DESTROYED;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000715 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000716}
717
718/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100719 * Populates @s2tt with unassigned_empty s2ttes.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000720 *
721 * The granule is populated before it is made a table,
722 * hence, don't use s2tte_write for access.
723 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100724void s2tt_init_unassigned_empty(unsigned long *s2tt)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000725{
726 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100727 s2tt[i] = s2tte_create_unassigned_empty();
728 }
729
730 dsb(ish);
731}
732
733/*
734 * Populates @s2tt with unassigned_ram s2ttes.
735 *
736 * The granule is populated before it is made a table,
737 * hence, don't use s2tte_write for access.
738 */
739void s2tt_init_unassigned_ram(unsigned long *s2tt)
740{
741 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
742 s2tt[i] = s2tte_create_unassigned_ram();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000743 }
744
745 dsb(ish);
746}
747
748/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100749 * Populates @s2tt with unassigned_ns s2ttes.
750 *
751 * The granule is populated before it is made a table,
752 * hence, don't use s2tte_write for access.
753 */
754void s2tt_init_unassigned_ns(unsigned long *s2tt)
755{
756 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
757 s2tt[i] = s2tte_create_unassigned_ns();
758 }
759
760 dsb(ish);
761}
762
763/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000764 * Populates @s2tt with s2ttes which have HIPAS=DESTROYED.
765 *
766 * The granule is populated before it is made a table,
767 * hence, don't use s2tte_write for access.
768 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100769void s2tt_init_unassigned_destroyed(unsigned long *s2tt)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000770{
771 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100772 s2tt[i] = s2tte_create_unassigned_destroyed();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000773 }
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100774 dsb(ish);
775}
Soby Mathewb4c6df42022-11-09 11:13:29 +0000776
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100777/*
778 * Populates @s2tt with HIPAS=ASSIGNED, RIPAS=DESTROYED s2ttes that refer to a
779 * contiguous memory block starting at @pa, and mapped at level @level.
780 *
781 * The granule is populated before it is made a table,
782 * hence, don't use s2tte_write for access.
783 */
784void s2tt_init_assigned_destroyed(unsigned long *s2tt, unsigned long pa, long level)
785{
786 const unsigned long map_size = s2tte_map_size(level);
787
788 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
789 s2tt[i] = s2tte_create_assigned_destroyed(pa, level);
790 pa += map_size;
791 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000792 dsb(ish);
793}
794
795unsigned long s2tte_map_size(int level)
796{
797 int levels, lsb;
798
799 assert(level <= RTT_PAGE_LEVEL);
800
801 levels = RTT_PAGE_LEVEL - level;
802 lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100803 return (1UL << lsb);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000804}
805
806/*
807 * Populates @s2tt with HIPAS=ASSIGNED, RIPAS=EMPTY s2ttes that refer to a
808 * contiguous memory block starting at @pa, and mapped at level @level.
809 *
810 * The granule is populated before it is made a table,
811 * hence, don't use s2tte_write for access.
812 */
813void s2tt_init_assigned_empty(unsigned long *s2tt, unsigned long pa, long level)
814{
815 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000816
AlexeiFedorov3a739332023-04-13 13:54:04 +0100817 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000818 s2tt[i] = s2tte_create_assigned_empty(pa, level);
819 pa += map_size;
820 }
821 dsb(ish);
822}
823
824/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100825 * Populates @s2tt with assigned_ram s2ttes that refer to a
Soby Mathewb4c6df42022-11-09 11:13:29 +0000826 * contiguous memory block starting at @pa, and mapped at level @level.
827 *
828 * The granule is populated before it is made a table,
829 * hence, don't use s2tte_write for access.
830 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100831void s2tt_init_assigned_ram(unsigned long *s2tt, unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000832{
833 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000834
AlexeiFedorov3a739332023-04-13 13:54:04 +0100835 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
836 s2tt[i] = s2tte_create_assigned_ram(pa, level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000837 pa += map_size;
838 }
839 dsb(ish);
840}
841
842/*
AlexeiFedorov3a739332023-04-13 13:54:04 +0100843 * Populates @s2tt with assigned_ns s2ttes that refer to a
Soby Mathewb4c6df42022-11-09 11:13:29 +0000844 * contiguous memory block starting at @pa, and mapped at level @level.
845 *
846 * The granule is populated before it is made a table,
847 * hence, don't use s2tte_write for access.
848 */
AlexeiFedorov3a739332023-04-13 13:54:04 +0100849void s2tt_init_assigned_ns(unsigned long *s2tt, unsigned long pa, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000850{
851 const unsigned long map_size = s2tte_map_size(level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000852
AlexeiFedorov3a739332023-04-13 13:54:04 +0100853 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
854 s2tt[i] = s2tte_create_assigned_ns(pa, level);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000855 pa += map_size;
856 }
857 dsb(ish);
858}
859
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100860/*
861 * Returns true if s2tte has 'output address' field, namely, if it is one of:
862 * - assigned_empty
863 * - assigned_ram
864 * - assigned_ns
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100865 * - assigned_destroyed
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100866 * - table
867 */
AlexeiFedorov7641a812023-08-22 14:31:27 +0100868static bool s2tte_has_pa(unsigned long s2tte, long level)
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100869{
870 unsigned long desc_type = s2tte & DESC_TYPE_MASK;
871
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100872 return ((desc_type != S2TTE_INVALID) || /* block, page or table */
873 s2tte_is_assigned_empty(s2tte, level) ||
874 s2tte_is_assigned_destroyed(s2tte, level));
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100875}
876
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100877/*
878 * Returns true if s2tte is a live RTTE entry. i.e.,
AlexeiFedorov3ebd4622023-07-18 16:27:39 +0100879 * HIPAS is ASSIGNED.
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100880 *
881 * NOTE: For now, only the RTTE with PA are live.
882 * This could change with EXPORT/IMPORT support.
883 */
AlexeiFedorov7641a812023-08-22 14:31:27 +0100884static bool s2tte_is_live(unsigned long s2tte, long level)
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100885{
886 return s2tte_has_pa(s2tte, level);
887}
888
Soby Mathewb4c6df42022-11-09 11:13:29 +0000889/* Returns physical address of a page entry or block */
890unsigned long s2tte_pa(unsigned long s2tte, long level)
891{
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100892 if (!s2tte_has_pa(s2tte, level)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000893 assert(false);
894 }
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100895
896 if (s2tte_is_table(s2tte, level)) {
897 return addr_level_mask(s2tte, RTT_PAGE_LEVEL);
898 }
899
Soby Mathewb4c6df42022-11-09 11:13:29 +0000900 return addr_level_mask(s2tte, level);
901}
902
903/* Returns physical address of a table entry */
904unsigned long s2tte_pa_table(unsigned long s2tte, long level)
905{
906 assert(s2tte_is_table(s2tte, level));
907 return addr_level_mask(s2tte, RTT_PAGE_LEVEL);
908}
909
910bool addr_is_level_aligned(unsigned long addr, long level)
911{
912 return (addr == addr_level_mask(addr, level));
913}
914
915typedef bool (*s2tte_type_checker)(unsigned long s2tte);
916
917static bool __table_is_uniform_block(unsigned long *table,
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100918 s2tte_type_checker s2tte_is_x)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000919{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100920 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
921 unsigned long s2tte = s2tte_read(&table[i]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000922
923 if (!s2tte_is_x(s2tte)) {
924 return false;
925 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000926 }
927
928 return true;
929}
930
931/*
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100932 * Returns true if all s2ttes in @table are unassigned_empty.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000933 */
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100934bool table_is_unassigned_empty_block(unsigned long *table)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000935{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100936 return __table_is_uniform_block(table, s2tte_is_unassigned_empty);
AlexeiFedorovc07a6382023-04-14 11:59:18 +0100937}
938
939/*
940 * Returns true if all s2ttes in @table are unassigned_ram.
941 */
942bool table_is_unassigned_ram_block(unsigned long *table)
943{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100944 return __table_is_uniform_block(table, s2tte_is_unassigned_ram);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000945}
946
947/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100948 * Returns true if all s2ttes in @table are unassigned_ns
949 */
950bool table_is_unassigned_ns_block(unsigned long *table)
951{
AlexeiFedorov377d81f2023-04-14 16:29:12 +0100952 return __table_is_uniform_block(table, s2tte_is_unassigned_ns);
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100953}
954
955/*
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100956 * Returns true if all s2ttes in @table are unassigned_destroyed
Soby Mathewb4c6df42022-11-09 11:13:29 +0000957 */
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100958bool table_is_unassigned_destroyed_block(unsigned long *table)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000959{
AlexeiFedorovc53b1f72023-07-04 15:37:03 +0100960 return __table_is_uniform_block(table, s2tte_is_unassigned_destroyed);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000961}
962
963typedef bool (*s2tte_type_level_checker)(unsigned long s2tte, long level);
964
965static bool __table_maps_block(unsigned long *table,
966 long level,
967 s2tte_type_level_checker s2tte_is_x)
968{
969 unsigned long base_pa;
970 unsigned long map_size = s2tte_map_size(level);
971 unsigned long s2tte = s2tte_read(&table[0]);
972 unsigned int i;
973
974 if (!s2tte_is_x(s2tte, level)) {
975 return false;
976 }
977
978 base_pa = s2tte_pa(s2tte, level);
979 if (!addr_is_level_aligned(base_pa, level - 1L)) {
980 return false;
981 }
982
983 for (i = 1U; i < S2TTES_PER_S2TT; i++) {
984 unsigned long expected_pa = base_pa + (i * map_size);
985
986 s2tte = s2tte_read(&table[i]);
987
988 if (!s2tte_is_x(s2tte, level)) {
989 return false;
990 }
991
992 if (s2tte_pa(s2tte, level) != expected_pa) {
993 return false;
994 }
995 }
996
997 return true;
998}
999
1000/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001001 * Returns true if all s2ttes are assigned_empty
Soby Mathewb4c6df42022-11-09 11:13:29 +00001002 * and refer to a contiguous block of granules aligned to @level - 1.
1003 */
AlexeiFedorov3a739332023-04-13 13:54:04 +01001004bool table_maps_assigned_empty_block(unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001005{
AlexeiFedorov3a739332023-04-13 13:54:04 +01001006 return __table_maps_block(table, level, s2tte_is_assigned_empty);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001007}
1008
1009/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001010 * Returns true if all s2ttes are assigned_ram and
Soby Mathewb4c6df42022-11-09 11:13:29 +00001011 * refer to a contiguous block of granules aligned to @level - 1.
1012 */
AlexeiFedorov3a739332023-04-13 13:54:04 +01001013bool table_maps_assigned_ram_block(unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001014{
AlexeiFedorov3a739332023-04-13 13:54:04 +01001015 return __table_maps_block(table, level, s2tte_is_assigned_ram);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001016}
1017
1018/*
AlexeiFedorov3a739332023-04-13 13:54:04 +01001019 * Returns true if all s2ttes in @table are assigned_ns s2ttes and
Soby Mathewb4c6df42022-11-09 11:13:29 +00001020 * refer to a contiguous block of granules aligned to @level - 1.
AlexeiFedorov3a739332023-04-13 13:54:04 +01001021 *
1022 * @pre: @table maps IPA outside PAR.
Soby Mathewb4c6df42022-11-09 11:13:29 +00001023 */
AlexeiFedorov3a739332023-04-13 13:54:04 +01001024bool table_maps_assigned_ns_block(unsigned long *table, long level)
Soby Mathewb4c6df42022-11-09 11:13:29 +00001025{
AlexeiFedorov3a739332023-04-13 13:54:04 +01001026 return __table_maps_block(table, level, s2tte_is_assigned_ns);
Soby Mathewb4c6df42022-11-09 11:13:29 +00001027}
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001028
1029/*
AlexeiFedorov3f840a02023-07-19 10:55:05 +01001030 * Returns true if all s2ttes are assigned_destroyed and
1031 * refer to a contiguous block of granules aligned to @level - 1.
1032 */
1033bool table_maps_assigned_destroyed_block(unsigned long *table, long level)
1034{
1035 return __table_maps_block(table, level, s2tte_is_assigned_destroyed);
1036}
1037
1038/*
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001039 * Scan the RTT @s2tt (which is @wi.level), from the entry (@wi.index) and
AlexeiFedorov3ebd4622023-07-18 16:27:39 +01001040 * skip the non-live entries (i.e., HIPAS=UNASSIGNED).
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001041 * In other words, the scanning stops when a live RTTE is encountered or we
1042 * reach the end of this RTT.
1043 *
1044 * For now an RTTE can be considered non-live if it doesn't have a PA.
1045 * NOTE: This would change with EXPORT/IMPORT where we may have metadata stored
1046 * in the RTTE.
1047 *
1048 * @addr is not necessarily aligned to the wi.last_level (e.g., if we were called
1049 * with RMI_ERROR_RTT).
1050 *
1051 * Returns:
1052 * - If the entry @wi.index is live, returns @addr.
1053 * - If none of the entries in the @s2tt are "live", returns the address of the
1054 * first entry in the next table.
1055 * - Otherwise, the address of the first live entry in @s2tt
1056 */
1057unsigned long skip_non_live_entries(unsigned long addr,
1058 unsigned long *s2tt,
1059 const struct rtt_walk *wi)
1060{
1061 unsigned int i, index = wi->index;
1062 long level = wi->last_level;
1063 unsigned long map_size;
1064
1065 /*
1066 * If the entry for the map_addr is live,
1067 * return @addr.
1068 */
1069 if (s2tte_is_live(s2tte_read(&s2tt[index]), level)) {
1070 return addr;
1071 }
1072
1073 /*
1074 * Align the address DOWN to the map_size, as expected for the @level,
1075 * so that we can compute the correct address by using the index.
1076 */
1077 map_size = s2tte_map_size(level);
1078 addr &= ~(map_size - 1UL);
1079
1080 /* Skip the "index" */
1081 for (i = index + 1U; i < S2TTES_PER_S2TT; i++) {
1082 unsigned long s2tte = s2tte_read(&s2tt[i]);
1083
1084 if (s2tte_is_live(s2tte, level)) {
1085 break;
1086 }
1087 }
1088
AlexeiFedorovc53b1f72023-07-04 15:37:03 +01001089 return (addr + (i - index) * map_size);
AlexeiFedorov917eabf2023-04-24 12:20:41 +01001090}