diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index 16d12a3830ef2b6e4753f6a52e9c8a1ab84299bf..cb7dab7ff32a8b0a207056e4608df089302a18eb 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -598,4 +598,10 @@ #define MAKE_MAIR_NORMAL_MEMORY(inner, outer) ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) +/* PAR_EL1 fields */ +#define PAR_F_SHIFT 0 +#define PAR_F_MASK 1 +#define PAR_ADDR_SHIFT 12 +#define PAR_ADDR_MASK (BIT(40) - 1) /* 40-bits-wide page address */ + #endif /* __ARCH_H__ */ diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 9c022ab5e64fa56ee9ddf29243730591afac382f..782343d67ff73cc3cecf94fe1b2e49dbb75bf37c 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -155,6 +155,7 @@ DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1r) DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1w) DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0r) DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0w) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e2r) void flush_dcache_range(uintptr_t addr, size_t size); void clean_dcache_range(uintptr_t addr, size_t size); diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 1905c0b05efc88ea18b4d31d1ee1bb17ed104cc9..bf6397377c5f3ac7d086e61e9e024e58fe1829e9 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -204,3 +204,51 @@ unsigned int plat_get_syscnt_freq2(void) } #endif /* ARM_SYS_CNTCTL_BASE */ + +#if SDEI_SUPPORT +/* + * Translate SDEI entry point to PA, and perform standard ARM entry point + * validation on it. + */ +int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) +{ + uint64_t par, pa; + uint32_t scr_el3; + + /* Doing Non-secure address translation requires SCR_EL3.NS set */ + scr_el3 = read_scr_el3(); + write_scr_el3(scr_el3 | SCR_NS_BIT); + isb(); + + assert((client_mode == MODE_EL2) || (client_mode == MODE_EL1)); + if (client_mode == MODE_EL2) { + /* + * Translate entry point to Physical Address using the EL2 + * translation regime. + */ + ats1e2r(ep); + } else { + /* + * Translate entry point to Physical Address using the EL1&0 + * translation regime, including stage 2. + */ + ats12e1r(ep); + } + isb(); + par = read_par_el1(); + + /* Restore original SCRL_EL3 */ + write_scr_el3(scr_el3); + isb(); + + /* If the translation resulted in fault, return failure */ + if ((par & PAR_F_MASK) != 0) + return -1; + + /* Extract Physical Address from PAR */ + pa = (par & (PAR_ADDR_MASK << PAR_ADDR_SHIFT)); + + /* Perform NS entry point validation on the physical address */ + return arm_validate_ns_entrypoint(pa); +} +#endif