mirror of
https://github.com/CTCaer/switch-l4t-atf.git
synced 2024-12-02 23:56:35 +00:00
Refactor Statistical Profiling Extensions implementation
Factor out SPE operations in a separate file. Use the publish subscribe framework to drain the SPE buffers before entering secure world. Additionally, enable SPE before entering normal world. A side effect of this change is that the profiling buffers are now only drained when a transition from normal world to secure world happens. Previously they were drained also on return from secure world, which is unnecessary as SPE is not supported in S-EL1. Change-Id: I17582c689b4b525770dbb6db098b3a0b5777b70a Signed-off-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
This commit is contained in:
parent
c776deed60
commit
281a08cc64
1
Makefile
1
Makefile
@ -189,6 +189,7 @@ INCLUDES += -Iinclude/bl1 \
|
||||
-Iinclude/lib/cpus/${ARCH} \
|
||||
-Iinclude/lib/el3_runtime \
|
||||
-Iinclude/lib/el3_runtime/${ARCH} \
|
||||
-Iinclude/lib/extensions \
|
||||
-Iinclude/lib/pmf \
|
||||
-Iinclude/lib/psci \
|
||||
-Iinclude/lib/xlat_tables \
|
||||
|
@ -46,6 +46,10 @@ BL31_SOURCES += services/std_svc/sdei/sdei_event.c \
|
||||
services/std_svc/sdei/sdei_state.c
|
||||
endif
|
||||
|
||||
ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1)
|
||||
BL31_SOURCES += lib/extensions/spe/spe.c
|
||||
endif
|
||||
|
||||
BL31_LINKERFILE := bl31/bl31.ld.S
|
||||
|
||||
# Flag used to indicate if Crash reporting via console should be included
|
||||
|
@ -95,10 +95,6 @@
|
||||
* MDCR_EL3.SPD32: Set to 0b10 to disable AArch32 Secure self-hosted
|
||||
* privileged debug from S-EL1.
|
||||
*
|
||||
* MDCR_EL3.NSPB (ARM v8.2): SPE enabled in non-secure state and
|
||||
* disabled in secure state. Accesses to SPE registers at SEL1 generate
|
||||
* trap exceptions to EL3.
|
||||
*
|
||||
* MDCR_EL3.TDOSA: Set to zero so that EL2 and EL2 System register
|
||||
* access to the powerdown debug registers do not trap to EL3.
|
||||
*
|
||||
@ -112,19 +108,6 @@
|
||||
*/
|
||||
mov_imm x0, ((MDCR_EL3_RESET_VAL | MDCR_SDD_BIT | MDCR_SPD32(MDCR_SPD32_DISABLE)) \
|
||||
& ~(MDCR_TDOSA_BIT | MDCR_TDA_BIT | MDCR_TPM_BIT))
|
||||
|
||||
#if ENABLE_SPE_FOR_LOWER_ELS
|
||||
/* Detect if SPE is implemented */
|
||||
mrs x1, id_aa64dfr0_el1
|
||||
ubfx x1, x1, #ID_AA64DFR0_PMS_SHIFT, #ID_AA64DFR0_PMS_LENGTH
|
||||
cmp x1, #0x1
|
||||
b.ne 1f
|
||||
|
||||
/* Enable SPE for use by normal world */
|
||||
orr x0, x0, #MDCR_NSPB(MDCR_NSPB_EL1)
|
||||
1:
|
||||
#endif
|
||||
|
||||
msr mdcr_el3, x0
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
@ -604,4 +604,9 @@
|
||||
#define PAR_ADDR_SHIFT 12
|
||||
#define PAR_ADDR_MASK (BIT(40) - 1) /* 40-bits-wide page address */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions for system register interface to SPE
|
||||
******************************************************************************/
|
||||
#define PMBLIMITR_EL1 S3_0_C9_C10_0
|
||||
|
||||
#endif /* __ARCH_H__ */
|
||||
|
@ -197,6 +197,7 @@ DEFINE_SYSOP_TYPE_FUNC(dmb, sy)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dmb, st)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dsb, nsh)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dmb, ishst)
|
||||
@ -301,6 +302,7 @@ DEFINE_SYSREG_READ_FUNC(isr_el1)
|
||||
DEFINE_SYSREG_READ_FUNC(ctr_el0)
|
||||
|
||||
DEFINE_SYSREG_RW_FUNCS(mdcr_el2)
|
||||
DEFINE_SYSREG_RW_FUNCS(mdcr_el3)
|
||||
DEFINE_SYSREG_RW_FUNCS(hstr_el2)
|
||||
DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2)
|
||||
DEFINE_SYSREG_RW_FUNCS(pmcr_el0)
|
||||
@ -320,6 +322,7 @@ DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1)
|
||||
DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1)
|
||||
DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1)
|
||||
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
|
||||
|
||||
#define IS_IN_EL(x) \
|
||||
(GET_EL(read_CurrentEl()) == MODE_EL##x)
|
||||
|
@ -313,7 +313,6 @@ CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx),
|
||||
* Function prototypes
|
||||
******************************************************************************/
|
||||
void el1_sysregs_context_save(el1_sys_regs_t *regs);
|
||||
void el1_sysregs_context_save_post_ops(void);
|
||||
void el1_sysregs_context_restore(el1_sys_regs_t *regs);
|
||||
#if CTX_INCLUDE_FPREGS
|
||||
void fpregs_context_save(fp_regs_t *regs);
|
||||
|
13
include/lib/extensions/spe.h
Normal file
13
include/lib/extensions/spe.h
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __SPE_H__
|
||||
#define __SPE_H__
|
||||
|
||||
void spe_enable(int el2_unused);
|
||||
void spe_disable(void);
|
||||
|
||||
#endif /* __SPE_H__ */
|
@ -227,7 +227,4 @@ int arm_execution_state_switch(unsigned int smc_fid,
|
||||
uint32_t cookie_lo,
|
||||
void *handle);
|
||||
|
||||
/* Disable Statistical Profiling Extensions helper */
|
||||
void arm_disable_spe(void);
|
||||
|
||||
#endif /* __PLAT_ARM_H__ */
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <context.h>
|
||||
|
||||
.global el1_sysregs_context_save
|
||||
.global el1_sysregs_context_save_post_ops
|
||||
.global el1_sysregs_context_restore
|
||||
#if CTX_INCLUDE_FPREGS
|
||||
.global fpregs_context_save
|
||||
@ -109,36 +108,6 @@ func el1_sysregs_context_save
|
||||
ret
|
||||
endfunc el1_sysregs_context_save
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* The following function strictly follows the AArch64
|
||||
* PCS to use x9-x17 (temporary caller-saved registers)
|
||||
* to do post operations after saving the EL1 system
|
||||
* register context.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func el1_sysregs_context_save_post_ops
|
||||
#if ENABLE_SPE_FOR_LOWER_ELS
|
||||
/* Detect if SPE is implemented */
|
||||
mrs x9, id_aa64dfr0_el1
|
||||
ubfx x9, x9, #ID_AA64DFR0_PMS_SHIFT, #ID_AA64DFR0_PMS_LENGTH
|
||||
cmp x9, #0x1
|
||||
b.ne 1f
|
||||
|
||||
/*
|
||||
* Before switching from normal world to secure world
|
||||
* the profiling buffers need to be drained out to memory. This is
|
||||
* required to avoid an invalid memory access when TTBR is switched
|
||||
* for entry to SEL1.
|
||||
*/
|
||||
.arch armv8.2-a+profile
|
||||
psb csync
|
||||
dsb nsh
|
||||
.arch armv8-a
|
||||
1:
|
||||
#endif
|
||||
ret
|
||||
endfunc el1_sysregs_context_save_post_ops
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* The following function strictly follows the AArch64
|
||||
* PCS to use x9-x17 (temporary caller-saved registers)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <platform_def.h>
|
||||
#include <pubsub_events.h>
|
||||
#include <smcc_helpers.h>
|
||||
#include <spe.h>
|
||||
#include <string.h>
|
||||
#include <utils.h>
|
||||
|
||||
@ -216,6 +217,9 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t
|
||||
static void enable_extensions_nonsecure(int el2_unused)
|
||||
{
|
||||
#if IMAGE_BL31
|
||||
#if ENABLE_SPE_FOR_LOWER_ELS
|
||||
spe_enable(el2_unused);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -354,13 +358,6 @@ void cm_prepare_el3_exit(uint32_t security_state)
|
||||
* relying on hw. Some fields are architecturally
|
||||
* UNKNOWN on reset.
|
||||
*
|
||||
* MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
|
||||
* profiling controls to EL2.
|
||||
*
|
||||
* MDCR_EL2.E2PB (ARM v8.2): SPE enabled in non-secure
|
||||
* state. Accesses to profiling buffer controls at
|
||||
* non-secure EL1 are not trapped to EL2.
|
||||
*
|
||||
* MDCR_EL2.TDRA: Set to zero so that Non-secure EL0 and
|
||||
* EL1 System register accesses to the Debug ROM
|
||||
* registers are not trapped to EL2.
|
||||
@ -397,22 +394,6 @@ void cm_prepare_el3_exit(uint32_t security_state)
|
||||
| MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT
|
||||
| MDCR_EL2_TPMCR_BIT));
|
||||
|
||||
#if ENABLE_SPE_FOR_LOWER_ELS
|
||||
uint64_t id_aa64dfr0_el1;
|
||||
|
||||
/* Detect if SPE is implemented */
|
||||
id_aa64dfr0_el1 = read_id_aa64dfr0_el1() >>
|
||||
ID_AA64DFR0_PMS_SHIFT;
|
||||
if ((id_aa64dfr0_el1 & ID_AA64DFR0_PMS_MASK) == 1) {
|
||||
/*
|
||||
* Make sure traps to EL2 are not generated if
|
||||
* EL2 is implemented but not used.
|
||||
*/
|
||||
mdcr_el2 &= ~MDCR_EL2_TPMS;
|
||||
mdcr_el2 |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
|
||||
}
|
||||
#endif
|
||||
|
||||
write_mdcr_el2(mdcr_el2);
|
||||
|
||||
/*
|
||||
@ -454,7 +435,6 @@ void cm_el1_sysregs_context_save(uint32_t security_state)
|
||||
assert(ctx);
|
||||
|
||||
el1_sysregs_context_save(get_sysregs_ctx(ctx));
|
||||
el1_sysregs_context_save_post_ops();
|
||||
|
||||
#if IMAGE_BL31
|
||||
if (security_state == SECURE)
|
||||
|
85
lib/extensions/spe/spe.c
Normal file
85
lib/extensions/spe/spe.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <pubsub.h>
|
||||
|
||||
/*
|
||||
* The assembler does not yet understand the psb csync mnemonic
|
||||
* so use the equivalent hint instruction.
|
||||
*/
|
||||
#define psb_csync() asm volatile("hint #17")
|
||||
|
||||
void spe_enable(int el2_unused)
|
||||
{
|
||||
uint64_t features;
|
||||
|
||||
features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
|
||||
if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
|
||||
uint64_t v;
|
||||
|
||||
if (el2_unused) {
|
||||
/*
|
||||
* MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
|
||||
* profiling controls to EL2.
|
||||
*
|
||||
* MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
|
||||
* state. Accesses to profiling buffer controls at
|
||||
* Non-secure EL1 are not trapped to EL2.
|
||||
*/
|
||||
v = read_mdcr_el2();
|
||||
v &= ~MDCR_EL2_TPMS;
|
||||
v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
|
||||
write_mdcr_el2(v);
|
||||
}
|
||||
|
||||
/*
|
||||
* MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state
|
||||
* and disabled in secure state. Accesses to SPE registers at
|
||||
* S-EL1 generate trap exceptions to EL3.
|
||||
*/
|
||||
v = read_mdcr_el3();
|
||||
v |= MDCR_NSPB(MDCR_NSPB_EL1);
|
||||
write_mdcr_el3(v);
|
||||
}
|
||||
}
|
||||
|
||||
void spe_disable(void)
|
||||
{
|
||||
uint64_t features;
|
||||
|
||||
features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
|
||||
if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
|
||||
uint64_t v;
|
||||
|
||||
/* Drain buffered data */
|
||||
psb_csync();
|
||||
dsbnsh();
|
||||
|
||||
/* Disable profiling buffer */
|
||||
v = read_pmblimitr_el1();
|
||||
v &= ~(1ULL << 0);
|
||||
write_pmblimitr_el1(v);
|
||||
isb();
|
||||
}
|
||||
}
|
||||
|
||||
static void *spe_drain_buffers_hook(const void *arg)
|
||||
{
|
||||
uint64_t features;
|
||||
|
||||
features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
|
||||
if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
|
||||
/* Drain buffered data */
|
||||
psb_csync();
|
||||
dsbnsh();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);
|
@ -14,6 +14,7 @@
|
||||
#include <plat_arm.h>
|
||||
#include <platform.h>
|
||||
#include <psci.h>
|
||||
#include <spe.h>
|
||||
#include <v2m_def.h>
|
||||
#include "drivers/pwrc/fvp_pwrc.h"
|
||||
#include "fvp_def.h"
|
||||
@ -57,7 +58,7 @@ static void fvp_cluster_pwrdwn_common(void)
|
||||
* On power down we need to disable statistical profiling extensions
|
||||
* before exiting coherency.
|
||||
*/
|
||||
arm_disable_spe();
|
||||
spe_disable();
|
||||
#endif
|
||||
|
||||
/* Disable coherency if this cluster is to be turned off */
|
||||
|
@ -12,7 +12,6 @@
|
||||
.globl plat_crash_console_putc
|
||||
.globl plat_crash_console_flush
|
||||
.globl platform_mem_init
|
||||
.globl arm_disable_spe
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
@ -88,34 +87,6 @@ func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void arm_disable_spe (void);
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
#if ENABLE_SPE_FOR_LOWER_ELS
|
||||
func arm_disable_spe
|
||||
/* Detect if SPE is implemented */
|
||||
mrs x0, id_aa64dfr0_el1
|
||||
ubfx x0, x0, #ID_AA64DFR0_PMS_SHIFT, #ID_AA64DFR0_PMS_LENGTH
|
||||
cmp x0, #0x1
|
||||
b.ne 1f
|
||||
|
||||
/* Drain buffered data */
|
||||
.arch armv8.2-a+profile
|
||||
psb csync
|
||||
dsb nsh
|
||||
|
||||
/* Disable Profiling Buffer */
|
||||
mrs x0, pmblimitr_el1
|
||||
bic x0, x0, #1
|
||||
msr pmblimitr_el1, x0
|
||||
isb
|
||||
.arch armv8-a
|
||||
1:
|
||||
ret
|
||||
endfunc arm_disable_spe
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Need to use coherent stack when ARM Cryptocell is used to autheticate images
|
||||
* since Cryptocell uses DMA to transfer data and it is not coherent with the
|
||||
|
Loading…
Reference in New Issue
Block a user