Add wrapper for AT instruction

In case of AT speculative workaround applied, page table walk
is disabled for lower ELs (EL1 and EL0) in EL3.
Hence added a wrapper function which temporarily enables page
table walk to execute AT instruction for lower ELs and then
disables page table walk.

Execute AT instructions directly for lower ELs (EL1 and EL0)
assuming page table walk is enabled always when AT speculative
workaround is not applied.

Change-Id: I4ad4c0bcbb761448af257e9f72ae979473c0dde8
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
This commit is contained in:
Manish V Badarkhe 2020-07-14 14:43:12 +01:00
parent 3b8456bd1c
commit 86ba585300
4 changed files with 26 additions and 6 deletions

View File

@ -70,7 +70,7 @@ static bool is_address_readable(uintptr_t addr)
} else if (el == 2U) {
ats1e2r(addr);
} else {
ats1e1r(addr);
AT(ats1e1r, addr);
}
isb();

View File

@ -590,4 +590,24 @@ static inline uint64_t el_implemented(unsigned int el)
#define read_clusterpwrdn() read_clusterpwrdn_el1()
#define write_clusterpwrdn(_v) write_clusterpwrdn_el1(_v)
#if ERRATA_SPECULATIVE_AT
/*
* Assuming SCTLR.M bit is already enabled
* 1. Enable page table walk by clearing TCR_EL1.EPDx bits
* 2. Execute AT instruction for lower EL1/0
* 3. Disable page table walk by setting TCR_EL1.EPDx bits
*/
#define AT(_at_inst, _va) \
{ \
assert((read_sctlr_el1() & SCTLR_M_BIT) != 0ULL); \
write_tcr_el1(read_tcr_el1() & ~(TCR_EPD0_BIT | TCR_EPD1_BIT)); \
isb(); \
_at_inst(_va); \
write_tcr_el1(read_tcr_el1() | (TCR_EPD0_BIT | TCR_EPD1_BIT)); \
isb(); \
}
#else
#define AT(_at_inst, _va) _at_inst(_va);
#endif
#endif /* ARCH_HELPERS_H */

View File

@ -216,7 +216,7 @@ int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode)
* Translate entry point to Physical Address using the EL1&0
* translation regime, including stage 2.
*/
ats12e1r(ep);
AT(ats12e1r, ep);
}
isb();
par = read_par_el1();

View File

@ -38,16 +38,16 @@ uint64_t tlkd_va_translate(uintptr_t va, int type)
int at = type & AT_MASK;
switch (at) {
case 0:
ats12e1r(va);
AT(ats12e1r, va);
break;
case 1:
ats12e1w(va);
AT(ats12e1w, va);
break;
case 2:
ats12e0r(va);
AT(ats12e0r, va);
break;
case 3:
ats12e0w(va);
AT(ats12e0w, va);
break;
default:
assert(0); /* Unreachable */