Commit 127ccd17 authored by johpow01's avatar johpow01 Committed by Mark Dykes
Browse files

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: default avatarJohn Powell <john.powell@arm.com>
Change-Id: I5bc8f3413144fb63d9eb4f5885abdcf5a44b4db1
parent 65412d77
......@@ -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.
*
......
......@@ -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
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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
......
......@@ -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 <lib/cassert.h>
#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)
......
......@@ -23,9 +23,11 @@
#include <lib/extensions/spe.h>
#include <lib/extensions/sve.h>
#include <lib/extensions/twed.h>
#if ENABLE_RME
#include <lib/gpt/gpt.h>
#endif
#include <lib/utils.h>
/*******************************************************************************
* 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
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment