GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,268 @@
/*
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ARCH_FEATURES_H
#define ARCH_FEATURES_H
#include <stdbool.h>
#include <arch_helpers.h>
static inline bool is_armv7_gentimer_present(void)
{
/* The Generic Timer is always present in an ARMv8-A implementation */
return true;
}
static inline bool is_armv8_1_pan_present(void)
{
return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) &
ID_AA64MMFR1_EL1_PAN_MASK) != 0U;
}
static inline bool is_armv8_1_vhe_present(void)
{
return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_VHE_SHIFT) &
ID_AA64MMFR1_EL1_VHE_MASK) != 0U;
}
static inline bool is_armv8_2_ttcnp_present(void)
{
return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_CNP_SHIFT) &
ID_AA64MMFR2_EL1_CNP_MASK) != 0U;
}
static inline bool is_feat_pacqarma3_present(void)
{
uint64_t mask_id_aa64isar2 =
(ID_AA64ISAR2_GPA3_MASK << ID_AA64ISAR2_GPA3_SHIFT) |
(ID_AA64ISAR2_APA3_MASK << ID_AA64ISAR2_APA3_SHIFT);
/* If any of the fields is not zero, QARMA3 algorithm is present */
return (read_id_aa64isar2_el1() & mask_id_aa64isar2) != 0U;
}
static inline bool is_armv8_3_pauth_present(void)
{
uint64_t mask_id_aa64isar1 =
(ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) |
(ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) |
(ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) |
(ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT);
/*
* If any of the fields is not zero or QARMA3 is present,
* PAuth is present
*/
return ((read_id_aa64isar1_el1() & mask_id_aa64isar1) != 0U ||
is_feat_pacqarma3_present());
}
static inline bool is_armv8_4_dit_present(void)
{
return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) &
ID_AA64PFR0_DIT_MASK) == 1U;
}
static inline bool is_armv8_4_ttst_present(void)
{
return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) &
ID_AA64MMFR2_EL1_ST_MASK) == 1U;
}
static inline bool is_armv8_5_bti_present(void)
{
return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_BT_SHIFT) &
ID_AA64PFR1_EL1_BT_MASK) == BTI_IMPLEMENTED;
}
static inline unsigned int get_armv8_5_mte_support(void)
{
return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) &
ID_AA64PFR1_EL1_MTE_MASK);
}
static inline bool is_armv8_4_sel2_present(void)
{
return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SEL2_SHIFT) &
ID_AA64PFR0_SEL2_MASK) == 1ULL;
}
static inline bool is_armv8_6_twed_present(void)
{
return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_TWED_SHIFT) &
ID_AA64MMFR1_EL1_TWED_MASK) == ID_AA64MMFR1_EL1_TWED_SUPPORTED);
}
static inline bool is_armv8_6_fgt_present(void)
{
return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_FGT_SHIFT) &
ID_AA64MMFR0_EL1_FGT_MASK) != 0U;
}
static inline unsigned long int get_armv8_6_ecv_support(void)
{
return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_ECV_SHIFT) &
ID_AA64MMFR0_EL1_ECV_MASK);
}
static inline bool is_armv8_5_rng_present(void)
{
return ((read_id_aa64isar0_el1() >> ID_AA64ISAR0_RNDR_SHIFT) &
ID_AA64ISAR0_RNDR_MASK);
}
static inline bool is_armv8_6_feat_amuv1p1_present(void)
{
return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
ID_AA64PFR0_AMU_MASK) >= ID_AA64PFR0_AMU_V1P1);
}
/*
* Return MPAM version:
*
* 0x00: None Armv8.0 or later
* 0x01: v0.1 Armv8.4 or later
* 0x10: v1.0 Armv8.2 or later
* 0x11: v1.1 Armv8.4 or later
*
*/
static inline unsigned int get_mpam_version(void)
{
return (unsigned int)((((read_id_aa64pfr0_el1() >>
ID_AA64PFR0_MPAM_SHIFT) & ID_AA64PFR0_MPAM_MASK) << 4) |
((read_id_aa64pfr1_el1() >>
ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK));
}
static inline bool is_feat_hcx_present(void)
{
return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_HCX_SHIFT) &
ID_AA64MMFR1_EL1_HCX_MASK) == ID_AA64MMFR1_EL1_HCX_SUPPORTED);
}
static inline bool is_feat_rng_trap_present(void)
{
return (((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT) &
ID_AA64PFR1_EL1_RNDR_TRAP_MASK)
== ID_AA64PFR1_EL1_RNG_TRAP_SUPPORTED);
}
static inline unsigned int get_armv9_2_feat_rme_support(void)
{
/*
* Return the RME version, zero if not supported. This function can be
* used as both an integer value for the RME version or compared to zero
* to detect RME presence.
*/
return (unsigned int)(read_id_aa64pfr0_el1() >>
ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK;
}
/*********************************************************************************
* Function to identify the presence of FEAT_SB (Speculation Barrier Instruction)
********************************************************************************/
static inline bool is_armv8_0_feat_sb_present(void)
{
return (((read_id_aa64isar1_el1() >> ID_AA64ISAR1_SB_SHIFT) &
ID_AA64ISAR1_SB_MASK) == ID_AA64ISAR1_SB_SUPPORTED);
}
/*********************************************************************************
* Function to identify the presence of FEAT_CSV2_2 (Cache Speculation Variant 2)
********************************************************************************/
static inline bool is_armv8_0_feat_csv2_2_present(void)
{
return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_CSV2_SHIFT) &
ID_AA64PFR0_CSV2_MASK) == ID_AA64PFR0_CSV2_2_SUPPORTED);
}
/**********************************************************************************
* Function to identify the presence of FEAT_SPE (Statistical Profiling Extension)
*********************************************************************************/
static inline bool is_armv8_2_feat_spe_present(void)
{
return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT) &
ID_AA64DFR0_PMS_MASK) != ID_AA64DFR0_SPE_NOT_SUPPORTED);
}
/*******************************************************************************
* Function to identify the presence of FEAT_SVE (Scalable Vector Extension)
******************************************************************************/
static inline bool is_armv8_2_feat_sve_present(void)
{
return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT) &
ID_AA64PFR0_SVE_MASK) == ID_AA64PFR0_SVE_SUPPORTED);
}
/*******************************************************************************
* Function to identify the presence of FEAT_RAS (Reliability,Availability,
* and Serviceability Extension)
******************************************************************************/
static inline bool is_armv8_2_feat_ras_present(void)
{
return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_RAS_SHIFT) &
ID_AA64PFR0_RAS_MASK) != ID_AA64PFR0_RAS_NOT_SUPPORTED);
}
/**************************************************************************
* Function to identify the presence of FEAT_DIT (Data Independent Timing)
*************************************************************************/
static inline bool is_armv8_4_feat_dit_present(void)
{
return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) &
ID_AA64PFR0_DIT_MASK) == ID_AA64PFR0_DIT_SUPPORTED);
}
/*************************************************************************
* Function to identify the presence of FEAT_TRF (TraceLift)
************************************************************************/
static inline bool is_arm8_4_feat_trf_present(void)
{
return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT) &
ID_AA64DFR0_TRACEFILT_MASK) == ID_AA64DFR0_TRACEFILT_SUPPORTED);
}
/*******************************************************************************
* Function to identify the presence of FEAT_AMUv1 (Activity Monitors-
* Extension v1)
******************************************************************************/
static inline bool is_armv8_4_feat_amuv1_present(void)
{
return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
ID_AA64PFR0_AMU_MASK) >= ID_AA64PFR0_AMU_V1);
}
/********************************************************************************
* Function to identify the presence of FEAT_NV2 (Enhanced Nested Virtualization
* Support)
*******************************************************************************/
static inline unsigned int get_armv8_4_feat_nv_support(void)
{
return (((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_NV_SHIFT) &
ID_AA64MMFR2_EL1_NV_MASK));
}
/*******************************************************************************
* Function to identify the presence of FEAT_BRBE (Branch Record Buffer
* Extension)
******************************************************************************/
static inline bool is_feat_brbe_present(void)
{
return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_BRBE_SHIFT) &
ID_AA64DFR0_BRBE_MASK) == ID_AA64DFR0_BRBE_SUPPORTED);
}
/*******************************************************************************
* Function to identify the presence of FEAT_TRBE (Trace Buffer Extension)
******************************************************************************/
static inline bool is_feat_trbe_present(void)
{
return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT) &
ID_AA64DFR0_TRACEBUFFER_MASK) == ID_AA64DFR0_TRACEBUFFER_SUPPORTED);
}
#endif /* ARCH_FEATURES_H */
@@ -0,0 +1,671 @@
/*
* Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ARCH_HELPERS_H
#define ARCH_HELPERS_H
#include <cdefs.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <arch.h>
/**********************************************************************
* Macros which create inline functions to read or write CPU system
* registers
*********************************************************************/
#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \
static inline u_register_t read_ ## _name(void) \
{ \
u_register_t v; \
__asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \
return v; \
}
#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \
static inline void write_ ## _name(u_register_t v) \
{ \
__asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \
}
#define SYSREG_WRITE_CONST(reg_name, v) \
__asm__ volatile ("msr " #reg_name ", %0" : : "i" (v))
/* Define read function for system register */
#define DEFINE_SYSREG_READ_FUNC(_name) \
_DEFINE_SYSREG_READ_FUNC(_name, _name)
/* Define read & write function for system register */
#define DEFINE_SYSREG_RW_FUNCS(_name) \
_DEFINE_SYSREG_READ_FUNC(_name, _name) \
_DEFINE_SYSREG_WRITE_FUNC(_name, _name)
/* Define read & write function for renamed system register */
#define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name) \
_DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \
_DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
/* Define read function for renamed system register */
#define DEFINE_RENAME_SYSREG_READ_FUNC(_name, _reg_name) \
_DEFINE_SYSREG_READ_FUNC(_name, _reg_name)
/* Define write function for renamed system register */
#define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name) \
_DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
/**********************************************************************
* Macros to create inline functions for system instructions
*********************************************************************/
/* Define function for simple system instruction */
#define DEFINE_SYSOP_FUNC(_op) \
static inline void _op(void) \
{ \
__asm__ (#_op); \
}
/* Define function for system instruction with register parameter */
#define DEFINE_SYSOP_PARAM_FUNC(_op) \
static inline void _op(uint64_t v) \
{ \
__asm__ (#_op " %0" : : "r" (v)); \
}
/* Define function for system instruction with type specifier */
#define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \
static inline void _op ## _type(void) \
{ \
__asm__ (#_op " " #_type : : : "memory"); \
}
/* Define function for system instruction with register parameter */
#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \
static inline void _op ## _type(uint64_t v) \
{ \
__asm__ (#_op " " #_type ", %0" : : "r" (v)); \
}
/*******************************************************************************
* TLB maintenance accessor prototypes
******************************************************************************/
#if ERRATA_A57_813419 || ERRATA_A76_1286807
/*
* Define function for TLBI instruction with type specifier that implements
* the workaround for errata 813419 of Cortex-A57 or errata 1286807 of
* Cortex-A76.
*/
#define DEFINE_TLBIOP_ERRATA_TYPE_FUNC(_type)\
static inline void tlbi ## _type(void) \
{ \
__asm__("tlbi " #_type "\n" \
"dsb ish\n" \
"tlbi " #_type); \
}
/*
* Define function for TLBI instruction with register parameter that implements
* the workaround for errata 813419 of Cortex-A57 or errata 1286807 of
* Cortex-A76.
*/
#define DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(_type) \
static inline void tlbi ## _type(uint64_t v) \
{ \
__asm__("tlbi " #_type ", %0\n" \
"dsb ish\n" \
"tlbi " #_type ", %0" : : "r" (v)); \
}
#endif /* ERRATA_A57_813419 */
#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319
/*
* Define function for DC instruction with register parameter that enables
* the workaround for errata 819472, 824069 and 827319 of Cortex-A53.
*/
#define DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(_name, _type) \
static inline void dc ## _name(uint64_t v) \
{ \
__asm__("dc " #_type ", %0" : : "r" (v)); \
}
#endif /* ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 */
#if ERRATA_A57_813419
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is)
DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1)
#elif ERRATA_A76_1286807
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1is)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2is)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is)
DEFINE_TLBIOP_ERRATA_TYPE_FUNC(vmalle1)
#else
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3)
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is)
DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1)
#endif
#if ERRATA_A57_813419
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is)
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is)
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is)
#elif ERRATA_A76_1286807
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaae1is)
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaale1is)
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae2is)
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale2is)
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is)
DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is)
#else
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae3is)
DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale3is)
#endif
/*******************************************************************************
* Cache maintenance accessor prototypes
******************************************************************************/
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw)
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw)
#if ERRATA_A53_827319
DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(csw, cisw)
#else
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw)
#endif
#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319
DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(cvac, civac)
#else
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac)
#endif
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac)
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac)
#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319
DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(cvau, civac)
#else
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau)
#endif
DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva)
/*******************************************************************************
* Address translation accessor prototypes
******************************************************************************/
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, s1e1r)
DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e2r)
DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e3r)
/*******************************************************************************
* Strip Pointer Authentication Code
******************************************************************************/
DEFINE_SYSOP_PARAM_FUNC(xpaci)
void flush_dcache_range(uintptr_t addr, size_t size);
void flush_dcache_to_popa_range(uintptr_t addr, size_t size);
void clean_dcache_range(uintptr_t addr, size_t size);
void inv_dcache_range(uintptr_t addr, size_t size);
bool is_dcache_enabled(void);
void dcsw_op_louis(u_register_t op_type);
void dcsw_op_all(u_register_t op_type);
void disable_mmu_el1(void);
void disable_mmu_el3(void);
void disable_mpu_el2(void);
void disable_mmu_icache_el1(void);
void disable_mmu_icache_el3(void);
void disable_mpu_icache_el2(void);
/*******************************************************************************
* Misc. accessor prototypes
******************************************************************************/
#define write_daifclr(val) SYSREG_WRITE_CONST(daifclr, val)
#define write_daifset(val) SYSREG_WRITE_CONST(daifset, val)
DEFINE_SYSREG_RW_FUNCS(par_el1)
DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64isar0_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64isar2_el1, ID_AA64ISAR2_EL1)
DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1)
DEFINE_SYSREG_READ_FUNC(id_afr0_el1)
DEFINE_SYSREG_READ_FUNC(CurrentEl)
DEFINE_SYSREG_READ_FUNC(ctr_el0)
DEFINE_SYSREG_RW_FUNCS(daif)
DEFINE_SYSREG_RW_FUNCS(spsr_el1)
DEFINE_SYSREG_RW_FUNCS(spsr_el2)
DEFINE_SYSREG_RW_FUNCS(spsr_el3)
DEFINE_SYSREG_RW_FUNCS(elr_el1)
DEFINE_SYSREG_RW_FUNCS(elr_el2)
DEFINE_SYSREG_RW_FUNCS(elr_el3)
DEFINE_SYSREG_RW_FUNCS(mdccsr_el0)
DEFINE_SYSREG_RW_FUNCS(dbgdtrrx_el0)
DEFINE_SYSREG_RW_FUNCS(dbgdtrtx_el0)
DEFINE_SYSREG_RW_FUNCS(sp_el1)
DEFINE_SYSREG_RW_FUNCS(sp_el2)
DEFINE_SYSOP_FUNC(wfi)
DEFINE_SYSOP_FUNC(wfe)
DEFINE_SYSOP_FUNC(sev)
DEFINE_SYSOP_TYPE_FUNC(dsb, sy)
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, osh)
DEFINE_SYSOP_TYPE_FUNC(dsb, nsh)
DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
DEFINE_SYSOP_TYPE_FUNC(dsb, oshst)
DEFINE_SYSOP_TYPE_FUNC(dmb, oshld)
DEFINE_SYSOP_TYPE_FUNC(dmb, oshst)
DEFINE_SYSOP_TYPE_FUNC(dmb, osh)
DEFINE_SYSOP_TYPE_FUNC(dmb, nshld)
DEFINE_SYSOP_TYPE_FUNC(dmb, nshst)
DEFINE_SYSOP_TYPE_FUNC(dmb, nsh)
DEFINE_SYSOP_TYPE_FUNC(dmb, ishld)
DEFINE_SYSOP_TYPE_FUNC(dmb, ishst)
DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
DEFINE_SYSOP_FUNC(isb)
static inline void enable_irq(void)
{
/*
* The compiler memory barrier will prevent the compiler from
* scheduling non-volatile memory access after the write to the
* register.
*
* This could happen if some initialization code issues non-volatile
* accesses to an area used by an interrupt handler, in the assumption
* that it is safe as the interrupts are disabled at the time it does
* that (according to program order). However, non-volatile accesses
* are not necessarily in program order relatively with volatile inline
* assembly statements (and volatile accesses).
*/
COMPILER_BARRIER();
write_daifclr(DAIF_IRQ_BIT);
isb();
}
static inline void enable_fiq(void)
{
COMPILER_BARRIER();
write_daifclr(DAIF_FIQ_BIT);
isb();
}
static inline void enable_serror(void)
{
COMPILER_BARRIER();
write_daifclr(DAIF_ABT_BIT);
isb();
}
static inline void enable_debug_exceptions(void)
{
COMPILER_BARRIER();
write_daifclr(DAIF_DBG_BIT);
isb();
}
static inline void disable_irq(void)
{
COMPILER_BARRIER();
write_daifset(DAIF_IRQ_BIT);
isb();
}
static inline void disable_fiq(void)
{
COMPILER_BARRIER();
write_daifset(DAIF_FIQ_BIT);
isb();
}
static inline void disable_serror(void)
{
COMPILER_BARRIER();
write_daifset(DAIF_ABT_BIT);
isb();
}
static inline void disable_debug_exceptions(void)
{
COMPILER_BARRIER();
write_daifset(DAIF_DBG_BIT);
isb();
}
void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3,
uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7);
/*******************************************************************************
* System register accessor prototypes
******************************************************************************/
DEFINE_SYSREG_READ_FUNC(midr_el1)
DEFINE_SYSREG_READ_FUNC(mpidr_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64mmfr1_el1)
DEFINE_SYSREG_RW_FUNCS(scr_el3)
DEFINE_SYSREG_RW_FUNCS(hcr_el2)
DEFINE_SYSREG_RW_FUNCS(vbar_el1)
DEFINE_SYSREG_RW_FUNCS(vbar_el2)
DEFINE_SYSREG_RW_FUNCS(vbar_el3)
DEFINE_SYSREG_RW_FUNCS(sctlr_el1)
DEFINE_SYSREG_RW_FUNCS(sctlr_el2)
DEFINE_SYSREG_RW_FUNCS(sctlr_el3)
DEFINE_SYSREG_RW_FUNCS(actlr_el1)
DEFINE_SYSREG_RW_FUNCS(actlr_el2)
DEFINE_SYSREG_RW_FUNCS(actlr_el3)
DEFINE_SYSREG_RW_FUNCS(esr_el1)
DEFINE_SYSREG_RW_FUNCS(esr_el2)
DEFINE_SYSREG_RW_FUNCS(esr_el3)
DEFINE_SYSREG_RW_FUNCS(afsr0_el1)
DEFINE_SYSREG_RW_FUNCS(afsr0_el2)
DEFINE_SYSREG_RW_FUNCS(afsr0_el3)
DEFINE_SYSREG_RW_FUNCS(afsr1_el1)
DEFINE_SYSREG_RW_FUNCS(afsr1_el2)
DEFINE_SYSREG_RW_FUNCS(afsr1_el3)
DEFINE_SYSREG_RW_FUNCS(far_el1)
DEFINE_SYSREG_RW_FUNCS(far_el2)
DEFINE_SYSREG_RW_FUNCS(far_el3)
DEFINE_SYSREG_RW_FUNCS(mair_el1)
DEFINE_SYSREG_RW_FUNCS(mair_el2)
DEFINE_SYSREG_RW_FUNCS(mair_el3)
DEFINE_SYSREG_RW_FUNCS(amair_el1)
DEFINE_SYSREG_RW_FUNCS(amair_el2)
DEFINE_SYSREG_RW_FUNCS(amair_el3)
DEFINE_SYSREG_READ_FUNC(rvbar_el1)
DEFINE_SYSREG_READ_FUNC(rvbar_el2)
DEFINE_SYSREG_READ_FUNC(rvbar_el3)
DEFINE_SYSREG_RW_FUNCS(rmr_el1)
DEFINE_SYSREG_RW_FUNCS(rmr_el2)
DEFINE_SYSREG_RW_FUNCS(rmr_el3)
DEFINE_SYSREG_RW_FUNCS(tcr_el1)
DEFINE_SYSREG_RW_FUNCS(tcr_el2)
DEFINE_SYSREG_RW_FUNCS(tcr_el3)
DEFINE_SYSREG_RW_FUNCS(ttbr0_el1)
DEFINE_SYSREG_RW_FUNCS(ttbr0_el2)
DEFINE_SYSREG_RW_FUNCS(ttbr0_el3)
DEFINE_SYSREG_RW_FUNCS(ttbr1_el1)
DEFINE_SYSREG_RW_FUNCS(vttbr_el2)
DEFINE_SYSREG_RW_FUNCS(cptr_el2)
DEFINE_SYSREG_RW_FUNCS(cptr_el3)
DEFINE_SYSREG_RW_FUNCS(cpacr_el1)
DEFINE_SYSREG_RW_FUNCS(cntfrq_el0)
DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2)
DEFINE_SYSREG_RW_FUNCS(cnthp_tval_el2)
DEFINE_SYSREG_RW_FUNCS(cnthp_cval_el2)
DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1)
DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1)
DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1)
DEFINE_SYSREG_RW_FUNCS(cntp_ctl_el0)
DEFINE_SYSREG_RW_FUNCS(cntp_tval_el0)
DEFINE_SYSREG_RW_FUNCS(cntp_cval_el0)
DEFINE_SYSREG_READ_FUNC(cntpct_el0)
DEFINE_SYSREG_RW_FUNCS(cnthctl_el2)
DEFINE_SYSREG_RW_FUNCS(vtcr_el2)
#define get_cntp_ctl_enable(x) (((x) >> CNTP_CTL_ENABLE_SHIFT) & \
CNTP_CTL_ENABLE_MASK)
#define get_cntp_ctl_imask(x) (((x) >> CNTP_CTL_IMASK_SHIFT) & \
CNTP_CTL_IMASK_MASK)
#define get_cntp_ctl_istatus(x) (((x) >> CNTP_CTL_ISTATUS_SHIFT) & \
CNTP_CTL_ISTATUS_MASK)
#define set_cntp_ctl_enable(x) ((x) |= (U(1) << CNTP_CTL_ENABLE_SHIFT))
#define set_cntp_ctl_imask(x) ((x) |= (U(1) << CNTP_CTL_IMASK_SHIFT))
#define clr_cntp_ctl_enable(x) ((x) &= ~(U(1) << CNTP_CTL_ENABLE_SHIFT))
#define clr_cntp_ctl_imask(x) ((x) &= ~(U(1) << CNTP_CTL_IMASK_SHIFT))
DEFINE_SYSREG_RW_FUNCS(tpidr_el3)
DEFINE_SYSREG_RW_FUNCS(cntvoff_el2)
DEFINE_SYSREG_RW_FUNCS(vpidr_el2)
DEFINE_SYSREG_RW_FUNCS(vmpidr_el2)
DEFINE_SYSREG_READ_FUNC(isr_el1)
DEFINE_SYSREG_RW_FUNCS(mdcr_el2)
DEFINE_SYSREG_RW_FUNCS(mdcr_el3)
DEFINE_SYSREG_RW_FUNCS(hstr_el2)
DEFINE_SYSREG_RW_FUNCS(pmcr_el0)
/* GICv3 System Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(icc_rpr_el1, ICC_RPR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el3, ICC_IGRPEN1_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir0_el1, ICC_HPPIR0_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir1_el1, ICC_HPPIR1_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar0_el1, ICC_IAR0_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar1_el1, ICC_IAR1_EL1)
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(icc_sgi1r, ICC_SGI1R)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r, ICC_ASGI1R)
DEFINE_RENAME_SYSREG_READ_FUNC(amcfgr_el0, AMCFGR_EL0)
DEFINE_RENAME_SYSREG_READ_FUNC(amcgcr_el0, AMCGCR_EL0)
DEFINE_RENAME_SYSREG_READ_FUNC(amcg1idr_el0, AMCG1IDR_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcr_el0, AMCR_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
DEFINE_RENAME_SYSREG_READ_FUNC(mpamidr_el1, MPAMIDR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3)
DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2)
DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64smfr0_el1, ID_AA64SMFR0_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(smcr_el3, SMCR_EL3)
DEFINE_RENAME_SYSREG_READ_FUNC(erridr_el1, ERRIDR_EL1)
DEFINE_RENAME_SYSREG_WRITE_FUNC(errselr_el1, ERRSELR_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(erxfr_el1, ERXFR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(erxctlr_el1, ERXCTLR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(erxstatus_el1, ERXSTATUS_EL1)
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.2 Registers */
DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1)
/* Armv8.3 Pointer Authentication Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1)
/* Armv8.4 Data Independent Timing Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(dit, DIT)
/* Armv8.5 MTE Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(tfsre0_el1, TFSRE0_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1)
/* Armv8.5 FEAT_RNG Registers */
DEFINE_SYSREG_READ_FUNC(rndr)
DEFINE_SYSREG_READ_FUNC(rndrrs)
/* FEAT_HCX Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2)
/* DynamIQ Shared Unit power management */
DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
/* CPU Power/Performance Management registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(cpuppmcr_el3, CPUPPMCR_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(cpumpmmcr_el3, CPUMPMMCR_EL3)
/* Armv9.2 RME Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3)
#define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x)
#define IS_IN_EL1() IS_IN_EL(1)
#define IS_IN_EL2() IS_IN_EL(2)
#define IS_IN_EL3() IS_IN_EL(3)
static inline unsigned int get_current_el(void)
{
return GET_EL(read_CurrentEl());
}
static inline unsigned int get_current_el_maybe_constant(void)
{
#if defined(IMAGE_AT_EL1)
return 1;
#elif defined(IMAGE_AT_EL2)
return 2; /* no use-case in TF-A */
#elif defined(IMAGE_AT_EL3)
return 3;
#else
/*
* If we do not know which exception level this is being built for
* (e.g. built for library), fall back to run-time detection.
*/
return get_current_el();
#endif
}
/*
* Check if an EL is implemented from AA64PFR0 register fields.
*/
static inline uint64_t el_implemented(unsigned int el)
{
if (el > 3U) {
return EL_IMPL_NONE;
} else {
unsigned int shift = ID_AA64PFR0_EL1_SHIFT * el;
return (read_id_aa64pfr0_el1() >> shift) & ID_AA64PFR0_ELX_MASK;
}
}
/*
* TLBIPAALLOS instruction
* (TLB Inivalidate GPT Information by PA,
* All Entries, Outer Shareable)
*/
static inline void tlbipaallos(void)
{
__asm__("SYS #6,c8,c1,#4");
}
/*
* Invalidate TLBs of GPT entries by Physical address, last level.
*
* @pa: the starting address for the range
* of invalidation
* @size: size of the range of invalidation
*/
void gpt_tlbi_by_pa_ll(uint64_t pa, size_t size);
/* Previously defined accessor functions with incomplete register names */
#define read_current_el() read_CurrentEl()
#define dsb() dsbsy()
#define read_midr() read_midr_el1()
#define read_mpidr() read_mpidr_el1()
#define read_scr() read_scr_el3()
#define write_scr(_v) write_scr_el3(_v)
#define read_hcr() read_hcr_el2()
#define write_hcr(_v) write_hcr_el2(_v)
#define read_cpacr() read_cpacr_el1()
#define write_cpacr(_v) write_cpacr_el1(_v)
#define read_clusterpwrdn() read_clusterpwrdn_el1()
#define write_clusterpwrdn(_v) write_clusterpwrdn_el1(_v)
#if ERRATA_SPECULATIVE_AT
/*
* Assuming SCTLR.M bit is already enabled
* 1. Enable page table walk by clearing TCR_EL1.EPDx bits
* 2. Execute AT instruction for lower EL1/0
* 3. Disable page table walk by setting TCR_EL1.EPDx bits
*/
#define AT(_at_inst, _va) \
{ \
assert((read_sctlr_el1() & SCTLR_M_BIT) != 0ULL); \
write_tcr_el1(read_tcr_el1() & ~(TCR_EPD0_BIT | TCR_EPD1_BIT)); \
isb(); \
_at_inst(_va); \
write_tcr_el1(read_tcr_el1() | (TCR_EPD0_BIT | TCR_EPD1_BIT)); \
isb(); \
}
#else
#define AT(_at_inst, _va) _at_inst(_va);
#endif
#endif /* ARCH_HELPERS_H */
@@ -0,0 +1,244 @@
/*
* Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ASM_MACROS_S
#define ASM_MACROS_S
#include <arch.h>
#include <common/asm_macros_common.S>
#include <lib/spinlock.h>
/*
* TLBI instruction with type specifier that implements the workaround for
* errata 813419 of Cortex-A57 or errata 1286807 of Cortex-A76.
*/
#if ERRATA_A57_813419 || ERRATA_A76_1286807
#define TLB_INVALIDATE(_type) \
tlbi _type; \
dsb ish; \
tlbi _type
#else
#define TLB_INVALIDATE(_type) \
tlbi _type
#endif
.macro func_prologue
stp x29, x30, [sp, #-0x10]!
mov x29,sp
.endm
.macro func_epilogue
ldp x29, x30, [sp], #0x10
.endm
.macro dcache_line_size reg, tmp
mrs \tmp, ctr_el0
ubfx \tmp, \tmp, #16, #4
mov \reg, #4
lsl \reg, \reg, \tmp
.endm
.macro icache_line_size reg, tmp
mrs \tmp, ctr_el0
and \tmp, \tmp, #0xf
mov \reg, #4
lsl \reg, \reg, \tmp
.endm
.macro smc_check label
mrs x0, esr_el3
ubfx x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH
cmp x0, #EC_AARCH64_SMC
b.ne $label
.endm
/*
* Declare the exception vector table, enforcing it is aligned on a
* 2KB boundary, as required by the ARMv8 architecture.
* Use zero bytes as the fill value to be stored in the padding bytes
* so that it inserts illegal AArch64 instructions. This increases
* security, robustness and potentially facilitates debugging.
*/
.macro vector_base label, section_name=.vectors
.section \section_name, "ax"
.align 11, 0
\label:
.endm
/*
* Create an entry in the exception vector table, enforcing it is
* aligned on a 128-byte boundary, as required by the ARMv8 architecture.
* Use zero bytes as the fill value to be stored in the padding bytes
* so that it inserts illegal AArch64 instructions. This increases
* security, robustness and potentially facilitates debugging.
*/
.macro vector_entry label, section_name=.vectors
.cfi_sections .debug_frame
.section \section_name, "ax"
.align 7, 0
.type \label, %function
.cfi_startproc
\label:
.endm
/*
* Add the bytes until fill the full exception vector, whose size is always
* 32 instructions. If there are more than 32 instructions in the
* exception vector then an error is emitted.
*/
.macro end_vector_entry label
.cfi_endproc
.fill \label + (32 * 4) - .
.endm
/*
* This macro calculates the base address of the current CPU's MP stack
* using the plat_my_core_pos() index, the name of the stack storage
* and the size of each stack
* Out: X0 = physical address of stack base
* Clobber: X30, X1, X2
*/
.macro get_my_mp_stack _name, _size
bl plat_my_core_pos
adrp x2, (\_name + \_size)
add x2, x2, :lo12:(\_name + \_size)
mov x1, #\_size
madd x0, x0, x1, x2
.endm
/*
* This macro calculates the base address of a UP stack using the
* name of the stack storage and the size of the stack
* Out: X0 = physical address of stack base
*/
.macro get_up_stack _name, _size
adrp x0, (\_name + \_size)
add x0, x0, :lo12:(\_name + \_size)
.endm
/*
* Helper macro to generate the best mov/movk combinations according
* the value to be moved. The 16 bits from '_shift' are tested and
* if not zero, they are moved into '_reg' without affecting
* other bits.
*/
.macro _mov_imm16 _reg, _val, _shift
.if (\_val >> \_shift) & 0xffff
.if (\_val & (1 << \_shift - 1))
movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift
.else
mov \_reg, \_val & (0xffff << \_shift)
.endif
.endif
.endm
/*
* Helper macro to load arbitrary values into 32 or 64-bit registers
* which generates the best mov/movk combinations. Many base addresses
* are 64KB aligned the macro will eliminate updating bits 15:0 in
* that case
*/
.macro mov_imm _reg, _val
.if (\_val) == 0
mov \_reg, #0
.else
_mov_imm16 \_reg, (\_val), 0
_mov_imm16 \_reg, (\_val), 16
_mov_imm16 \_reg, (\_val), 32
_mov_imm16 \_reg, (\_val), 48
.endif
.endm
/*
* Macro to mark instances where we're jumping to a function and don't
* expect a return. To provide the function being jumped to with
* additional information, we use 'bl' instruction to jump rather than
* 'b'.
*
* Debuggers infer the location of a call from where LR points to, which
* is usually the instruction after 'bl'. If this macro expansion
* happens to be the last location in a function, that'll cause the LR
* to point a location beyond the function, thereby misleading debugger
* back trace. We therefore insert a 'nop' after the function call for
* debug builds, unless 'skip_nop' parameter is non-zero.
*/
.macro no_ret _func:req, skip_nop=0
bl \_func
#if DEBUG
.ifeq \skip_nop
nop
.endif
#endif
.endm
/*
* Reserve space for a spin lock in assembly file.
*/
.macro define_asm_spinlock _name:req
.align SPINLOCK_ASM_ALIGN
\_name:
.space SPINLOCK_ASM_SIZE
.endm
#if RAS_EXTENSION
.macro esb
.inst 0xd503221f
.endm
#endif
/*
* Helper macro to read system register value into x0
*/
.macro read reg:req
#if ENABLE_BTI
bti j
#endif
mrs x0, \reg
ret
.endm
/*
* Helper macro to write value from x1 to system register
*/
.macro write reg:req
#if ENABLE_BTI
bti j
#endif
msr \reg, x1
ret
.endm
/*
* Macro for using speculation barrier instruction introduced by
* FEAT_SB, if it's enabled.
*/
.macro speculation_barrier
#if ENABLE_FEAT_SB
sb
#else
dsb sy
isb
#endif
.endm
/*
* Macro for mitigating against speculative execution beyond ERET. Uses the
* speculation barrier instruction introduced by FEAT_SB, if it's enabled.
*/
.macro exception_return
eret
#if ENABLE_FEAT_SB
sb
#else
dsb nsh
isb
#endif
.endm
#endif /* ASM_MACROS_S */
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ASSERT_MACROS_S
#define ASSERT_MACROS_S
/*
* Assembler macro to enable asm_assert. Use this macro wherever
* assert is required in assembly. Please note that the macro makes
* use of label '300' to provide the logic and the caller
* should make sure that this label is not used to branch prior
* to calling this macro.
*/
#define ASM_ASSERT(_cc) \
.ifndef .L_assert_filename ;\
.pushsection .rodata.str1.1, "aS" ;\
.L_assert_filename: ;\
.string __FILE__ ;\
.popsection ;\
.endif ;\
b._cc 300f ;\
adr x0, .L_assert_filename ;\
mov x1, __LINE__ ;\
b asm_assert ;\
300:
#endif /* ASSERT_MACROS_S */
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CONSOLE_MACROS_S
#define CONSOLE_MACROS_S
#include <drivers/console.h>
/*
* This macro encapsulates the common setup that has to be done at the end of
* a console driver's register function. It will register all of the driver's
* callbacks in the console_t structure and initialize the flags field (by
* default consoles are enabled for the "boot" and "crash" states, this can be
* changed after registration with the console_set_scope() function). It ends
* with a tail call that will include return to the caller.
* REQUIRES console_t pointer in x0 and a valid return address in x30.
*/
.macro finish_console_register _driver, putc=0, getc=0, flush=0
/*
* If any of the callback is not specified or set as 0, then the
* corresponding callback entry in console_t is set to 0.
*/
.ifne \putc
adrp x1, console_\_driver\()_putc
add x1, x1, :lo12:console_\_driver\()_putc
str x1, [x0, #CONSOLE_T_PUTC]
.else
str xzr, [x0, #CONSOLE_T_PUTC]
.endif
.ifne \getc
adrp x1, console_\_driver\()_getc
add x1, x1, :lo12:console_\_driver\()_getc
str x1, [x0, #CONSOLE_T_GETC]
.else
str xzr, [x0, #CONSOLE_T_GETC]
.endif
.ifne \flush
adrp x1, console_\_driver\()_flush
add x1, x1, :lo12:console_\_driver\()_flush
str x1, [x0, #CONSOLE_T_FLUSH]
.else
str xzr, [x0, #CONSOLE_T_FLUSH]
.endif
mov x1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
str x1, [x0, #CONSOLE_T_FLAGS]
b console_register
.endm
#endif /* CONSOLE_MACROS_S */
@@ -0,0 +1,422 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef EL2_COMMON_MACROS_S
#define EL2_COMMON_MACROS_S
#include <arch.h>
#include <asm_macros.S>
#include <context.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
#include <platform_def.h>
/*
* Helper macro to initialise system registers at EL2.
*/
.macro el2_arch_init_common
/* ---------------------------------------------------------------------
* SCTLR_EL2 has already been initialised - read current value before
* modifying.
*
* SCTLR_EL2.I: Enable the instruction cache.
*
* SCTLR_EL2.SA: Enable Stack Alignment check. A SP alignment fault
* exception is generated if a load or store instruction executed at
* EL2 uses the SP as the base address and the SP is not aligned to a
* 16-byte boundary.
*
* SCTLR_EL2.A: Enable Alignment fault checking. All instructions that
* load or store one or more registers have an alignment check that the
* address being accessed is aligned to the size of the data element(s)
* being accessed.
* ---------------------------------------------------------------------
*/
mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
mrs x0, sctlr_el2
orr x0, x0, x1
msr sctlr_el2, x0
isb
/* ---------------------------------------------------------------------
* Initialise HCR_EL2, setting all fields rather than relying on HW.
* All fields are architecturally UNKNOWN on reset. The following fields
* do not change during the TF lifetime. The remaining fields are set to
* zero here but are updated ahead of transitioning to a lower EL in the
* function cm_init_context_common().
*
* HCR_EL2.TWE: Set to zero so that execution of WFE instructions at
* EL2, EL1 and EL0 are not trapped to EL2.
*
* HCR_EL2.TWI: Set to zero so that execution of WFI instructions at
* EL2, EL1 and EL0 are not trapped to EL2.
*
* HCR_EL2.HCD: Set to zero to enable HVC calls at EL1 and above,
* from both Security states and both Execution states.
*
* HCR_EL2.TEA: Set to one to route External Aborts and SError
* Interrupts to EL2 when executing at any EL.
*
* HCR_EL2.{API,APK}: For Armv8.3 pointer authentication feature,
* disable traps to EL2 when accessing key registers or using
* pointer authentication instructions from lower ELs.
* ---------------------------------------------------------------------
*/
mov_imm x0, ((HCR_RESET_VAL | HCR_TEA_BIT) \
& ~(HCR_TWE_BIT | HCR_TWI_BIT | HCR_HCD_BIT))
#if CTX_INCLUDE_PAUTH_REGS
/*
* If the pointer authentication registers are saved during world
* switches, enable pointer authentication everywhere, as it is safe to
* do so.
*/
orr x0, x0, #(HCR_API_BIT | HCR_APK_BIT)
#endif /* CTX_INCLUDE_PAUTH_REGS */
msr hcr_el2, x0
/* ---------------------------------------------------------------------
* Initialise MDCR_EL2, setting all fields rather than relying on
* hw. Some fields are architecturally UNKNOWN on reset.
*
* MDCR_EL2.TDOSA: Set to zero so that EL2 and EL2 System register
* access to the powerdown debug registers do not trap to EL2.
*
* MDCR_EL2.TDA: Set to zero to allow EL0, EL1 and EL2 access to the
* debug registers, other than those registers that are controlled by
* MDCR_EL2.TDOSA.
*
* MDCR_EL2.TPM: Set to zero so that EL0, EL1, and EL2 System
* register accesses to all Performance Monitors registers do not trap
* to EL2.
*
* MDCR_EL2.HPMD: Set to zero so that event counting by the program-
* mable counters PMEVCNTR<n>_EL0 is prohibited in Secure state. If
* ARMv8.2 Debug is not implemented this bit does not have any effect
* on the counters unless there is support for the implementation
* defined authentication interface
* ExternalSecureNoninvasiveDebugEnabled().
* ---------------------------------------------------------------------
*/
mov_imm x0, ((MDCR_EL2_RESET_VAL | \
MDCR_SPD32(MDCR_SPD32_DISABLE)) \
& ~(MDCR_EL2_HPMD | MDCR_TDOSA_BIT | \
MDCR_TDA_BIT | MDCR_TPM_BIT))
msr mdcr_el2, x0
/* ---------------------------------------------------------------------
* Initialise PMCR_EL0 setting all fields rather than relying
* on hw. Some fields are architecturally UNKNOWN on reset.
*
* PMCR_EL0.DP: Set to one so that the cycle counter,
* PMCCNTR_EL0 does not count when event counting is prohibited.
*
* PMCR_EL0.X: Set to zero to disable export of events.
*
* PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0
* counts on every clock cycle.
* ---------------------------------------------------------------------
*/
mov_imm x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_DP_BIT) & \
~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT))
msr pmcr_el0, x0
/* ---------------------------------------------------------------------
* Enable External Aborts and SError Interrupts now that the exception
* vectors have been setup.
* ---------------------------------------------------------------------
*/
msr daifclr, #DAIF_ABT_BIT
/* ---------------------------------------------------------------------
* Initialise CPTR_EL2, setting all fields rather than relying on hw.
* All fields are architecturally UNKNOWN on reset.
*
* CPTR_EL2.TCPAC: Set to zero so that any accesses to CPACR_EL1 do
* not trap to EL2.
*
* CPTR_EL2.TTA: Set to zero so that System register accesses to the
* trace registers do not trap to EL2.
*
* CPTR_EL2.TFP: Set to zero so that accesses to the V- or Z- registers
* by Advanced SIMD, floating-point or SVE instructions (if implemented)
* do not trap to EL2.
*/
mov_imm x0, (CPTR_EL2_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
msr cptr_el2, x0
/*
* If Data Independent Timing (DIT) functionality is implemented,
* always enable DIT in EL2
*/
mrs x0, id_aa64pfr0_el1
ubfx x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH
cmp x0, #ID_AA64PFR0_DIT_SUPPORTED
bne 1f
mov x0, #DIT_BIT
msr DIT, x0
1:
.endm
/* -----------------------------------------------------------------------------
* This is the super set of actions that need to be performed during a cold boot
* or a warm boot in EL2. This code is shared by BL1 and BL31.
*
* This macro will always perform reset handling, architectural initialisations
* and stack setup. The rest of the actions are optional because they might not
* be needed, depending on the context in which this macro is called. This is
* why this macro is parameterised ; each parameter allows to enable/disable
* some actions.
*
* _init_sctlr:
* Whether the macro needs to initialise SCTLR_EL2, including configuring
* the endianness of data accesses.
*
* _warm_boot_mailbox:
* Whether the macro needs to detect the type of boot (cold/warm). The
* detection is based on the platform entrypoint address : if it is zero
* then it is a cold boot, otherwise it is a warm boot. In the latter case,
* this macro jumps on the platform entrypoint address.
*
* _secondary_cold_boot:
* Whether the macro needs to identify the CPU that is calling it: primary
* CPU or secondary CPU. The primary CPU will be allowed to carry on with
* the platform initialisations, while the secondaries will be put in a
* platform-specific state in the meantime.
*
* If the caller knows this macro will only be called by the primary CPU
* then this parameter can be defined to 0 to skip this step.
*
* _init_memory:
* Whether the macro needs to initialise the memory.
*
* _init_c_runtime:
* Whether the macro needs to initialise the C runtime environment.
*
* _exception_vectors:
* Address of the exception vectors to program in the VBAR_EL2 register.
*
* _pie_fixup_size:
* Size of memory region to fixup Global Descriptor Table (GDT).
*
* A non-zero value is expected when firmware needs GDT to be fixed-up.
*
* -----------------------------------------------------------------------------
*/
.macro el2_entrypoint_common \
_init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \
_init_memory, _init_c_runtime, _exception_vectors, \
_pie_fixup_size
.if \_init_sctlr
/* -------------------------------------------------------------
* This is the initialisation of SCTLR_EL2 and so must ensure
* that all fields are explicitly set rather than relying on hw.
* Some fields reset to an IMPLEMENTATION DEFINED value and
* others are architecturally UNKNOWN on reset.
*
* SCTLR.EE: Set the CPU endianness before doing anything that
* might involve memory reads or writes. Set to zero to select
* Little Endian.
*
* SCTLR_EL2.WXN: For the EL2 translation regime, this field can
* force all memory regions that are writeable to be treated as
* XN (Execute-never). Set to zero so that this control has no
* effect on memory access permissions.
*
* SCTLR_EL2.SA: Set to zero to disable Stack Alignment check.
*
* SCTLR_EL2.A: Set to zero to disable Alignment fault checking.
*
* SCTLR.DSSBS: Set to zero to disable speculation store bypass
* safe behaviour upon exception entry to EL2.
* -------------------------------------------------------------
*/
mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \
| SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT))
msr sctlr_el2, x0
isb
.endif /* _init_sctlr */
#if DISABLE_MTPMU
bl mtpmu_disable
#endif
.if \_warm_boot_mailbox
/* -------------------------------------------------------------
* This code will be executed for both warm and cold resets.
* Now is the time to distinguish between the two.
* Query the platform entrypoint address and if it is not zero
* then it means it is a warm boot so jump to this address.
* -------------------------------------------------------------
*/
bl plat_get_my_entrypoint
cbz x0, do_cold_boot
br x0
do_cold_boot:
.endif /* _warm_boot_mailbox */
.if \_pie_fixup_size
#if ENABLE_PIE
/*
* ------------------------------------------------------------
* If PIE is enabled fixup the Global descriptor Table only
* once during primary core cold boot path.
*
* Compile time base address, required for fixup, is calculated
* using "pie_fixup" label present within first page.
* ------------------------------------------------------------
*/
pie_fixup:
ldr x0, =pie_fixup
and x0, x0, #~(PAGE_SIZE_MASK)
mov_imm x1, \_pie_fixup_size
add x1, x1, x0
bl fixup_gdt_reloc
#endif /* ENABLE_PIE */
.endif /* _pie_fixup_size */
/* ---------------------------------------------------------------------
* Set the exception vectors.
* ---------------------------------------------------------------------
*/
adr x0, \_exception_vectors
msr vbar_el2, x0
isb
/* ---------------------------------------------------------------------
* It is a cold boot.
* Perform any processor specific actions upon reset e.g. cache, TLB
* invalidations etc.
* ---------------------------------------------------------------------
*/
bl reset_handler
el2_arch_init_common
.if \_secondary_cold_boot
/* -------------------------------------------------------------
* Check if this is a primary or secondary CPU cold boot.
* The primary CPU will set up the platform while the
* secondaries are placed in a platform-specific state until the
* primary CPU performs the necessary actions to bring them out
* of that state and allows entry into the OS.
* -------------------------------------------------------------
*/
bl plat_is_my_cpu_primary
cbnz w0, do_primary_cold_boot
/* This is a cold boot on a secondary CPU */
bl plat_secondary_cold_boot_setup
/* plat_secondary_cold_boot_setup() is not supposed to return */
bl el2_panic
do_primary_cold_boot:
.endif /* _secondary_cold_boot */
/* ---------------------------------------------------------------------
* Initialize memory now. Secondary CPU initialization won't get to this
* point.
* ---------------------------------------------------------------------
*/
.if \_init_memory
bl platform_mem_init
.endif /* _init_memory */
/* ---------------------------------------------------------------------
* Init C runtime environment:
* - Zero-initialise the NOBITS sections. There are 2 of them:
* - the .bss section;
* - the coherent memory section (if any).
* - Relocate the data section from ROM to RAM, if required.
* ---------------------------------------------------------------------
*/
.if \_init_c_runtime
adrp x0, __BSS_START__
add x0, x0, :lo12:__BSS_START__
adrp x1, __BSS_END__
add x1, x1, :lo12:__BSS_END__
sub x1, x1, x0
bl zeromem
#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM)
adrp x0, __DATA_RAM_START__
add x0, x0, :lo12:__DATA_RAM_START__
adrp x1, __DATA_ROM_START__
add x1, x1, :lo12:__DATA_ROM_START__
adrp x2, __DATA_RAM_END__
add x2, x2, :lo12:__DATA_RAM_END__
sub x2, x2, x0
bl memcpy16
#endif
.endif /* _init_c_runtime */
/* ---------------------------------------------------------------------
* Use SP_EL0 for the C runtime stack.
* ---------------------------------------------------------------------
*/
msr spsel, #0
/* ---------------------------------------------------------------------
* Allocate a stack whose memory will be marked as Normal-IS-WBWA when
* the MMU is enabled. There is no risk of reading stale stack memory
* after enabling the MMU as only the primary CPU is running at the
* moment.
* ---------------------------------------------------------------------
*/
bl plat_set_my_stack
#if STACK_PROTECTOR_ENABLED
.if \_init_c_runtime
bl update_stack_protector_canary
.endif /* _init_c_runtime */
#endif
.endm
.macro apply_at_speculative_wa
#if ERRATA_SPECULATIVE_AT
/*
* Explicitly save x30 so as to free up a register and to enable
* branching and also, save x29 which will be used in the called
* function
*/
stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
bl save_and_update_ptw_el1_sys_regs
ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
#endif
.endm
.macro restore_ptw_el1_sys_regs
#if ERRATA_SPECULATIVE_AT
/* -----------------------------------------------------------
* In case of ERRATA_SPECULATIVE_AT, must follow below order
* to ensure that page table walk is not enabled until
* restoration of all EL1 system registers. TCR_EL1 register
* should be updated at the end which restores previous page
* table walk setting of stage1 i.e.(TCR_EL1.EPDx) bits. ISB
* ensures that CPU does below steps in order.
*
* 1. Ensure all other system registers are written before
* updating SCTLR_EL1 using ISB.
* 2. Restore SCTLR_EL1 register.
* 3. Ensure SCTLR_EL1 written successfully using ISB.
* 4. Restore TCR_EL1 register.
* -----------------------------------------------------------
*/
isb
ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
#endif
.endm
#endif /* EL2_COMMON_MACROS_S */
@@ -0,0 +1,570 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef EL3_COMMON_MACROS_S
#define EL3_COMMON_MACROS_S
#include <arch.h>
#include <asm_macros.S>
#include <assert_macros.S>
#include <context.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
/*
* Helper macro to initialise EL3 registers we care about.
*/
.macro el3_arch_init_common
/* ---------------------------------------------------------------------
* SCTLR_EL3 has already been initialised - read current value before
* modifying.
*
* SCTLR_EL3.I: Enable the instruction cache.
*
* SCTLR_EL3.SA: Enable Stack Alignment check. A SP alignment fault
* exception is generated if a load or store instruction executed at
* EL3 uses the SP as the base address and the SP is not aligned to a
* 16-byte boundary.
*
* SCTLR_EL3.A: Enable Alignment fault checking. All instructions that
* load or store one or more registers have an alignment check that the
* address being accessed is aligned to the size of the data element(s)
* being accessed.
* ---------------------------------------------------------------------
*/
mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
mrs x0, sctlr_el3
orr x0, x0, x1
msr sctlr_el3, x0
isb
#ifdef IMAGE_BL31
/* ---------------------------------------------------------------------
* Initialise the per-cpu cache pointer to the CPU.
* This is done early to enable crash reporting to have access to crash
* stack. Since crash reporting depends on cpu_data to report the
* unhandled exception, not doing so can lead to recursive exceptions
* due to a NULL TPIDR_EL3.
* ---------------------------------------------------------------------
*/
bl init_cpu_data_ptr
#endif /* IMAGE_BL31 */
/* ---------------------------------------------------------------------
* Initialise SCR_EL3, setting all fields rather than relying on hw.
* All fields are architecturally UNKNOWN on reset. The following fields
* do not change during the TF lifetime. The remaining fields are set to
* zero here but are updated ahead of transitioning to a lower EL in the
* function cm_init_context_common().
*
* SCR_EL3.TWE: Set to zero so that execution of WFE instructions at
* EL2, EL1 and EL0 are not trapped to EL3.
*
* SCR_EL3.TWI: Set to zero so that execution of WFI instructions at
* EL2, EL1 and EL0 are not trapped to EL3.
*
* SCR_EL3.SIF: Set to one to disable instruction fetches from
* Non-secure memory.
*
* SCR_EL3.SMD: Set to zero to enable SMC calls at EL1 and above, from
* both Security states and both Execution states.
*
* SCR_EL3.EA: Set to one to route External Aborts and SError Interrupts
* to EL3 when executing at any EL.
*
* SCR_EL3.{API,APK}: For Armv8.3 pointer authentication feature,
* disable traps to EL3 when accessing key registers or using pointer
* authentication instructions from lower ELs.
* ---------------------------------------------------------------------
*/
mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \
& ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT))
#if CTX_INCLUDE_PAUTH_REGS
/*
* If the pointer authentication registers are saved during world
* switches, enable pointer authentication everywhere, as it is safe to
* do so.
*/
orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT)
#endif
#if ENABLE_RME
/*
* TODO: Settting the EEL2 bit to allow EL3 access to secure only registers
* in context management. This will need to be refactored.
*/
orr x0, x0, #SCR_EEL2_BIT
#endif
msr scr_el3, x0
/* ---------------------------------------------------------------------
* Initialise MDCR_EL3, setting all fields rather than relying on hw.
* Some fields are architecturally UNKNOWN on reset.
*
* MDCR_EL3.SDD: Set to one to disable AArch64 Secure self-hosted debug.
* Debug exceptions, other than Breakpoint Instruction exceptions, are
* disabled from all ELs in Secure state.
*
* MDCR_EL3.SPD32: Set to 0b10 to disable AArch32 Secure self-hosted
* privileged debug from S-EL1.
*
* MDCR_EL3.TDOSA: Set to zero so that EL2 and EL2 System register
* access to the powerdown debug registers do not trap to EL3.
*
* MDCR_EL3.TDA: Set to zero to allow EL0, EL1 and EL2 access to the
* debug registers, other than those registers that are controlled by
* MDCR_EL3.TDOSA.
*
* MDCR_EL3.TPM: Set to zero so that EL0, EL1, and EL2 System register
* accesses to all Performance Monitors registers do not trap to EL3.
*
* MDCR_EL3.SCCD: Set to one so that cycle counting by PMCCNTR_EL0 is
* prohibited in Secure state. This bit is RES0 in versions of the
* architecture with FEAT_PMUv3p5 not implemented, setting it to 1
* doesn't have any effect on them.
*
* MDCR_EL3.MCCD: Set to one so that cycle counting by PMCCNTR_EL0 is
* prohibited in EL3. This bit is RES0 in versions of the
* architecture with FEAT_PMUv3p7 not implemented, setting it to 1
* doesn't have any effect on them.
*
* MDCR_EL3.SPME: Set to zero so that event counting by the programmable
* counters PMEVCNTR<n>_EL0 is prohibited in Secure state. If ARMv8.2
* Debug is not implemented this bit does not have any effect on the
* counters unless there is support for the implementation defined
* authentication interface ExternalSecureNoninvasiveDebugEnabled().
*
* MDCR_EL3.NSTB, MDCR_EL3.NSTBE: Set to zero so that Trace Buffer
* owning security state is Secure state. If FEAT_TRBE is implemented,
* accesses to Trace Buffer control registers at EL2 and EL1 in any
* security state generates trap exceptions to EL3.
* If FEAT_TRBE is not implemented, these bits are RES0.
*
* MDCR_EL3.TTRF: Set to one so that access to trace filter control
* registers in non-monitor mode generate EL3 trap exception,
* unless the access generates a higher priority exception when trace
* filter control(FEAT_TRF) is implemented.
* When FEAT_TRF is not implemented, this bit is RES0.
* ---------------------------------------------------------------------
*/
mov_imm x0, ((MDCR_EL3_RESET_VAL | MDCR_SDD_BIT | \
MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \
MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \
MDCR_TDA_BIT | MDCR_TPM_BIT | MDCR_NSTB(MDCR_NSTB_EL1) | \
MDCR_NSTBE | MDCR_TTRF_BIT))
mrs x1, id_aa64dfr0_el1
ubfx x1, x1, #ID_AA64DFR0_TRACEFILT_SHIFT, #ID_AA64DFR0_TRACEFILT_LENGTH
cbz x1, 1f
orr x0, x0, #MDCR_TTRF_BIT
1:
msr mdcr_el3, x0
/* ---------------------------------------------------------------------
* Initialise PMCR_EL0 setting all fields rather than relying
* on hw. Some fields are architecturally UNKNOWN on reset.
*
* PMCR_EL0.LP: Set to one so that event counter overflow, that
* is recorded in PMOVSCLR_EL0[0-30], occurs on the increment
* that changes PMEVCNTR<n>_EL0[63] from 1 to 0, when ARMv8.5-PMU
* is implemented. This bit is RES0 in versions of the architecture
* earlier than ARMv8.5, setting it to 1 doesn't have any effect
* on them.
*
* PMCR_EL0.LC: Set to one so that cycle counter overflow, that
* is recorded in PMOVSCLR_EL0[31], occurs on the increment
* that changes PMCCNTR_EL0[63] from 1 to 0.
*
* PMCR_EL0.DP: Set to one so that the cycle counter,
* PMCCNTR_EL0 does not count when event counting is prohibited.
*
* PMCR_EL0.X: Set to zero to disable export of events.
*
* PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0
* counts on every clock cycle.
* ---------------------------------------------------------------------
*/
mov_imm x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_LP_BIT | \
PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT) & \
~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT))
msr pmcr_el0, x0
/* ---------------------------------------------------------------------
* Enable External Aborts and SError Interrupts now that the exception
* vectors have been setup.
* ---------------------------------------------------------------------
*/
msr daifclr, #DAIF_ABT_BIT
/* ---------------------------------------------------------------------
* Initialise CPTR_EL3, setting all fields rather than relying on hw.
* All fields are architecturally UNKNOWN on reset.
*
* CPTR_EL3.TCPAC: Set to zero so that any accesses to CPACR_EL1,
* CPTR_EL2, CPACR, or HCPTR do not trap to EL3.
*
* CPTR_EL3.TTA: Set to one so that accesses to the trace system
* registers trap to EL3 from all exception levels and security
* states when system register trace is implemented.
* When system register trace is not implemented, this bit is RES0 and
* hence set to zero.
*
* CPTR_EL3.TTA: Set to zero so that System register accesses to the
* trace registers do not trap to EL3.
*
* CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers
* by Advanced SIMD, floating-point or SVE instructions (if implemented)
* do not trap to EL3.
*
* CPTR_EL3.TAM: Set to one so that Activity Monitor access is
* trapped to EL3 by default.
*
* CPTR_EL3.EZ: Set to zero so that all SVE functionality is trapped
* to EL3 by default.
*
* CPTR_EL3.ESM: Set to zero so that all SME functionality is trapped
* to EL3 by default.
*/
mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
mrs x1, id_aa64dfr0_el1
ubfx x1, x1, #ID_AA64DFR0_TRACEVER_SHIFT, #ID_AA64DFR0_TRACEVER_LENGTH
cbz x1, 1f
orr x0, x0, #TTA_BIT
1:
msr cptr_el3, x0
/*
* If Data Independent Timing (DIT) functionality is implemented,
* always enable DIT in EL3.
* First assert that the FEAT_DIT build flag matches the feature id
* register value for DIT.
*/
#if ENABLE_FEAT_DIT
#if ENABLE_ASSERTIONS
mrs x0, id_aa64pfr0_el1
ubfx x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH
cmp x0, #ID_AA64PFR0_DIT_SUPPORTED
ASM_ASSERT(eq)
#endif /* ENABLE_ASSERTIONS */
mov x0, #DIT_BIT
msr DIT, x0
#endif
.endm
/* -----------------------------------------------------------------------------
* This is the super set of actions that need to be performed during a cold boot
* or a warm boot in EL3. This code is shared by BL1 and BL31.
*
* This macro will always perform reset handling, architectural initialisations
* and stack setup. The rest of the actions are optional because they might not
* be needed, depending on the context in which this macro is called. This is
* why this macro is parameterised ; each parameter allows to enable/disable
* some actions.
*
* _init_sctlr:
* Whether the macro needs to initialise SCTLR_EL3, including configuring
* the endianness of data accesses.
*
* _warm_boot_mailbox:
* Whether the macro needs to detect the type of boot (cold/warm). The
* detection is based on the platform entrypoint address : if it is zero
* then it is a cold boot, otherwise it is a warm boot. In the latter case,
* this macro jumps on the platform entrypoint address.
*
* _secondary_cold_boot:
* Whether the macro needs to identify the CPU that is calling it: primary
* CPU or secondary CPU. The primary CPU will be allowed to carry on with
* the platform initialisations, while the secondaries will be put in a
* platform-specific state in the meantime.
*
* If the caller knows this macro will only be called by the primary CPU
* then this parameter can be defined to 0 to skip this step.
*
* _init_memory:
* Whether the macro needs to initialise the memory.
*
* _init_c_runtime:
* Whether the macro needs to initialise the C runtime environment.
*
* _exception_vectors:
* Address of the exception vectors to program in the VBAR_EL3 register.
*
* _pie_fixup_size:
* Size of memory region to fixup Global Descriptor Table (GDT).
*
* A non-zero value is expected when firmware needs GDT to be fixed-up.
*
* -----------------------------------------------------------------------------
*/
.macro el3_entrypoint_common \
_init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \
_init_memory, _init_c_runtime, _exception_vectors, \
_pie_fixup_size
.if \_init_sctlr
/* -------------------------------------------------------------
* This is the initialisation of SCTLR_EL3 and so must ensure
* that all fields are explicitly set rather than relying on hw.
* Some fields reset to an IMPLEMENTATION DEFINED value and
* others are architecturally UNKNOWN on reset.
*
* SCTLR.EE: Set the CPU endianness before doing anything that
* might involve memory reads or writes. Set to zero to select
* Little Endian.
*
* SCTLR_EL3.WXN: For the EL3 translation regime, this field can
* force all memory regions that are writeable to be treated as
* XN (Execute-never). Set to zero so that this control has no
* effect on memory access permissions.
*
* SCTLR_EL3.SA: Set to zero to disable Stack Alignment check.
*
* SCTLR_EL3.A: Set to zero to disable Alignment fault checking.
*
* SCTLR.DSSBS: Set to zero to disable speculation store bypass
* safe behaviour upon exception entry to EL3.
* -------------------------------------------------------------
*/
mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \
| SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT))
msr sctlr_el3, x0
isb
.endif /* _init_sctlr */
#if DISABLE_MTPMU
bl mtpmu_disable
#endif
.if \_warm_boot_mailbox
/* -------------------------------------------------------------
* This code will be executed for both warm and cold resets.
* Now is the time to distinguish between the two.
* Query the platform entrypoint address and if it is not zero
* then it means it is a warm boot so jump to this address.
* -------------------------------------------------------------
*/
bl plat_get_my_entrypoint
cbz x0, do_cold_boot
br x0
do_cold_boot:
.endif /* _warm_boot_mailbox */
.if \_pie_fixup_size
#if ENABLE_PIE
/*
* ------------------------------------------------------------
* If PIE is enabled fixup the Global descriptor Table only
* once during primary core cold boot path.
*
* Compile time base address, required for fixup, is calculated
* using "pie_fixup" label present within first page.
* ------------------------------------------------------------
*/
pie_fixup:
ldr x0, =pie_fixup
and x0, x0, #~(PAGE_SIZE_MASK)
mov_imm x1, \_pie_fixup_size
add x1, x1, x0
bl fixup_gdt_reloc
#endif /* ENABLE_PIE */
.endif /* _pie_fixup_size */
/* ---------------------------------------------------------------------
* Set the exception vectors.
* ---------------------------------------------------------------------
*/
adr x0, \_exception_vectors
msr vbar_el3, x0
isb
#if !(defined(IMAGE_BL2) && ENABLE_RME)
/* ---------------------------------------------------------------------
* It is a cold boot.
* Perform any processor specific actions upon reset e.g. cache, TLB
* invalidations etc.
* ---------------------------------------------------------------------
*/
bl reset_handler
#endif
el3_arch_init_common
.if \_secondary_cold_boot
/* -------------------------------------------------------------
* Check if this is a primary or secondary CPU cold boot.
* The primary CPU will set up the platform while the
* secondaries are placed in a platform-specific state until the
* primary CPU performs the necessary actions to bring them out
* of that state and allows entry into the OS.
* -------------------------------------------------------------
*/
bl plat_is_my_cpu_primary
cbnz w0, do_primary_cold_boot
/* This is a cold boot on a secondary CPU */
bl plat_secondary_cold_boot_setup
/* plat_secondary_cold_boot_setup() is not supposed to return */
bl el3_panic
do_primary_cold_boot:
.endif /* _secondary_cold_boot */
/* ---------------------------------------------------------------------
* Initialize memory now. Secondary CPU initialization won't get to this
* point.
* ---------------------------------------------------------------------
*/
.if \_init_memory
bl platform_mem_init
.endif /* _init_memory */
/* ---------------------------------------------------------------------
* Init C runtime environment:
* - Zero-initialise the NOBITS sections. There are 2 of them:
* - the .bss section;
* - the coherent memory section (if any).
* - Relocate the data section from ROM to RAM, if required.
* ---------------------------------------------------------------------
*/
.if \_init_c_runtime
#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \
((BL2_AT_EL3 && BL2_INV_DCACHE) || ENABLE_RME))
/* -------------------------------------------------------------
* Invalidate the RW memory used by the BL31 image. This
* includes the data and NOBITS sections. This is done to
* safeguard against possible corruption of this memory by
* dirty cache lines in a system cache as a result of use by
* an earlier boot loader stage. If PIE is enabled however,
* RO sections including the GOT may be modified during
* pie fixup. Therefore, to be on the safe side, invalidate
* the entire image region if PIE is enabled.
* -------------------------------------------------------------
*/
#if ENABLE_PIE
#if SEPARATE_CODE_AND_RODATA
adrp x0, __TEXT_START__
add x0, x0, :lo12:__TEXT_START__
#else
adrp x0, __RO_START__
add x0, x0, :lo12:__RO_START__
#endif /* SEPARATE_CODE_AND_RODATA */
#else
adrp x0, __RW_START__
add x0, x0, :lo12:__RW_START__
#endif /* ENABLE_PIE */
adrp x1, __RW_END__
add x1, x1, :lo12:__RW_END__
sub x1, x1, x0
bl inv_dcache_range
#if defined(IMAGE_BL31) && SEPARATE_NOBITS_REGION
adrp x0, __NOBITS_START__
add x0, x0, :lo12:__NOBITS_START__
adrp x1, __NOBITS_END__
add x1, x1, :lo12:__NOBITS_END__
sub x1, x1, x0
bl inv_dcache_range
#endif
#if defined(IMAGE_BL2) && SEPARATE_BL2_NOLOAD_REGION
adrp x0, __BL2_NOLOAD_START__
add x0, x0, :lo12:__BL2_NOLOAD_START__
adrp x1, __BL2_NOLOAD_END__
add x1, x1, :lo12:__BL2_NOLOAD_END__
sub x1, x1, x0
bl inv_dcache_range
#endif
#endif
adrp x0, __BSS_START__
add x0, x0, :lo12:__BSS_START__
adrp x1, __BSS_END__
add x1, x1, :lo12:__BSS_END__
sub x1, x1, x0
bl zeromem
#if USE_COHERENT_MEM
adrp x0, __COHERENT_RAM_START__
add x0, x0, :lo12:__COHERENT_RAM_START__
adrp x1, __COHERENT_RAM_END_UNALIGNED__
add x1, x1, :lo12: __COHERENT_RAM_END_UNALIGNED__
sub x1, x1, x0
bl zeromem
#endif
#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM)
adrp x0, __DATA_RAM_START__
add x0, x0, :lo12:__DATA_RAM_START__
adrp x1, __DATA_ROM_START__
add x1, x1, :lo12:__DATA_ROM_START__
adrp x2, __DATA_RAM_END__
add x2, x2, :lo12:__DATA_RAM_END__
sub x2, x2, x0
bl memcpy16
#endif
.endif /* _init_c_runtime */
/* ---------------------------------------------------------------------
* Use SP_EL0 for the C runtime stack.
* ---------------------------------------------------------------------
*/
msr spsel, #0
/* ---------------------------------------------------------------------
* Allocate a stack whose memory will be marked as Normal-IS-WBWA when
* the MMU is enabled. There is no risk of reading stale stack memory
* after enabling the MMU as only the primary CPU is running at the
* moment.
* ---------------------------------------------------------------------
*/
bl plat_set_my_stack
#if STACK_PROTECTOR_ENABLED
.if \_init_c_runtime
bl update_stack_protector_canary
.endif /* _init_c_runtime */
#endif
.endm
.macro apply_at_speculative_wa
#if ERRATA_SPECULATIVE_AT
/*
* Explicitly save x30 so as to free up a register and to enable
* branching and also, save x29 which will be used in the called
* function
*/
stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
bl save_and_update_ptw_el1_sys_regs
ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
#endif
.endm
.macro restore_ptw_el1_sys_regs
#if ERRATA_SPECULATIVE_AT
/* -----------------------------------------------------------
* In case of ERRATA_SPECULATIVE_AT, must follow below order
* to ensure that page table walk is not enabled until
* restoration of all EL1 system registers. TCR_EL1 register
* should be updated at the end which restores previous page
* table walk setting of stage1 i.e.(TCR_EL1.EPDx) bits. ISB
* ensures that CPU does below steps in order.
*
* 1. Ensure all other system registers are written before
* updating SCTLR_EL1 using ISB.
* 2. Restore SCTLR_EL1 register.
* 3. Ensure SCTLR_EL1 written successfully using ISB.
* 4. Restore TCR_EL1 register.
* -----------------------------------------------------------
*/
isb
ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
#endif
.endm
#endif /* EL3_COMMON_MACROS_S */
@@ -0,0 +1,144 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SMCCC_HELPERS_H
#define SMCCC_HELPERS_H
#include <lib/smccc.h>
/* Definitions to help the assembler access the SMC/ERET args structure */
#define SMC_ARGS_SIZE 0x40
#define SMC_ARG0 0x0
#define SMC_ARG1 0x8
#define SMC_ARG2 0x10
#define SMC_ARG3 0x18
#define SMC_ARG4 0x20
#define SMC_ARG5 0x28
#define SMC_ARG6 0x30
#define SMC_ARG7 0x38
#define SMC_ARGS_END 0x40
#ifndef __ASSEMBLER__
#include <stdbool.h>
#include <context.h>
#include <platform_def.h> /* For CACHE_WRITEBACK_GRANULE */
/* Convenience macros to return from SMC handler */
#define SMC_RET0(_h) { \
return (uint64_t) (_h); \
}
#define SMC_RET1(_h, _x0) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X0), (_x0)); \
SMC_RET0(_h); \
}
#define SMC_RET2(_h, _x0, _x1) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X1), (_x1)); \
SMC_RET1(_h, (_x0)); \
}
#define SMC_RET3(_h, _x0, _x1, _x2) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X2), (_x2)); \
SMC_RET2(_h, (_x0), (_x1)); \
}
#define SMC_RET4(_h, _x0, _x1, _x2, _x3) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X3), (_x3)); \
SMC_RET3(_h, (_x0), (_x1), (_x2)); \
}
#define SMC_RET5(_h, _x0, _x1, _x2, _x3, _x4) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X4), (_x4)); \
SMC_RET4(_h, (_x0), (_x1), (_x2), (_x3)); \
}
#define SMC_RET6(_h, _x0, _x1, _x2, _x3, _x4, _x5) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X5), (_x5)); \
SMC_RET5(_h, (_x0), (_x1), (_x2), (_x3), (_x4)); \
}
#define SMC_RET7(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X6), (_x6)); \
SMC_RET6(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5)); \
}
#define SMC_RET8(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7) { \
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X7), (_x7)); \
SMC_RET7(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5), (_x6)); \
}
/*
* Convenience macros to access general purpose registers using handle provided
* to SMC handler. These take the offset values defined in context.h
*/
#define SMC_GET_GP(_h, _g) \
read_ctx_reg((get_gpregs_ctx(_h)), (_g))
#define SMC_SET_GP(_h, _g, _v) \
write_ctx_reg((get_gpregs_ctx(_h)), (_g), (_v))
/*
* Convenience macros to access EL3 context registers using handle provided to
* SMC handler. These take the offset values defined in context.h
*/
#define SMC_GET_EL3(_h, _e) \
read_ctx_reg((get_el3state_ctx(_h)), (_e))
#define SMC_SET_EL3(_h, _e, _v) \
write_ctx_reg((get_el3state_ctx(_h)), (_e), (_v))
/*
* Helper macro to retrieve the SMC parameters from cpu_context_t.
*/
#define get_smc_params_from_ctx(_hdl, _x1, _x2, _x3, _x4) \
do { \
const gp_regs_t *regs = get_gpregs_ctx(_hdl); \
_x1 = read_ctx_reg(regs, CTX_GPREG_X1); \
_x2 = read_ctx_reg(regs, CTX_GPREG_X2); \
_x3 = read_ctx_reg(regs, CTX_GPREG_X3); \
_x4 = read_ctx_reg(regs, CTX_GPREG_X4); \
} while (false)
typedef struct {
uint64_t _regs[SMC_ARGS_END >> 3];
} __aligned(CACHE_WRITEBACK_GRANULE) smc_args_t;
/*
* Ensure that the assembler's view of the size of the tsp_args is the
* same as the compilers.
*/
CASSERT(sizeof(smc_args_t) == SMC_ARGS_SIZE, assert_sp_args_size_mismatch);
static inline smc_args_t smc_helper(uint32_t func, uint64_t arg0,
uint64_t arg1, uint64_t arg2,
uint64_t arg3, uint64_t arg4,
uint64_t arg5, uint64_t arg6)
{
smc_args_t ret_args = {0};
register uint64_t r0 __asm__("x0") = func;
register uint64_t r1 __asm__("x1") = arg0;
register uint64_t r2 __asm__("x2") = arg1;
register uint64_t r3 __asm__("x3") = arg2;
register uint64_t r4 __asm__("x4") = arg3;
register uint64_t r5 __asm__("x5") = arg4;
register uint64_t r6 __asm__("x6") = arg5;
register uint64_t r7 __asm__("x7") = arg6;
/* Output registers, also used as inputs ('+' constraint). */
__asm__ volatile("smc #0"
: "+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3), "+r"(r4),
"+r"(r5), "+r"(r6), "+r"(r7));
ret_args._regs[0] = r0;
ret_args._regs[1] = r1;
ret_args._regs[2] = r2;
ret_args._regs[3] = r3;
ret_args._regs[4] = r4;
ret_args._regs[5] = r5;
ret_args._regs[6] = r6;
ret_args._regs[7] = r7;
return ret_args;
}
#endif /*__ASSEMBLER__*/
#endif /* SMCCC_HELPERS_H */