From ea735bf556f8768fd4c82a7b3c224b529aee057a Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 17 Nov 2022 16:42:09 +0000 Subject: [PATCH] refactor(cpufeat): enable FEAT_VHE for FEAT_STATE_CHECKED At the moment we only support FEAT_VHE to be either unconditionally compiled in, or to be not supported at all. Add support for runtime detection (ENABLE_FEAT_VHE=2), by splitting is_armv8_1_vhe_present() into an ID register reading function and a second function to report the support status. That function considers both build time settings and runtime information (if needed), and is used before we access VHE related registers. Also move the context saving code from assembly to C, and use the new is_feat_vhe_supported() function to guard its execution. Enable VHE in its runtime detection version for all FVP builds. Change-Id: Ib397cd0c83e8c709bd6fed603560e39901fa672b Signed-off-by: Andre Przywara --- common/feat_detect.c | 12 +--------- include/arch/aarch64/arch.h | 2 ++ include/arch/aarch64/arch_features.h | 18 ++++++++++++--- include/arch/aarch64/arch_helpers.h | 4 ++++ include/lib/el3_runtime/aarch64/context.h | 4 ---- lib/el3_runtime/aarch64/context.S | 28 ----------------------- lib/el3_runtime/aarch64/context_mgmt.c | 16 ++++++++----- plat/arm/board/fvp/platform.mk | 1 + services/std_svc/sdei/sdei_intr_mgmt.c | 2 +- 9 files changed, 34 insertions(+), 53 deletions(-) diff --git a/common/feat_detect.c b/common/feat_detect.c index a885107b8..abb6d718c 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -90,16 +90,6 @@ static void read_feat_pan(void) #endif } -/****************************************************** - * Feature : FEAT_VHE (Virtualization Host Extensions) - *****************************************************/ -static void read_feat_vhe(void) -{ -#if (ENABLE_FEAT_VHE == FEAT_STATE_ALWAYS) - feat_detect_panic(is_armv8_1_vhe_present(), "VHE"); -#endif -} - /******************************************************************************* * Feature : FEAT_RAS (Reliability, Availability, and Serviceability Extension) ******************************************************************************/ @@ -271,7 +261,7 @@ void detect_arch_features(void) /* v8.1 features */ read_feat_pan(); - read_feat_vhe(); + check_feature(ENABLE_FEAT_VHE, read_feat_vhe_id_field(), "VHE", 1, 1); /* v8.2 features */ read_feat_ras(); diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index cafc1e8bc..85546ec47 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -121,6 +121,8 @@ #define TRFCR_EL2 S3_4_C1_C2_1 #define PMSCR_EL2 S3_4_C9_C9_0 #define TFSR_EL2 S3_4_C5_C6_0 +#define CONTEXTIDR_EL2 S3_4_C13_C0_1 +#define TTBR1_EL2 S3_4_C2_C0_1 /******************************************************************************* * Generic timer memory mapped registers & offsets diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index 1bb6a8c2a..f1a13d290 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -27,10 +27,22 @@ static inline bool is_armv8_1_pan_present(void) ID_AA64MMFR1_EL1_PAN_MASK) != 0U; } -static inline bool is_armv8_1_vhe_present(void) +static inline unsigned int read_feat_vhe_id_field(void) { - return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_VHE_SHIFT) & - ID_AA64MMFR1_EL1_VHE_MASK) != 0U; + return ISOLATE_FIELD(read_id_aa64mmfr1_el1(), ID_AA64MMFR1_EL1_VHE); +} + +static inline bool is_feat_vhe_supported(void) +{ + if (ENABLE_FEAT_VHE == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_VHE == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_vhe_id_field() != 0U; } static inline bool is_armv8_2_ttcnp_present(void) diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index e45fb8944..6d115c7e5 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -540,6 +540,10 @@ DEFINE_RENAME_SYSREG_READ_FUNC(erxaddr_el1, ERXADDR_EL1) DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc0_el1, ERXMISC0_EL1) DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1) +/* Armv8.1 VHE Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(contextidr_el2, CONTEXTIDR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(ttbr1_el2, TTBR1_EL2) + /* Armv8.2 ID Registers */ DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index 838e74484..9b50f3319 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -521,10 +521,6 @@ void el2_sysregs_context_restore_mte(el2_sysregs_t *regs); void el2_sysregs_context_save_ecv(el2_sysregs_t *regs); void el2_sysregs_context_restore_ecv(el2_sysregs_t *regs); #endif /* ENABLE_FEAT_ECV */ -#if ENABLE_FEAT_VHE -void el2_sysregs_context_save_vhe(el2_sysregs_t *regs); -void el2_sysregs_context_restore_vhe(el2_sysregs_t *regs); -#endif /* ENABLE_FEAT_VHE */ #if RAS_EXTENSION void el2_sysregs_context_save_ras(el2_sysregs_t *regs); void el2_sysregs_context_restore_ras(el2_sysregs_t *regs); diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 7bb0f99a6..a5b64a5f2 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -21,10 +21,6 @@ .global el2_sysregs_context_save_ecv .global el2_sysregs_context_restore_ecv #endif /* ENABLE_FEAT_ECV */ -#if ENABLE_FEAT_VHE - .global el2_sysregs_context_save_vhe - .global el2_sysregs_context_restore_vhe -#endif /* ENABLE_FEAT_VHE */ #if RAS_EXTENSION .global el2_sysregs_context_save_ras .global el2_sysregs_context_restore_ras @@ -240,30 +236,6 @@ func el2_sysregs_context_restore_ecv endfunc el2_sysregs_context_restore_ecv #endif /* ENABLE_FEAT_ECV */ -#if ENABLE_FEAT_VHE -func el2_sysregs_context_save_vhe - /* - * CONTEXTIDR_EL2 register is saved only when FEAT_VHE or - * FEAT_Debugv8p2 (currently not in TF-A) is supported. - */ - mrs x9, contextidr_el2 - mrs x10, ttbr1_el2 - stp x9, x10, [x0, #CTX_CONTEXTIDR_EL2] - ret -endfunc el2_sysregs_context_save_vhe - -func el2_sysregs_context_restore_vhe - /* - * CONTEXTIDR_EL2 register is restored only when FEAT_VHE or - * FEAT_Debugv8p2 (currently not in TF-A) is supported. - */ - ldp x9, x10, [x0, #CTX_CONTEXTIDR_EL2] - msr contextidr_el2, x9 - msr ttbr1_el2, x10 - ret -endfunc el2_sysregs_context_restore_vhe -#endif /* ENABLE_FEAT_VHE */ - #if RAS_EXTENSION func el2_sysregs_context_save_ras /* diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index eb5d1dbf2..20eb5f67d 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -960,9 +960,12 @@ void cm_el2_sysregs_context_save(uint32_t security_state) #if ENABLE_FEAT_ECV el2_sysregs_context_save_ecv(el2_sysregs_ctx); #endif -#if ENABLE_FEAT_VHE - el2_sysregs_context_save_vhe(el2_sysregs_ctx); -#endif + if (is_feat_vhe_supported()) { + write_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2, + read_contextidr_el2()); + write_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2, + read_ttbr1_el2()); + } #if RAS_EXTENSION el2_sysregs_context_save_ras(el2_sysregs_ctx); #endif @@ -1020,9 +1023,10 @@ void cm_el2_sysregs_context_restore(uint32_t security_state) #if ENABLE_FEAT_ECV el2_sysregs_context_restore_ecv(el2_sysregs_ctx); #endif -#if ENABLE_FEAT_VHE - el2_sysregs_context_restore_vhe(el2_sysregs_ctx); -#endif + if (is_feat_vhe_supported()) { + write_contextidr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2)); + write_ttbr1_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2)); + } #if RAS_EXTENSION el2_sysregs_context_restore_ras(el2_sysregs_ctx); #endif diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 2e7ff480b..435a35e3d 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -469,6 +469,7 @@ ENABLE_FEAT_FGT := 2 ENABLE_FEAT_HCX := 2 ENABLE_FEAT_TCR2 := 2 +ENABLE_FEAT_VHE := 2 ENABLE_MPAM_FOR_LOWER_ELS := 2 ifeq (${SPMC_AT_EL3}, 1) diff --git a/services/std_svc/sdei/sdei_intr_mgmt.c b/services/std_svc/sdei/sdei_intr_mgmt.c index 87a1fb7dc..9862e4f8d 100644 --- a/services/std_svc/sdei/sdei_intr_mgmt.c +++ b/services/std_svc/sdei/sdei_intr_mgmt.c @@ -270,7 +270,7 @@ static void sdei_set_elr_spsr(sdei_entry_t *se, sdei_dispatch_context_t *disp_ct * HCR_EL2.E2H = 1 and HCR_EL2.TGE = 1 */ u_register_t hcr_el2 = read_hcr(); - bool el_is_in_host = is_armv8_1_vhe_present() && + bool el_is_in_host = (read_feat_vhe_id_field() != 0U) && (hcr_el2 & HCR_TGE_BIT) && (hcr_el2 & HCR_E2H_BIT);