blob: c73f57b35773c2d9586c7c067ef83adca7e9a63e [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
31#define DESC_TYPE_MASK 0x3UL
32#define S2TTE_L012_TABLE 0x3UL
33#define S2TTE_L012_BLOCK 0x1UL
34#define S2TTE_L3_PAGE 0x3UL
35#define S2TTE_Lx_INVALID 0x0UL
36
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)
74#define S2TTE_INVALID 0
75
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]
80 * 4. HIPAS field [5:2]
81 * 4. RIPAS field [6]
82 * 5. NS field [55]
Soby Mathewb4c6df42022-11-09 11:13:29 +000083 *
AlexeiFedorov5ceff352023-04-12 16:17:00 +010084 * s2tte type level DESC_TYPE[1:0] HIPAS[5:2] RIPAS[6] NS OA alignment
85 * =============================================================================
86 * unassigned_empty any invalid[0] unassigned[0] empty[0] 0 n/a
87 * -----------------------------------------------------------------------------
88 * unassigned_ram any invalid[0] unassigned[0] ram[1] 0 n/a
89 * -----------------------------------------------------------------------------
90 * assigned_empty 2,3 invalid[0] assigned[1] empty[0] 0 to level
91 * -----------------------------------------------------------------------------
92 * assigned_ram 3 page[1] n/a n/a 0 to level
93 * 2 block[3] n/a n/a 0 to level
94 * -----------------------------------------------------------------------------
95 * destroyed any invalid[0] destroyed[2] n/a 0 n/a
96 * =============================================================================
97 * unassigned_ns any invalid[0] unassigned[0] n/a 1 n/a
98 * -----------------------------------------------------------------------------
99 * assigned_ns 3 page[1] n/a n/a 1 to level
100 * 2 block[3] n/a n/a 1 to level
101 * =============================================================================
102 * table <=2 table[1] n/a n/a n/a to 4K
Soby Mathewb4c6df42022-11-09 11:13:29 +0000103 */
104
105#define S2TTE_INVALID_HIPAS_SHIFT 2
106#define S2TTE_INVALID_HIPAS_WIDTH 4
107#define S2TTE_INVALID_HIPAS_MASK MASK(S2TTE_INVALID_HIPAS)
108
109#define S2TTE_INVALID_HIPAS_UNASSIGNED (INPLACE(S2TTE_INVALID_HIPAS, 0))
110#define S2TTE_INVALID_HIPAS_ASSIGNED (INPLACE(S2TTE_INVALID_HIPAS, 1))
111#define S2TTE_INVALID_HIPAS_DESTROYED (INPLACE(S2TTE_INVALID_HIPAS, 2))
112
113#define S2TTE_INVALID_RIPAS_SHIFT 6
114#define S2TTE_INVALID_RIPAS_WIDTH 1
115#define S2TTE_INVALID_RIPAS_MASK MASK(S2TTE_INVALID_RIPAS)
116
117#define S2TTE_INVALID_RIPAS_EMPTY (INPLACE(S2TTE_INVALID_RIPAS, 0))
118#define S2TTE_INVALID_RIPAS_RAM (INPLACE(S2TTE_INVALID_RIPAS, 1))
119
120#define S2TTE_INVALID_DESTROYED S2TTE_INVALID_HIPAS_DESTROYED
121#define S2TTE_INVALID_UNPROTECTED 0x0UL
122
123#define NR_RTT_LEVELS 4
124
125/*
126 * Invalidates S2 TLB entries from [ipa, ipa + size] region tagged with `vmid`.
127 */
128static void stage2_tlbi_ipa(const struct realm_s2_context *s2_ctx,
129 unsigned long ipa,
130 unsigned long size)
131{
132 /*
133 * Notes:
134 *
135 * - This follows the description provided in the Arm ARM on
136 * "Invalidation of TLB entries from stage 2 translations".
137 *
138 * - @TODO: Provide additional information to this primitive so that
139 * we can utilize:
140 * - The TTL level hint, see FEAT_TTL,
141 * - Final level lookup only invalidation,
142 * - Address range invalidation.
143 */
144
145 /*
146 * Save the current content of vttb_el2.
147 */
148 unsigned long old_vttbr_el2 = read_vttbr_el2();
149
150 /*
151 * Make 'vmid' the `current vmid`. Note that the tlbi instructions
152 * bellow target the TLB entries that match the `current vmid`.
153 */
154 write_vttbr_el2(INPLACE(VTTBR_EL2_VMID, s2_ctx->vmid));
155 isb();
156
157 /*
158 * Invalidate entries in S2 TLB caches that
159 * match both `ipa` & the `current vmid`.
160 */
161 while (size != 0UL) {
162 tlbiipas2e1is(ipa >> 12);
163 size -= GRANULE_SIZE;
164 ipa += GRANULE_SIZE;
165 }
166 dsb(ish);
167
168 /*
169 * The architecture does not require TLB invalidation by IPA to affect
170 * combined Stage-1 + Stage-2 TLBs. Therefore we must invalidate all of
171 * Stage-1 (tagged with the `current vmid`) after invalidating Stage-2.
172 */
173 tlbivmalle1is();
174 dsb(ish);
175 isb();
176
177 /*
178 * Restore the old content of vttb_el2.
179 */
180 write_vttbr_el2(old_vttbr_el2);
181 isb();
182}
183
184/*
185 * Invalidate S2 TLB entries with "addr" IPA.
186 * Call this function after:
187 * 1. A L3 page desc has been removed.
188 */
189void invalidate_page(const struct realm_s2_context *s2_ctx, unsigned long addr)
190{
191 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
192}
193
194/*
195 * Invalidate S2 TLB entries with "addr" IPA.
196 * Call this function after:
197 * 1. A L2 block desc has been removed, or
198 * 2a. A L2 table desc has been removed, where
199 * 2b. All S2TTEs in L3 table that the L2 table desc was pointed to were invalid.
200 */
201void invalidate_block(const struct realm_s2_context *s2_ctx, unsigned long addr)
202{
203 stage2_tlbi_ipa(s2_ctx, addr, GRANULE_SIZE);
204}
205
206/*
207 * Invalidate S2 TLB entries with "addr" IPA.
208 * Call this function after:
209 * 1a. A L2 table desc has been removed, where
210 * 1b. Some S2TTEs in the table that the L2 table desc was pointed to were valid.
211 */
212void invalidate_pages_in_block(const struct realm_s2_context *s2_ctx, unsigned long addr)
213{
214 stage2_tlbi_ipa(s2_ctx, addr, BLOCK_L2_SIZE);
215}
216
217/*
218 * Return the index of the entry describing @addr in the translation table at
219 * level @level. This only works for non-concatenated page tables, so should
220 * not be called to get the index for the starting level.
221 *
222 * See the library pseudocode
223 * aarch64/translation/vmsa_addrcalc/AArch64.TTEntryAddress on which this is
224 * modeled.
225 */
226static unsigned long s2_addr_to_idx(unsigned long addr, long level)
227{
228 int levels = RTT_PAGE_LEVEL - level;
229 int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
230
231 addr >>= lsb;
232 addr &= (1UL << S2TTE_STRIDE) - 1;
233 return addr;
234}
235
236/*
237 * Return the index of the entry describing @addr in the translation table
238 * starting level. This may return an index >= S2TTES_PER_S2TT when the
239 * combination of @start_level and @ipa_bits implies concatenated
240 * stage 2 tables.
241 *
242 * See the library pseudocode
243 * aarch64/translation/vmsa_addrcalc/AArch64.S2SLTTEntryAddress on which
244 * this is modeled.
245 */
246static unsigned long s2_sl_addr_to_idx(unsigned long addr, int start_level,
247 unsigned long ipa_bits)
248{
249 int levels = RTT_PAGE_LEVEL - start_level;
250 int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
251
252 addr &= (1UL << ipa_bits) - 1UL;
253 addr >>= lsb;
254 return addr;
255}
256
257static unsigned long addr_level_mask(unsigned long addr, long level)
258{
259 int levels = RTT_PAGE_LEVEL - level;
260 unsigned int lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
261 unsigned int msb = S2TTE_OA_BITS - 1;
262
263 return addr & BIT_MASK_ULL(msb, lsb);
264}
265
266static inline unsigned long table_entry_to_phys(unsigned long entry)
267{
268 return addr_level_mask(entry, RTT_PAGE_LEVEL);
269}
270
271static inline bool entry_is_table(unsigned long entry)
272{
273 return (entry & DESC_TYPE_MASK) == S2TTE_L012_TABLE;
274}
275
276static unsigned long __table_get_entry(struct granule *g_tbl,
277 unsigned long idx)
278{
279 unsigned long *table, entry;
280
281 table = granule_map(g_tbl, SLOT_RTT);
282 entry = s2tte_read(&table[idx]);
283 buffer_unmap(table);
284
285 return entry;
286}
287
288static struct granule *__find_next_level_idx(struct granule *g_tbl,
289 unsigned long idx)
290{
291 const unsigned long entry = __table_get_entry(g_tbl, idx);
292
293 if (!entry_is_table(entry)) {
294 return NULL;
295 }
296
297 return addr_to_granule(table_entry_to_phys(entry));
298}
299
300static struct granule *__find_lock_next_level(struct granule *g_tbl,
301 unsigned long map_addr,
302 long level)
303{
304 const unsigned long idx = s2_addr_to_idx(map_addr, level);
305 struct granule *g = __find_next_level_idx(g_tbl, idx);
306
307 if (g != NULL) {
308 granule_lock(g, GRANULE_STATE_RTT);
309 }
310
311 return g;
312}
313
314/*
315 * Walk an RTT until level @level using @map_addr.
316 * @g_root is the root (level 0) table and must be locked before the call.
317 * @start_level is the initial lookup level used for the stage 2 translation
318 * tables which may depend on the configuration of the realm, factoring in the
319 * IPA size of the realm and the desired starting level (within the limits
320 * defined by the Armv8 VMSA including options for stage 2 table concatenation).
321 * The function uses hand-over-hand locking to avoid race conditions and allow
322 * concurrent access to RTT tree which is not part of the current walk; when a
323 * next level table is reached it is locked before releasing previously locked
324 * table.
325 * The walk stops when either:
326 * - The entry found is a leaf entry (not an RTT Table entry), or
327 * - Level @level is reached.
328 *
329 * On return:
330 * - rtt_walk::last_level is the last level that has been reached by the walk.
331 * - rtt_walk.g_llt points to the TABLE granule at level @rtt_walk::level.
332 * The granule is locked.
333 * - rtt_walk::index is the entry index at rtt_walk.g_llt for @map_addr.
334 */
335void rtt_walk_lock_unlock(struct granule *g_root,
336 int start_level,
337 unsigned long ipa_bits,
338 unsigned long map_addr,
339 long level,
340 struct rtt_walk *wi)
341{
342 struct granule *g_tbls[NR_RTT_LEVELS] = { NULL };
343 unsigned long sl_idx;
344 int i, last_level;
345
346 assert(start_level >= MIN_STARTING_LEVEL);
347 assert(level >= start_level);
348 assert(map_addr < (1UL << ipa_bits));
349 assert(wi != NULL);
350
351 /* Handle concatenated starting level (SL) tables */
352 sl_idx = s2_sl_addr_to_idx(map_addr, start_level, ipa_bits);
353 if (sl_idx >= S2TTES_PER_S2TT) {
354 unsigned int tt_num = (sl_idx >> S2TTE_STRIDE);
355 struct granule *g_concat_root = g_root + tt_num;
356
357 granule_lock(g_concat_root, GRANULE_STATE_RTT);
358 granule_unlock(g_root);
359 g_root = g_concat_root;
360 }
361
362 g_tbls[start_level] = g_root;
363 for (i = start_level; i < level; i++) {
364 /*
365 * Lock next RTT level. Correct locking order is guaranteed
366 * because reference is obtained from a locked granule
367 * (previous level). Also, hand-over-hand locking/unlocking is
368 * used to avoid race conditions.
369 */
370 g_tbls[i + 1] = __find_lock_next_level(g_tbls[i], map_addr, i);
371 if (g_tbls[i + 1] == NULL) {
372 last_level = i;
373 goto out;
374 }
375 granule_unlock(g_tbls[i]);
376 }
377
378 last_level = level;
379out:
380 wi->last_level = last_level;
381 wi->g_llt = g_tbls[last_level];
382 wi->index = s2_addr_to_idx(map_addr, last_level);
383}
384
385/*
386 * Creates a value which can be OR'd with an s2tte to set RIPAS=@ripas.
387 */
388unsigned long s2tte_create_ripas(enum ripas ripas)
389{
Yousuf A62808152022-10-31 10:35:42 +0000390 if (ripas == RIPAS_EMPTY) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000391 return S2TTE_INVALID_RIPAS_EMPTY;
392 }
393 return S2TTE_INVALID_RIPAS_RAM;
394}
395
396/*
397 * Creates an invalid s2tte with HIPAS=UNASSIGNED and RIPAS=@ripas.
398 */
399unsigned long s2tte_create_unassigned(enum ripas ripas)
400{
401 return S2TTE_INVALID_HIPAS_UNASSIGNED | s2tte_create_ripas(ripas);
402}
403
404/*
405 * Creates an invalid s2tte with HIPAS=DESTROYED.
406 */
407unsigned long s2tte_create_destroyed(void)
408{
409 return S2TTE_INVALID_DESTROYED;
410}
411
412/*
413 * Creates an invalid s2tte with output address @pa, HIPAS=ASSIGNED and
414 * RIPAS=EMPTY, at level @level.
415 */
416unsigned long s2tte_create_assigned_empty(unsigned long pa, long level)
417{
418 assert(level >= RTT_MIN_BLOCK_LEVEL);
419 assert(addr_is_level_aligned(pa, level));
420 return (pa | S2TTE_INVALID_HIPAS_ASSIGNED | S2TTE_INVALID_RIPAS_EMPTY);
421}
422
423/*
424 * Creates a page or block s2tte for a Protected IPA, with output address @pa.
425 */
426unsigned long s2tte_create_valid(unsigned long pa, long level)
427{
428 assert(level >= RTT_MIN_BLOCK_LEVEL);
429 assert(addr_is_level_aligned(pa, level));
430 if (level == RTT_PAGE_LEVEL) {
431 return (pa | S2TTE_PAGE);
432 }
433 return (pa | S2TTE_BLOCK);
434}
435
436/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100437 * Creates an unassigned_ns s2tte.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000438 */
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100439unsigned long s2tte_create_unassigned_ns(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000440{
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100441 return S2TTE_NS | S2TTE_INVALID_HIPAS_UNASSIGNED |
442 S2TTE_INVALID_UNPROTECTED;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000443}
444
445/*
446 * Creates a page or block s2tte for an Unprotected IPA at level @level.
447 *
448 * The following S2 TTE fields are provided through @s2tte argument:
449 * - The physical address
450 * - MemAttr
451 * - S2AP
452 * - Shareability
453 */
454unsigned long s2tte_create_valid_ns(unsigned long s2tte, long level)
455{
456 assert(level >= RTT_MIN_BLOCK_LEVEL);
457 if (level == RTT_PAGE_LEVEL) {
458 return (s2tte | S2TTE_PAGE_NS);
459 }
460 return (s2tte | S2TTE_BLOCK_NS);
461}
462
463/*
464 * Validate the portion of NS S2TTE that is provided by the host.
465 */
466bool host_ns_s2tte_is_valid(unsigned long s2tte, long level)
467{
468 unsigned long mask = addr_level_mask(~0UL, level) |
469 S2TTE_MEMATTR_MASK |
470 S2TTE_AP_MASK |
471 S2TTE_SH_MASK;
472
473 /*
474 * Test that all fields that are not controlled by the host are zero
475 * and that the output address is correctly aligned. Note that
476 * the host is permitted to map any physical address outside PAR.
477 */
478 if ((s2tte & ~mask) != 0UL) {
479 return false;
480 }
481
482 /*
483 * Only one value masked by S2TTE_MEMATTR_MASK is invalid/reserved.
484 */
485 if ((s2tte & S2TTE_MEMATTR_MASK) == S2TTE_MEMATTR_FWB_RESERVED) {
486 return false;
487 }
488
489 /*
490 * Only one value masked by S2TTE_SH_MASK is invalid/reserved.
491 */
492 if ((s2tte & S2TTE_SH_MASK) == S2TTE_SH_RESERVED) {
493 return false;
494 }
495
496 /*
497 * Note that all the values that are masked by S2TTE_AP_MASK are valid.
498 */
499 return true;
500}
501
502/*
503 * Returns the portion of NS S2TTE that is set by the host.
504 */
505unsigned long host_ns_s2tte(unsigned long s2tte, long level)
506{
507 unsigned long mask = addr_level_mask(~0UL, level) |
508 S2TTE_MEMATTR_MASK |
509 S2TTE_AP_MASK |
510 S2TTE_SH_MASK;
511 return (s2tte & mask);
512}
513
514/*
515 * Creates a table s2tte at level @level with output address @pa.
516 */
517unsigned long s2tte_create_table(unsigned long pa, long level)
518{
519 assert(level < RTT_PAGE_LEVEL);
520 assert(GRANULE_ALIGNED(pa));
521
522 return (pa | S2TTE_TABLE);
523}
524
525/*
526 * Returns true if @s2tte has HIPAS=@hipas.
527 */
528static bool s2tte_has_hipas(unsigned long s2tte, unsigned long hipas)
529{
530 unsigned long desc_type = s2tte & DESC_TYPE_MASK;
531 unsigned long invalid_desc_hipas = s2tte & S2TTE_INVALID_HIPAS_MASK;
532
533 if ((desc_type != S2TTE_Lx_INVALID) || (invalid_desc_hipas != hipas)) {
534 return false;
535 }
536 return true;
537}
538
539/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100540 * Returns true if @s2tte has HIPAS=UNASSIGNED.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000541 */
542bool s2tte_is_unassigned(unsigned long s2tte)
543{
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100544 if ((s2tte & S2TTE_NS) != 0UL) {
545 return false;
546 }
547
548 return s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED);
549}
550
551/*
552 * Returns true if @s2tte is unassigned_ns.
553 */
554bool s2tte_is_unassigned_ns(unsigned long s2tte)
555{
556 if ((s2tte & S2TTE_NS) == 0UL) {
557 return false;
558 }
559
Soby Mathewb4c6df42022-11-09 11:13:29 +0000560 return s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_UNASSIGNED);
561}
562
563/*
564 * Returns true if @s2tte has HIPAS=DESTROYED.
565 */
566bool s2tte_is_destroyed(unsigned long s2tte)
567{
568 return s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_DESTROYED);
569}
570
571/*
572 * Returns true if @s2tte has HIPAS=ASSIGNED.
573 */
574bool s2tte_is_assigned(unsigned long s2tte, long level)
575{
576 (void)level;
577
578 return s2tte_has_hipas(s2tte, S2TTE_INVALID_HIPAS_ASSIGNED);
579}
580
581static bool s2tte_check(unsigned long s2tte, long level, unsigned long ns)
582{
583 unsigned long desc_type;
584
585 if ((s2tte & S2TTE_NS) != ns) {
586 return false;
587 }
588
589 desc_type = s2tte & DESC_TYPE_MASK;
590
591 /* Only pages at L3 and valid blocks at L2 allowed */
592 if (((level == RTT_PAGE_LEVEL) && (desc_type == S2TTE_L3_PAGE)) ||
AlexeiFedorov80c2f042022-11-25 14:54:46 +0000593 ((level == RTT_MIN_BLOCK_LEVEL) && (desc_type == S2TTE_L012_BLOCK))) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000594 return true;
595 }
596
597 return false;
598}
599
600/*
601 * Returns true if @s2tte is a page or block s2tte, and NS=0.
602 */
603bool s2tte_is_valid(unsigned long s2tte, long level)
604{
605 return s2tte_check(s2tte, level, 0UL);
606}
607
608/*
609 * Returns true if @s2tte is a page or block s2tte, and NS=1.
610 */
611bool s2tte_is_valid_ns(unsigned long s2tte, long level)
612{
613 return s2tte_check(s2tte, level, S2TTE_NS);
614}
615
616/*
617 * Returns true if @s2tte is a table at level @level.
618 */
619bool s2tte_is_table(unsigned long s2tte, long level)
620{
621 unsigned long desc_type = s2tte & DESC_TYPE_MASK;
622
623 if ((level < RTT_PAGE_LEVEL) && (desc_type == S2TTE_TABLE)) {
624 return true;
625 }
626
627 return false;
628}
629
630/*
631 * Returns RIPAS of @s2tte.
632 *
633 * Caller should ensure that HIPAS=UNASSIGNED or HIPAS=ASSIGNED.
634 * The s2tte must be not valid/invalid descriptor.
635 */
636enum ripas s2tte_get_ripas(unsigned long s2tte)
637{
638 unsigned long desc_ripas = s2tte & S2TTE_INVALID_RIPAS_MASK;
639
640 /*
641 * If valid s2tte descriptor is passed, then ensure S2AP[0]
642 * bit is 1 (S2AP is set to RW for lower EL), which corresponds
643 * to RIPAS_RAM (bit[6]) on a valid descriptor.
644 */
645 if (((s2tte & DESC_TYPE_MASK) != S2TTE_Lx_INVALID) &&
646 (desc_ripas != S2TTE_INVALID_RIPAS_RAM)) {
647 assert(false);
648 }
649
650 if (desc_ripas == S2TTE_INVALID_RIPAS_EMPTY) {
Yousuf A62808152022-10-31 10:35:42 +0000651 return RIPAS_EMPTY;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000652 }
653
Yousuf A62808152022-10-31 10:35:42 +0000654 return RIPAS_RAM;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000655}
656
657/*
658 * Populates @s2tt with s2ttes which have HIPAS=UNASSIGNED and RIPAS=@ripas.
659 *
660 * The granule is populated before it is made a table,
661 * hence, don't use s2tte_write for access.
662 */
663void s2tt_init_unassigned(unsigned long *s2tt, enum ripas ripas)
664{
665 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
666 s2tt[i] = s2tte_create_unassigned(ripas);
667 }
668
669 dsb(ish);
670}
671
672/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100673 * Populates @s2tt with unassigned_ns s2ttes.
674 *
675 * The granule is populated before it is made a table,
676 * hence, don't use s2tte_write for access.
677 */
678void s2tt_init_unassigned_ns(unsigned long *s2tt)
679{
680 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
681 s2tt[i] = s2tte_create_unassigned_ns();
682 }
683
684 dsb(ish);
685}
686
687/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000688 * Populates @s2tt with s2ttes which have HIPAS=DESTROYED.
689 *
690 * The granule is populated before it is made a table,
691 * hence, don't use s2tte_write for access.
692 */
693void s2tt_init_destroyed(unsigned long *s2tt)
694{
695 for (unsigned int i = 0U; i < S2TTES_PER_S2TT; i++) {
696 s2tt[i] = s2tte_create_destroyed();
697 }
698
699 dsb(ish);
700}
701
702unsigned long s2tte_map_size(int level)
703{
704 int levels, lsb;
705
706 assert(level <= RTT_PAGE_LEVEL);
707
708 levels = RTT_PAGE_LEVEL - level;
709 lsb = levels * S2TTE_STRIDE + GRANULE_SHIFT;
710 return 1UL << lsb;
711}
712
713/*
714 * Populates @s2tt with HIPAS=ASSIGNED, RIPAS=EMPTY s2ttes that refer to a
715 * contiguous memory block starting at @pa, and mapped at level @level.
716 *
717 * The granule is populated before it is made a table,
718 * hence, don't use s2tte_write for access.
719 */
720void s2tt_init_assigned_empty(unsigned long *s2tt, unsigned long pa, long level)
721{
722 const unsigned long map_size = s2tte_map_size(level);
723 unsigned int i;
724
725 for (i = 0U; i < S2TTES_PER_S2TT; i++) {
726 s2tt[i] = s2tte_create_assigned_empty(pa, level);
727 pa += map_size;
728 }
729 dsb(ish);
730}
731
732/*
733 * Populates @s2tt with HIPAS=VALID, RIPAS=@ripas s2ttes that refer to a
734 * contiguous memory block starting at @pa, and mapped at level @level.
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_valid(unsigned long *s2tt, unsigned long pa, long level)
740{
741 const unsigned long map_size = s2tte_map_size(level);
742 unsigned int i;
743
744 for (i = 0U; i < S2TTES_PER_S2TT; i++) {
745 s2tt[i] = s2tte_create_valid(pa, level);
746 pa += map_size;
747 }
748 dsb(ish);
749}
750
751/*
752 * Populates @s2tt with HIPAS=VALID_NS, RIPAS=@ripas s2ttes that refer to a
753 * contiguous memory block starting at @pa, and mapped at level @level.
754 *
755 * The granule is populated before it is made a table,
756 * hence, don't use s2tte_write for access.
757 */
758void s2tt_init_valid_ns(unsigned long *s2tt, unsigned long pa, long level)
759{
760 const unsigned long map_size = s2tte_map_size(level);
761 unsigned int i;
762
763 for (i = 0U; i < S2TTES_PER_S2TT; i++) {
764 s2tt[i] = s2tte_create_valid_ns(pa, level);
765 pa += map_size;
766 }
767 dsb(ish);
768}
769
770/* Returns physical address of a page entry or block */
771unsigned long s2tte_pa(unsigned long s2tte, long level)
772{
773 if (s2tte_is_unassigned(s2tte) || s2tte_is_destroyed(s2tte) ||
774 s2tte_is_table(s2tte, level)) {
775 assert(false);
776 }
777 return addr_level_mask(s2tte, level);
778}
779
780/* Returns physical address of a table entry */
781unsigned long s2tte_pa_table(unsigned long s2tte, long level)
782{
783 assert(s2tte_is_table(s2tte, level));
784 return addr_level_mask(s2tte, RTT_PAGE_LEVEL);
785}
786
787bool addr_is_level_aligned(unsigned long addr, long level)
788{
789 return (addr == addr_level_mask(addr, level));
790}
791
792typedef bool (*s2tte_type_checker)(unsigned long s2tte);
793
794static bool __table_is_uniform_block(unsigned long *table,
795 s2tte_type_checker s2tte_is_x,
796 enum ripas *ripas_ptr)
797{
798 unsigned long s2tte = s2tte_read(&table[0]);
799 enum ripas ripas;
800 unsigned int i;
801
802 if (!s2tte_is_x(s2tte)) {
803 return false;
804 }
805
806 if (ripas_ptr != NULL) {
807 ripas = s2tte_get_ripas(s2tte);
808 }
809
810 for (i = 1U; i < S2TTES_PER_S2TT; i++) {
811 s2tte = s2tte_read(&table[i]);
812
813 if (!s2tte_is_x(s2tte)) {
814 return false;
815 }
816
817 if ((ripas_ptr != NULL) &&
818 (s2tte_get_ripas(s2tte) != ripas)) {
819 return false;
820 }
821 }
822
823 if (ripas_ptr != NULL) {
824 *ripas_ptr = ripas;
825 }
826
827 return true;
828}
829
830/*
831 * Returns true if all s2ttes in @table have HIPAS=UNASSIGNED and
832 * have the same RIPAS.
833 *
834 * If return value is true, the RIPAS value is returned in @ripas.
835 */
836bool table_is_unassigned_block(unsigned long *table, enum ripas *ripas)
837{
838 return __table_is_uniform_block(table, s2tte_is_unassigned, ripas);
839}
840
841/*
AlexeiFedorov5ceff352023-04-12 16:17:00 +0100842 * Returns true if all s2ttes in @table are unassigned_ns
843 */
844bool table_is_unassigned_ns_block(unsigned long *table)
845{
846 return __table_is_uniform_block(table, s2tte_is_unassigned_ns, NULL);
847}
848
849/*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000850 * Returns true if all s2ttes in @table have HIPAS=DESTROYED.
851 */
852bool table_is_destroyed_block(unsigned long *table)
853{
854 return __table_is_uniform_block(table, s2tte_is_destroyed, NULL);
855}
856
857typedef bool (*s2tte_type_level_checker)(unsigned long s2tte, long level);
858
859static bool __table_maps_block(unsigned long *table,
860 long level,
861 s2tte_type_level_checker s2tte_is_x)
862{
863 unsigned long base_pa;
864 unsigned long map_size = s2tte_map_size(level);
865 unsigned long s2tte = s2tte_read(&table[0]);
866 unsigned int i;
867
868 if (!s2tte_is_x(s2tte, level)) {
869 return false;
870 }
871
872 base_pa = s2tte_pa(s2tte, level);
873 if (!addr_is_level_aligned(base_pa, level - 1L)) {
874 return false;
875 }
876
877 for (i = 1U; i < S2TTES_PER_S2TT; i++) {
878 unsigned long expected_pa = base_pa + (i * map_size);
879
880 s2tte = s2tte_read(&table[i]);
881
882 if (!s2tte_is_x(s2tte, level)) {
883 return false;
884 }
885
886 if (s2tte_pa(s2tte, level) != expected_pa) {
887 return false;
888 }
889 }
890
891 return true;
892}
893
894/*
895 * Returns true if all s2ttes in @table have HIPAS=ASSIGNED
896 * and refer to a contiguous block of granules aligned to @level - 1.
897 */
898bool table_maps_assigned_block(unsigned long *table, long level)
899{
900 return __table_maps_block(table, level, s2tte_is_assigned);
901}
902
903/*
904 * Returns true if all s2ttes in @table have HIPAS=VALID and
905 * refer to a contiguous block of granules aligned to @level - 1.
906 */
907bool table_maps_valid_block(unsigned long *table, long level)
908{
909 return __table_maps_block(table, level, s2tte_is_valid);
910}
911
912/*
913 * Returns true if all s2ttes in @table have HIPAS=VALID_NS and
914 * refer to a contiguous block of granules aligned to @level - 1.
915 */
916bool table_maps_valid_ns_block(unsigned long *table, long level)
917{
918 return __table_maps_block(table, level, s2tte_is_valid_ns);
919}