From b4ae615bd734104cfed5d2534b4c14278415057e Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Mon, 25 Sep 2017 15:23:22 +0100 Subject: [PATCH] xlat: Introduce function xlat_arch_tlbi_va_regime() Introduce a variant of the TLB invalidation helper function that allows the targeted translation regime to be specified, rather than defaulting to the current one. This new function is useful in the context of EL3 software managing translation tables for the S-EL1&0 translation regime, as then it might need to invalidate S-EL1&0 TLB entries rather than EL3 ones. Define a new enumeration to be able to represent translation regimes in the xlat tables library. Change-Id: Ibe4438dbea2d7a6e7470bfb68ff805d8bf6b07e5 Co-authored-by: Sandrine Bailleux Co-authored-by: Douglas Raillard Co-authored-by: Antonio Nino Diaz Signed-off-by: Antonio Nino Diaz --- include/lib/xlat_tables/xlat_tables_v2.h | 8 +++++ lib/xlat_tables_v2/aarch32/xlat_tables_arch.c | 11 +++++++ lib/xlat_tables_v2/aarch64/xlat_tables_arch.c | 33 +++++++++++++++---- lib/xlat_tables_v2/xlat_tables_private.h | 16 +++++++-- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h index a4f0efd3..2cc59f6d 100644 --- a/include/lib/xlat_tables/xlat_tables_v2.h +++ b/include/lib/xlat_tables/xlat_tables_v2.h @@ -106,6 +106,14 @@ typedef struct mmap_region { size_t granularity; } mmap_region_t; +/* + * Translation regimes supported by this library. + */ +typedef enum xlat_regime { + EL1_EL0_REGIME, + EL3_REGIME, +} xlat_regime_t; + /* * Declare the translation context type. * Its definition is private. diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c index e66b9275..30ad91e1 100644 --- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c @@ -40,6 +40,17 @@ void xlat_arch_tlbi_va(uintptr_t va) tlbimvaais(TLBI_ADDR(va)); } +void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime __unused) +{ + /* + * Ensure the translation table write has drained into memory before + * invalidating the TLB entry. + */ + dsbishst(); + + tlbimvaais(TLBI_ADDR(va)); +} + void xlat_arch_tlbi_va_sync(void) { /* Invalidate all entries from branch predictors. */ diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c index 81e035be..06bd4978 100644 --- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c @@ -82,6 +82,17 @@ int is_mmu_enabled(void) } void xlat_arch_tlbi_va(uintptr_t va) +{ +#if IMAGE_EL == 1 + assert(IS_IN_EL(1)); + xlat_arch_tlbi_va_regime(va, EL1_EL0_REGIME); +#elif IMAGE_EL == 3 + assert(IS_IN_EL(3)); + xlat_arch_tlbi_va_regime(va, EL3_REGIME); +#endif +} + +void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime) { /* * Ensure the translation table write has drained into memory before @@ -89,13 +100,21 @@ void xlat_arch_tlbi_va(uintptr_t va) */ dsbishst(); -#if IMAGE_EL == 1 - assert(IS_IN_EL(1)); - tlbivaae1is(TLBI_ADDR(va)); -#elif IMAGE_EL == 3 - assert(IS_IN_EL(3)); - tlbivae3is(TLBI_ADDR(va)); -#endif + /* + * This function only supports invalidation of TLB entries for the EL3 + * and EL1&0 translation regimes. + * + * Also, it is architecturally UNDEFINED to invalidate TLBs of a higher + * exception level (see section D4.9.2 of the ARM ARM rev B.a). + */ + if (xlat_regime == EL1_EL0_REGIME) { + assert(xlat_arch_current_el() >= 1); + tlbivaae1is(TLBI_ADDR(va)); + } else { + assert(xlat_regime == EL3_REGIME); + assert(xlat_arch_current_el() >= 3); + tlbivae3is(TLBI_ADDR(va)); + } } void xlat_arch_tlbi_va_sync(void) diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h index fbd9578a..2730ab6c 100644 --- a/lib/xlat_tables_v2/xlat_tables_private.h +++ b/lib/xlat_tables_v2/xlat_tables_private.h @@ -37,11 +37,21 @@ typedef enum { #endif /* PLAT_XLAT_TABLES_DYNAMIC */ /* - * Function used to invalidate all levels of the translation walk for a given - * virtual address. It must be called for every translation table entry that is - * modified. + * Invalidate all TLB entries that match the given virtual address. This + * operation applies to all PEs in the same Inner Shareable domain as the PE + * that executes this function. This functions must be called for every + * translation table entry that is modified. + * + * xlat_arch_tlbi_va() applies the invalidation to the exception level of the + * current translation regime, whereas xlat_arch_tlbi_va_regime() applies it to + * the given translation regime. + * + * Note, however, that it is architecturally UNDEFINED to invalidate TLB entries + * pertaining to a higher exception level, e.g. invalidating EL3 entries from + * S-EL1. */ void xlat_arch_tlbi_va(uintptr_t va); +void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime); /* * This function has to be called at the end of any code that uses the function -- 2.30.2