From 127ccd1788084dcd9dc7ac2e7f16e88da54e233e Mon Sep 17 00:00:00 2001 From: johpow01 Date: Fri, 21 May 2021 11:29:40 -0500 Subject: [PATCH] feat(RME): BL31 changes The following is introduced in the patch 1. Enable GPT translation tables 2. Adds a new context for Realm world and adds realm world awareness in context management 3. Initializes CPU registers in context management for Realm world Signed-off-by: John Powell Change-Id: I5bc8f3413144fb63d9eb4f5885abdcf5a44b4db1 --- bl31/aarch64/bl31_entrypoint.S | 8 ++ bl31/aarch64/runtime_exceptions.S | 8 ++ bl31/bl31.mk | 7 ++ bl31/bl31_context_mgmt.c | 8 ++ include/lib/el3_runtime/aarch64/context.h | 9 +++ include/lib/el3_runtime/cpu_data.h | 30 +++++-- include/lib/smccc.h | 9 +++ lib/el3_runtime/aarch64/context_mgmt.c | 95 +++++++++++++++++++---- 8 files changed, 150 insertions(+), 24 deletions(-) diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S index 2d672dd12..21d5ee559 100644 --- a/bl31/aarch64/bl31_entrypoint.S +++ b/bl31/aarch64/bl31_entrypoint.S @@ -172,6 +172,14 @@ func bl31_warm_entrypoint _exception_vectors=runtime_exceptions \ _pie_fixup_size=0 +#if ENABLE_RME + /* + * Initialise and enable Granule Protection + * before enabling any stage of translation. + */ + bl gpt_enable +#endif + /* * We're about to enable MMU and participate in PSCI state coordination. * diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index 51eb2bd47..f85b64fc5 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -500,6 +500,14 @@ smc_handler64: stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] +#if ENABLE_RME + /* Copy SCR_EL3.NSE bit to the flag to indicate caller's security */ + ubfx x7, x18, #SCR_NSE_SHIFT, 1 + + /* Shift copied SCR_EL3.NSE bit by 1 to create space for SCR_EL3.NS bit */ + lsl x7, x7, #1 +#endif /* ENABLE_RME */ + /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */ bfi x7, x18, #0, #1 diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 2088533ac..41c6dbba5 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -95,6 +95,13 @@ BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \ lib/cpus/aarch64/wa_cve_2017_5715_mmu.S endif +ifeq (${ENABLE_RME},1) +include lib/gpt/gpt.mk + +BL31_SOURCES += ${GPT_LIB_SRCS} \ + ${RMMD_SOURCES} +endif + BL31_LINKERFILE := bl31/bl31.ld.S # Flag used to indicate if Crash reporting via console should be included diff --git a/bl31/bl31_context_mgmt.c b/bl31/bl31_context_mgmt.c index 9175ee35d..33442e4e3 100644 --- a/bl31/bl31_context_mgmt.c +++ b/bl31/bl31_context_mgmt.c @@ -19,7 +19,11 @@ ******************************************************************************/ void *cm_get_context(uint32_t security_state) { +#if ENABLE_RME + assert(sec_state_is_valid(security_state)); +#else /* ENABLE_RME */ assert(security_state <= NON_SECURE); +#endif return get_cpu_data(cpu_context[security_state]); } @@ -30,7 +34,11 @@ void *cm_get_context(uint32_t security_state) ******************************************************************************/ void cm_set_context(void *context, uint32_t security_state) { +#if ENABLE_RME + assert(sec_state_is_valid(security_state)); +#else /* ENABLE_RME */ assert(security_state <= NON_SECURE); +#endif set_cpu_data(cpu_context[security_state], context); } diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index 9d9f9d332..f0a51e39a 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -406,6 +406,15 @@ DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL); * to ensure that SP_EL3 always points to an instance of this * structure at exception entry and exit. Each instance will * correspond to either the secure or the non-secure state. + * + * For systems supporting RME: + * + * Top-level context structure which is used by EL3 firmware to preserve + * the state of a core at the next lower EL in a given security state and + * save enough EL3 meta data to be able to return to that EL and security + * state. The context management library will be used to ensure that + * SP_EL3 always points to an instance of this structure at exception + * entry and exit. */ typedef struct cpu_context { gp_regs_t gpregs_ctx; diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h index 54261358e..b67cdab3a 100644 --- a/include/lib/el3_runtime/cpu_data.h +++ b/include/lib/el3_runtime/cpu_data.h @@ -20,15 +20,27 @@ #define PSCI_CPU_DATA_SIZE_ALIGNED ((PSCI_CPU_DATA_SIZE + 7) & ~7) /* Offset of cpu_ops_ptr, size 8 bytes */ +#if ENABLE_RME +#define CPU_DATA_CPU_OPS_PTR 0x18 +#else /* ENABLE_RME */ #define CPU_DATA_CPU_OPS_PTR 0x10 +#endif /* ENABLE_RME */ #if ENABLE_PAUTH /* 8-bytes aligned offset of apiakey[2], size 16 bytes */ -#define CPU_DATA_APIAKEY_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED) -#define CPU_DATA_CRASH_BUF_OFFSET (CPU_DATA_APIAKEY_OFFSET + 0x10) -#else +#if ENABLE_RME +#define CPU_DATA_APIAKEY_OFFSET (0x20 + PSCI_CPU_DATA_SIZE_ALIGNED) +#else /* ENABLE_RME */ +#define CPU_DATA_APIAKEY_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED) +#endif /* ENABLE_RME */ +#define CPU_DATA_CRASH_BUF_OFFSET (0x10 + CPU_DATA_APIAKEY_OFFSET) +#else /* ENABLE_PAUTH */ +#if ENABLE_RME +#define CPU_DATA_CRASH_BUF_OFFSET (0x20 + PSCI_CPU_DATA_SIZE_ALIGNED) +#else /* ENABLE_RME */ #define CPU_DATA_CRASH_BUF_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED) -#endif /* ENABLE_PAUTH */ +#endif /* ENABLE_RME */ +#endif /* ENABLE_PAUTH */ /* need enough space in crash buffer to save 8 registers */ #define CPU_DATA_CRASH_BUF_SIZE 64 @@ -86,21 +98,23 @@ /******************************************************************************* * Cache of frequently used per-cpu data: - * Pointers to non-secure and secure security state contexts + * Pointers to non-secure, realm, and secure security state contexts * Address of the crash stack * It is aligned to the cache line boundary to allow efficient concurrent * manipulation of these pointers on different cpus * - * TODO: Add other commonly used variables to this (tf_issues#90) - * * The data structure and the _cpu_data accessors should not be used directly * by components that have per-cpu members. The member access macros should be * used for this. ******************************************************************************/ typedef struct cpu_data { #ifdef __aarch64__ +#if ENABLE_RME + void *cpu_context[3]; +#else /* ENABLE_RME */ void *cpu_context[2]; -#endif +#endif /* ENABLE_RME */ +#endif /* __aarch64__ */ uintptr_t cpu_ops_ptr; struct psci_cpu_data psci_svc_cpu_data; #if ENABLE_PAUTH diff --git a/include/lib/smccc.h b/include/lib/smccc.h index 470317dd0..ed5356fa1 100644 --- a/include/lib/smccc.h +++ b/include/lib/smccc.h @@ -94,6 +94,8 @@ /* Various flags passed to SMC handlers */ #define SMC_FROM_SECURE (U(0) << 0) #define SMC_FROM_NON_SECURE (U(1) << 0) +#define SMC_FROM_REALM (U(3) << 0) +#define SMC_FROM_MASK U(3) #ifndef __ASSEMBLER__ @@ -101,8 +103,15 @@ #include +#if ENABLE_RME +#define is_caller_non_secure(_f) (((_f) & SMC_FROM_MASK) == SMC_FROM_NON_SECURE) +#define is_caller_secure(_f) (((_f) & SMC_FROM_MASK) == SMC_FROM_SECURE) +#define is_caller_realm(_f) (((_f) & SMC_FROM_MASK) == SMC_FROM_REALM) +#define caller_sec_state(_f) ((_f) & SMC_FROM_MASK) +#else /* ENABLE_RME */ #define is_caller_non_secure(_f) (((_f) & SMC_FROM_NON_SECURE) != U(0)) #define is_caller_secure(_f) (!is_caller_non_secure(_f)) +#endif /* ENABLE_RME */ /* The macro below is used to identify a Standard Service SMC call */ #define is_std_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_STD_START) diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index e0e429849..b278d7f6e 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -23,9 +23,11 @@ #include #include #include +#if ENABLE_RME +#include +#endif #include - /******************************************************************************* * Context management library initialisation routine. This library is used by * runtime services to share pointers to 'cpu_context' structures for the secure @@ -70,6 +72,10 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) gp_regs_t *gp_regs; u_register_t sctlr_elx, actlr_elx; +#if ENABLE_RME + u_register_t hcr_el2; +#endif /* ENABLE_RME */ + assert(ctx != NULL); security_state = GET_SECURITY_STATE(ep->h.attr); @@ -89,24 +95,47 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) scr_el3 = read_scr(); scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT | SCR_ST_BIT | SCR_HCE_BIT); + +#if ENABLE_RME + /* When RME support is enabled, clear the NSE bit as well. */ + scr_el3 &= ~SCR_NSE_BIT; +#endif /* ENABLE_RME */ + /* * SCR_NS: Set the security state of the next EL. */ - if (security_state != SECURE) + if (security_state == NON_SECURE) { scr_el3 |= SCR_NS_BIT; + } + +#if ENABLE_RME + /* Check for realm state if RME support enabled. */ + if (security_state == REALM) { + scr_el3 |= SCR_NS_BIT | SCR_NSE_BIT; + + /* + * RMM relies on EL3 to setup HCR_EL2 for page table setup. + */ + hcr_el2 = HCR_TEA_BIT | HCR_E2H_BIT | HCR_TGE_BIT; + write_ctx_reg(get_el2_sysregs_ctx(ctx), CTX_HCR_EL2, hcr_el2); + } +#endif /* ENABLE_RME */ + /* * SCR_EL3.RW: Set the execution state, AArch32 or AArch64, for next * Exception level as specified by SPSR. */ - if (GET_RW(ep->spsr) == MODE_RW_64) + if (GET_RW(ep->spsr) == MODE_RW_64) { scr_el3 |= SCR_RW_BIT; + } /* * SCR_EL3.ST: Traps Secure EL1 accesses to the Counter-timer Physical * Secure timer registers to EL3, from AArch64 state only, if specified * by the entrypoint attributes. */ - if (EP_GET_ST(ep->h.attr) != 0U) + if (EP_GET_ST(ep->h.attr) != 0U) { scr_el3 |= SCR_ST_BIT; + } #if RAS_TRAP_LOWER_EL_ERR_ACCESS /* @@ -140,8 +169,9 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) * If the Secure world wants to use pointer authentication, * CTX_INCLUDE_PAUTH_REGS must be set to 1. */ - if (security_state == NON_SECURE) + if (security_state == NON_SECURE) { scr_el3 |= SCR_API_BIT | SCR_APK_BIT; + } #endif /* !CTX_INCLUDE_PAUTH_REGS */ #if !CTX_INCLUDE_MTE_REGS || ENABLE_ASSERTIONS @@ -178,7 +208,8 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) * indicated by the interrupt routing model for BL31. */ scr_el3 |= get_scr_el3_from_routing_model(security_state); -#endif + +#endif /* IMAGE_BL31 */ /* * SCR_EL3.HCE: Enable HVC instructions if next execution state is @@ -206,10 +237,18 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) } } +#if ENABLE_RME + /* + * RME model uses S-EL2 to emulate R-EL2 so EEL2 bit must be set when + * EL3 ERETs to R-EL2. + */ + if ((security_state != NON_SECURE) && (GET_EL(ep->spsr) == MODE_EL2)) { +#else /* Enable S-EL2 if the next EL is EL2 and security state is secure */ if ((security_state == SECURE) && (GET_EL(ep->spsr) == MODE_EL2)) { +#endif /* ENABLE_RME */ if (GET_RW(ep->spsr) != MODE_RW_64) { - ERROR("S-EL2 can not be used in AArch32."); + ERROR("S-EL2 cannot be used in AArch32."); panic(); } @@ -238,9 +277,9 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) * required by PSCI specification) */ sctlr_elx = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U; - if (GET_RW(ep->spsr) == MODE_RW_64) + if (GET_RW(ep->spsr) == MODE_RW_64) { sctlr_elx |= SCTLR_EL1_RES1; - else { + } else { /* * If the target execution state is AArch32 then the following * fields need to be set. @@ -370,7 +409,8 @@ void cm_init_my_context(const entry_point_info_t *ep) } /******************************************************************************* - * Prepare the CPU system registers for first entry into secure or normal world + * Prepare the CPU system registers for first entry into realm, secure, or + * normal world. * * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized * If execution is requested to non-secure EL1 or svc mode, and the CPU supports @@ -452,7 +492,7 @@ void cm_prepare_el3_exit(uint32_t security_state) * architecturally UNKNOWN on reset and are set to zero * except for field(s) listed below. * - * CNTHCTL_EL2.EL1PCEN: Set to one to disable traps to + * CNTHCTL_EL2.EL1PTEN: Set to one to disable traps to * Hyp mode of Non-secure EL0 and EL1 accesses to the * physical timer registers. * @@ -461,7 +501,8 @@ void cm_prepare_el3_exit(uint32_t security_state) * physical counter registers. */ write_cnthctl_el2(CNTHCTL_RESET_VAL | - EL1PCEN_BIT | EL1PCTEN_BIT); + CNTHCTL_EL1PTEN_BIT | + CNTHCTL_EL1PCTEN_BIT); /* * Initialise CNTVOFF_EL2 to zero as it resets to an @@ -598,6 +639,9 @@ void cm_el2_sysregs_context_save(uint32_t security_state) * S-EL2 context if S-EL2 is enabled. */ if ((security_state == NON_SECURE) || +#if ENABLE_RME + (security_state == REALM) || +#endif /* ENABLE_RME */ ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) { cpu_context_t *ctx; @@ -620,6 +664,9 @@ void cm_el2_sysregs_context_restore(uint32_t security_state) * S-EL2 context if S-EL2 is enabled. */ if ((security_state == NON_SECURE) || +#if ENABLE_RME + (security_state == REALM) || +#endif /* ENABLE_RME */ ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) { cpu_context_t *ctx; @@ -646,10 +693,18 @@ void cm_el1_sysregs_context_save(uint32_t security_state) el1_sysregs_context_save(get_el1_sysregs_ctx(ctx)); #if IMAGE_BL31 - if (security_state == SECURE) + if (security_state == SECURE) { PUBLISH_EVENT(cm_exited_secure_world); - else +#if ENABLE_RME + } else if (security_state == NON_SECURE) { PUBLISH_EVENT(cm_exited_normal_world); + } +#else /* ENABLE_RME */ + } else { + PUBLISH_EVENT(cm_exited_normal_world); + } +#endif /* ENABLE_RME */ + #endif } @@ -663,10 +718,18 @@ void cm_el1_sysregs_context_restore(uint32_t security_state) el1_sysregs_context_restore(get_el1_sysregs_ctx(ctx)); #if IMAGE_BL31 - if (security_state == SECURE) + if (security_state == SECURE) { PUBLISH_EVENT(cm_entering_secure_world); - else +#if ENABLE_RME + } else if (security_state == NON_SECURE) { PUBLISH_EVENT(cm_entering_normal_world); + } +#else /* ENABLE_RME */ + } else { + PUBLISH_EVENT(cm_entering_normal_world); + } +#endif /* ENABLE_RME */ + #endif } -- GitLab