GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,786 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2023, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef ARCH_H
|
||||
#define ARCH_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* MIDR bit definitions
|
||||
******************************************************************************/
|
||||
#define MIDR_IMPL_MASK U(0xff)
|
||||
#define MIDR_IMPL_SHIFT U(24)
|
||||
#define MIDR_VAR_SHIFT U(20)
|
||||
#define MIDR_VAR_BITS U(4)
|
||||
#define MIDR_VAR_MASK U(0xf)
|
||||
#define MIDR_REV_SHIFT U(0)
|
||||
#define MIDR_REV_BITS U(4)
|
||||
#define MIDR_REV_MASK U(0xf)
|
||||
#define MIDR_PN_MASK U(0xfff)
|
||||
#define MIDR_PN_SHIFT U(4)
|
||||
|
||||
/*******************************************************************************
|
||||
* MPIDR macros
|
||||
******************************************************************************/
|
||||
#define MPIDR_MT_MASK (U(1) << 24)
|
||||
#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK
|
||||
#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS)
|
||||
#define MPIDR_AFFINITY_BITS U(8)
|
||||
#define MPIDR_AFFLVL_MASK U(0xff)
|
||||
#define MPIDR_AFFLVL_SHIFT U(3)
|
||||
#define MPIDR_AFF0_SHIFT U(0)
|
||||
#define MPIDR_AFF1_SHIFT U(8)
|
||||
#define MPIDR_AFF2_SHIFT U(16)
|
||||
#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT
|
||||
#define MPIDR_AFFINITY_MASK U(0x00ffffff)
|
||||
#define MPIDR_AFFLVL0 U(0)
|
||||
#define MPIDR_AFFLVL1 U(1)
|
||||
#define MPIDR_AFFLVL2 U(2)
|
||||
#define MPIDR_AFFLVL(_n) MPIDR_AFFLVL##_n
|
||||
|
||||
#define MPIDR_AFFLVL0_VAL(mpidr) \
|
||||
(((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK)
|
||||
#define MPIDR_AFFLVL1_VAL(mpidr) \
|
||||
(((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK)
|
||||
#define MPIDR_AFFLVL2_VAL(mpidr) \
|
||||
(((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK)
|
||||
#define MPIDR_AFFLVL3_VAL(mpidr) U(0)
|
||||
|
||||
#define MPIDR_AFF_ID(mpid, n) \
|
||||
(((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK)
|
||||
|
||||
#define MPID_MASK (MPIDR_MT_MASK |\
|
||||
(MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT)|\
|
||||
(MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT)|\
|
||||
(MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT))
|
||||
|
||||
/*
|
||||
* An invalid MPID. This value can be used by functions that return an MPID to
|
||||
* indicate an error.
|
||||
*/
|
||||
#define INVALID_MPID U(0xFFFFFFFF)
|
||||
|
||||
/*
|
||||
* The MPIDR_MAX_AFFLVL count starts from 0. Take care to
|
||||
* add one while using this macro to define array sizes.
|
||||
*/
|
||||
#define MPIDR_MAX_AFFLVL U(2)
|
||||
|
||||
/* Data Cache set/way op type defines */
|
||||
#define DC_OP_ISW U(0x0)
|
||||
#define DC_OP_CISW U(0x1)
|
||||
#if ERRATA_A53_827319
|
||||
#define DC_OP_CSW DC_OP_CISW
|
||||
#else
|
||||
#define DC_OP_CSW U(0x2)
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Generic timer memory mapped registers & offsets
|
||||
******************************************************************************/
|
||||
#define CNTCR_OFF U(0x000)
|
||||
/* Counter Count Value Lower register */
|
||||
#define CNTCVL_OFF U(0x008)
|
||||
/* Counter Count Value Upper register */
|
||||
#define CNTCVU_OFF U(0x00C)
|
||||
#define CNTFID_OFF U(0x020)
|
||||
|
||||
#define CNTCR_EN (U(1) << 0)
|
||||
#define CNTCR_HDBG (U(1) << 1)
|
||||
#define CNTCR_FCREQ(x) ((x) << 8)
|
||||
|
||||
/*******************************************************************************
|
||||
* System register bit definitions
|
||||
******************************************************************************/
|
||||
/* CLIDR definitions */
|
||||
#define LOUIS_SHIFT U(21)
|
||||
#define LOC_SHIFT U(24)
|
||||
#define CLIDR_FIELD_WIDTH U(3)
|
||||
|
||||
/* CSSELR definitions */
|
||||
#define LEVEL_SHIFT U(1)
|
||||
|
||||
/* ID_DFR0_EL1 definitions */
|
||||
#define ID_DFR0_COPTRC_SHIFT U(12)
|
||||
#define ID_DFR0_COPTRC_MASK U(0xf)
|
||||
#define ID_DFR0_COPTRC_SUPPORTED U(1)
|
||||
#define ID_DFR0_COPTRC_LENGTH U(4)
|
||||
#define ID_DFR0_TRACEFILT_SHIFT U(28)
|
||||
#define ID_DFR0_TRACEFILT_MASK U(0xf)
|
||||
#define ID_DFR0_TRACEFILT_SUPPORTED U(1)
|
||||
#define ID_DFR0_TRACEFILT_LENGTH U(4)
|
||||
|
||||
/* ID_DFR1_EL1 definitions */
|
||||
#define ID_DFR1_MTPMU_SHIFT U(0)
|
||||
#define ID_DFR1_MTPMU_MASK U(0xf)
|
||||
#define ID_DFR1_MTPMU_SUPPORTED U(1)
|
||||
|
||||
/* ID_MMFR4 definitions */
|
||||
#define ID_MMFR4_CNP_SHIFT U(12)
|
||||
#define ID_MMFR4_CNP_LENGTH U(4)
|
||||
#define ID_MMFR4_CNP_MASK U(0xf)
|
||||
|
||||
#define ID_MMFR4_CCIDX_SHIFT U(24)
|
||||
#define ID_MMFR4_CCIDX_LENGTH U(4)
|
||||
#define ID_MMFR4_CCIDX_MASK U(0xf)
|
||||
|
||||
/* ID_PFR0 definitions */
|
||||
#define ID_PFR0_AMU_SHIFT U(20)
|
||||
#define ID_PFR0_AMU_LENGTH U(4)
|
||||
#define ID_PFR0_AMU_MASK U(0xf)
|
||||
#define ID_PFR0_AMU_NOT_SUPPORTED U(0x0)
|
||||
#define ID_PFR0_AMU_V1 U(0x1)
|
||||
#define ID_PFR0_AMU_V1P1 U(0x2)
|
||||
|
||||
#define ID_PFR0_DIT_SHIFT U(24)
|
||||
#define ID_PFR0_DIT_LENGTH U(4)
|
||||
#define ID_PFR0_DIT_MASK U(0xf)
|
||||
#define ID_PFR0_DIT_SUPPORTED (U(1) << ID_PFR0_DIT_SHIFT)
|
||||
|
||||
/* ID_PFR1 definitions */
|
||||
#define ID_PFR1_VIRTEXT_SHIFT U(12)
|
||||
#define ID_PFR1_VIRTEXT_MASK U(0xf)
|
||||
#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \
|
||||
& ID_PFR1_VIRTEXT_MASK)
|
||||
#define ID_PFR1_GENTIMER_SHIFT U(16)
|
||||
#define ID_PFR1_GENTIMER_MASK U(0xf)
|
||||
#define ID_PFR1_GIC_SHIFT U(28)
|
||||
#define ID_PFR1_GIC_MASK U(0xf)
|
||||
#define ID_PFR1_SEC_SHIFT U(4)
|
||||
#define ID_PFR1_SEC_MASK U(0xf)
|
||||
#define ID_PFR1_ELx_ENABLED U(1)
|
||||
|
||||
/* SCTLR definitions */
|
||||
#define SCTLR_RES1_DEF ((U(1) << 23) | (U(1) << 22) | (U(1) << 4) | \
|
||||
(U(1) << 3))
|
||||
#if ARM_ARCH_MAJOR == 7
|
||||
#define SCTLR_RES1 SCTLR_RES1_DEF
|
||||
#else
|
||||
#define SCTLR_RES1 (SCTLR_RES1_DEF | (U(1) << 11))
|
||||
#endif
|
||||
#define SCTLR_M_BIT (U(1) << 0)
|
||||
#define SCTLR_A_BIT (U(1) << 1)
|
||||
#define SCTLR_C_BIT (U(1) << 2)
|
||||
#define SCTLR_CP15BEN_BIT (U(1) << 5)
|
||||
#define SCTLR_ITD_BIT (U(1) << 7)
|
||||
#define SCTLR_Z_BIT (U(1) << 11)
|
||||
#define SCTLR_I_BIT (U(1) << 12)
|
||||
#define SCTLR_V_BIT (U(1) << 13)
|
||||
#define SCTLR_RR_BIT (U(1) << 14)
|
||||
#define SCTLR_NTWI_BIT (U(1) << 16)
|
||||
#define SCTLR_NTWE_BIT (U(1) << 18)
|
||||
#define SCTLR_WXN_BIT (U(1) << 19)
|
||||
#define SCTLR_UWXN_BIT (U(1) << 20)
|
||||
#define SCTLR_EE_BIT (U(1) << 25)
|
||||
#define SCTLR_TRE_BIT (U(1) << 28)
|
||||
#define SCTLR_AFE_BIT (U(1) << 29)
|
||||
#define SCTLR_TE_BIT (U(1) << 30)
|
||||
#define SCTLR_DSSBS_BIT (U(1) << 31)
|
||||
#define SCTLR_RESET_VAL (SCTLR_RES1 | SCTLR_NTWE_BIT | \
|
||||
SCTLR_NTWI_BIT | SCTLR_CP15BEN_BIT)
|
||||
|
||||
/* SDCR definitions */
|
||||
#define SDCR_SPD(x) ((x) << 14)
|
||||
#define SDCR_SPD_LEGACY U(0x0)
|
||||
#define SDCR_SPD_DISABLE U(0x2)
|
||||
#define SDCR_SPD_ENABLE U(0x3)
|
||||
#define SDCR_SCCD_BIT (U(1) << 23)
|
||||
#define SDCR_TTRF_BIT (U(1) << 19)
|
||||
#define SDCR_SPME_BIT (U(1) << 17)
|
||||
#define SDCR_RESET_VAL U(0x0)
|
||||
#define SDCR_MTPME_BIT (U(1) << 28)
|
||||
|
||||
/* HSCTLR definitions */
|
||||
#define HSCTLR_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \
|
||||
(U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \
|
||||
(U(1) << 11) | (U(1) << 4) | (U(1) << 3))
|
||||
|
||||
#define HSCTLR_M_BIT (U(1) << 0)
|
||||
#define HSCTLR_A_BIT (U(1) << 1)
|
||||
#define HSCTLR_C_BIT (U(1) << 2)
|
||||
#define HSCTLR_CP15BEN_BIT (U(1) << 5)
|
||||
#define HSCTLR_ITD_BIT (U(1) << 7)
|
||||
#define HSCTLR_SED_BIT (U(1) << 8)
|
||||
#define HSCTLR_I_BIT (U(1) << 12)
|
||||
#define HSCTLR_WXN_BIT (U(1) << 19)
|
||||
#define HSCTLR_EE_BIT (U(1) << 25)
|
||||
#define HSCTLR_TE_BIT (U(1) << 30)
|
||||
|
||||
/* CPACR definitions */
|
||||
#define CPACR_FPEN(x) ((x) << 20)
|
||||
#define CPACR_FP_TRAP_PL0 UL(0x1)
|
||||
#define CPACR_FP_TRAP_ALL UL(0x2)
|
||||
#define CPACR_FP_TRAP_NONE UL(0x3)
|
||||
|
||||
/* SCR definitions */
|
||||
#define SCR_TWE_BIT (UL(1) << 13)
|
||||
#define SCR_TWI_BIT (UL(1) << 12)
|
||||
#define SCR_SIF_BIT (UL(1) << 9)
|
||||
#define SCR_HCE_BIT (UL(1) << 8)
|
||||
#define SCR_SCD_BIT (UL(1) << 7)
|
||||
#define SCR_NET_BIT (UL(1) << 6)
|
||||
#define SCR_AW_BIT (UL(1) << 5)
|
||||
#define SCR_FW_BIT (UL(1) << 4)
|
||||
#define SCR_EA_BIT (UL(1) << 3)
|
||||
#define SCR_FIQ_BIT (UL(1) << 2)
|
||||
#define SCR_IRQ_BIT (UL(1) << 1)
|
||||
#define SCR_NS_BIT (UL(1) << 0)
|
||||
#define SCR_VALID_BIT_MASK U(0x33ff)
|
||||
#define SCR_RESET_VAL U(0x0)
|
||||
|
||||
#define GET_NS_BIT(scr) ((scr) & SCR_NS_BIT)
|
||||
|
||||
/* HCR definitions */
|
||||
#define HCR_TGE_BIT (U(1) << 27)
|
||||
#define HCR_AMO_BIT (U(1) << 5)
|
||||
#define HCR_IMO_BIT (U(1) << 4)
|
||||
#define HCR_FMO_BIT (U(1) << 3)
|
||||
#define HCR_RESET_VAL U(0x0)
|
||||
|
||||
/* CNTHCTL definitions */
|
||||
#define CNTHCTL_RESET_VAL U(0x0)
|
||||
#define PL1PCEN_BIT (U(1) << 1)
|
||||
#define PL1PCTEN_BIT (U(1) << 0)
|
||||
|
||||
/* CNTKCTL definitions */
|
||||
#define PL0PTEN_BIT (U(1) << 9)
|
||||
#define PL0VTEN_BIT (U(1) << 8)
|
||||
#define PL0PCTEN_BIT (U(1) << 0)
|
||||
#define PL0VCTEN_BIT (U(1) << 1)
|
||||
#define EVNTEN_BIT (U(1) << 2)
|
||||
#define EVNTDIR_BIT (U(1) << 3)
|
||||
#define EVNTI_SHIFT U(4)
|
||||
#define EVNTI_MASK U(0xf)
|
||||
|
||||
/* HCPTR definitions */
|
||||
#define HCPTR_RES1 ((U(1) << 13) | (U(1) << 12) | U(0x3ff))
|
||||
#define TCPAC_BIT (U(1) << 31)
|
||||
#define TAM_SHIFT U(30)
|
||||
#define TAM_BIT (U(1) << TAM_SHIFT)
|
||||
#define TTA_BIT (U(1) << 20)
|
||||
#define TCP11_BIT (U(1) << 11)
|
||||
#define TCP10_BIT (U(1) << 10)
|
||||
#define HCPTR_RESET_VAL HCPTR_RES1
|
||||
|
||||
/* VTTBR defintions */
|
||||
#define VTTBR_RESET_VAL ULL(0x0)
|
||||
#define VTTBR_VMID_MASK ULL(0xff)
|
||||
#define VTTBR_VMID_SHIFT U(48)
|
||||
#define VTTBR_BADDR_MASK ULL(0xffffffffffff)
|
||||
#define VTTBR_BADDR_SHIFT U(0)
|
||||
|
||||
/* HDCR definitions */
|
||||
#define HDCR_MTPME_BIT (U(1) << 28)
|
||||
#define HDCR_HLP_BIT (U(1) << 26)
|
||||
#define HDCR_HPME_BIT (U(1) << 7)
|
||||
#define HDCR_RESET_VAL U(0x0)
|
||||
|
||||
/* HSTR definitions */
|
||||
#define HSTR_RESET_VAL U(0x0)
|
||||
|
||||
/* CNTHP_CTL definitions */
|
||||
#define CNTHP_CTL_RESET_VAL U(0x0)
|
||||
|
||||
/* NSACR definitions */
|
||||
#define NSASEDIS_BIT (U(1) << 15)
|
||||
#define NSTRCDIS_BIT (U(1) << 20)
|
||||
#define NSACR_CP11_BIT (U(1) << 11)
|
||||
#define NSACR_CP10_BIT (U(1) << 10)
|
||||
#define NSACR_IMP_DEF_MASK (U(0x7) << 16)
|
||||
#define NSACR_ENABLE_FP_ACCESS (NSACR_CP11_BIT | NSACR_CP10_BIT)
|
||||
#define NSACR_RESET_VAL U(0x0)
|
||||
|
||||
/* CPACR definitions */
|
||||
#define ASEDIS_BIT (U(1) << 31)
|
||||
#define TRCDIS_BIT (U(1) << 28)
|
||||
#define CPACR_CP11_SHIFT U(22)
|
||||
#define CPACR_CP10_SHIFT U(20)
|
||||
#define CPACR_ENABLE_FP_ACCESS ((U(0x3) << CPACR_CP11_SHIFT) |\
|
||||
(U(0x3) << CPACR_CP10_SHIFT))
|
||||
#define CPACR_RESET_VAL U(0x0)
|
||||
|
||||
/* FPEXC definitions */
|
||||
#define FPEXC_RES1 ((U(1) << 10) | (U(1) << 9) | (U(1) << 8))
|
||||
#define FPEXC_EN_BIT (U(1) << 30)
|
||||
#define FPEXC_RESET_VAL FPEXC_RES1
|
||||
|
||||
/* SPSR/CPSR definitions */
|
||||
#define SPSR_FIQ_BIT (U(1) << 0)
|
||||
#define SPSR_IRQ_BIT (U(1) << 1)
|
||||
#define SPSR_ABT_BIT (U(1) << 2)
|
||||
#define SPSR_AIF_SHIFT U(6)
|
||||
#define SPSR_AIF_MASK U(0x7)
|
||||
|
||||
#define SPSR_E_SHIFT U(9)
|
||||
#define SPSR_E_MASK U(0x1)
|
||||
#define SPSR_E_LITTLE U(0)
|
||||
#define SPSR_E_BIG U(1)
|
||||
|
||||
#define SPSR_T_SHIFT U(5)
|
||||
#define SPSR_T_MASK U(0x1)
|
||||
#define SPSR_T_ARM U(0)
|
||||
#define SPSR_T_THUMB U(1)
|
||||
|
||||
#define SPSR_MODE_SHIFT U(0)
|
||||
#define SPSR_MODE_MASK U(0x7)
|
||||
|
||||
#define SPSR_SSBS_BIT BIT_32(23)
|
||||
|
||||
#define DISABLE_ALL_EXCEPTIONS \
|
||||
(SPSR_FIQ_BIT | SPSR_IRQ_BIT | SPSR_ABT_BIT)
|
||||
|
||||
#define CPSR_DIT_BIT (U(1) << 21)
|
||||
/*
|
||||
* TTBCR definitions
|
||||
*/
|
||||
#define TTBCR_EAE_BIT (U(1) << 31)
|
||||
|
||||
#define TTBCR_SH1_NON_SHAREABLE (U(0x0) << 28)
|
||||
#define TTBCR_SH1_OUTER_SHAREABLE (U(0x2) << 28)
|
||||
#define TTBCR_SH1_INNER_SHAREABLE (U(0x3) << 28)
|
||||
|
||||
#define TTBCR_RGN1_OUTER_NC (U(0x0) << 26)
|
||||
#define TTBCR_RGN1_OUTER_WBA (U(0x1) << 26)
|
||||
#define TTBCR_RGN1_OUTER_WT (U(0x2) << 26)
|
||||
#define TTBCR_RGN1_OUTER_WBNA (U(0x3) << 26)
|
||||
|
||||
#define TTBCR_RGN1_INNER_NC (U(0x0) << 24)
|
||||
#define TTBCR_RGN1_INNER_WBA (U(0x1) << 24)
|
||||
#define TTBCR_RGN1_INNER_WT (U(0x2) << 24)
|
||||
#define TTBCR_RGN1_INNER_WBNA (U(0x3) << 24)
|
||||
|
||||
#define TTBCR_EPD1_BIT (U(1) << 23)
|
||||
#define TTBCR_A1_BIT (U(1) << 22)
|
||||
|
||||
#define TTBCR_T1SZ_SHIFT U(16)
|
||||
#define TTBCR_T1SZ_MASK U(0x7)
|
||||
#define TTBCR_TxSZ_MIN U(0)
|
||||
#define TTBCR_TxSZ_MAX U(7)
|
||||
|
||||
#define TTBCR_SH0_NON_SHAREABLE (U(0x0) << 12)
|
||||
#define TTBCR_SH0_OUTER_SHAREABLE (U(0x2) << 12)
|
||||
#define TTBCR_SH0_INNER_SHAREABLE (U(0x3) << 12)
|
||||
|
||||
#define TTBCR_RGN0_OUTER_NC (U(0x0) << 10)
|
||||
#define TTBCR_RGN0_OUTER_WBA (U(0x1) << 10)
|
||||
#define TTBCR_RGN0_OUTER_WT (U(0x2) << 10)
|
||||
#define TTBCR_RGN0_OUTER_WBNA (U(0x3) << 10)
|
||||
|
||||
#define TTBCR_RGN0_INNER_NC (U(0x0) << 8)
|
||||
#define TTBCR_RGN0_INNER_WBA (U(0x1) << 8)
|
||||
#define TTBCR_RGN0_INNER_WT (U(0x2) << 8)
|
||||
#define TTBCR_RGN0_INNER_WBNA (U(0x3) << 8)
|
||||
|
||||
#define TTBCR_EPD0_BIT (U(1) << 7)
|
||||
#define TTBCR_T0SZ_SHIFT U(0)
|
||||
#define TTBCR_T0SZ_MASK U(0x7)
|
||||
|
||||
/*
|
||||
* HTCR definitions
|
||||
*/
|
||||
#define HTCR_RES1 ((U(1) << 31) | (U(1) << 23))
|
||||
|
||||
#define HTCR_SH0_NON_SHAREABLE (U(0x0) << 12)
|
||||
#define HTCR_SH0_OUTER_SHAREABLE (U(0x2) << 12)
|
||||
#define HTCR_SH0_INNER_SHAREABLE (U(0x3) << 12)
|
||||
|
||||
#define HTCR_RGN0_OUTER_NC (U(0x0) << 10)
|
||||
#define HTCR_RGN0_OUTER_WBA (U(0x1) << 10)
|
||||
#define HTCR_RGN0_OUTER_WT (U(0x2) << 10)
|
||||
#define HTCR_RGN0_OUTER_WBNA (U(0x3) << 10)
|
||||
|
||||
#define HTCR_RGN0_INNER_NC (U(0x0) << 8)
|
||||
#define HTCR_RGN0_INNER_WBA (U(0x1) << 8)
|
||||
#define HTCR_RGN0_INNER_WT (U(0x2) << 8)
|
||||
#define HTCR_RGN0_INNER_WBNA (U(0x3) << 8)
|
||||
|
||||
#define HTCR_T0SZ_SHIFT U(0)
|
||||
#define HTCR_T0SZ_MASK U(0x7)
|
||||
|
||||
#define MODE_RW_SHIFT U(0x4)
|
||||
#define MODE_RW_MASK U(0x1)
|
||||
#define MODE_RW_32 U(0x1)
|
||||
|
||||
#define MODE32_SHIFT U(0)
|
||||
#define MODE32_MASK U(0x1f)
|
||||
#define MODE32_usr U(0x10)
|
||||
#define MODE32_fiq U(0x11)
|
||||
#define MODE32_irq U(0x12)
|
||||
#define MODE32_svc U(0x13)
|
||||
#define MODE32_mon U(0x16)
|
||||
#define MODE32_abt U(0x17)
|
||||
#define MODE32_hyp U(0x1a)
|
||||
#define MODE32_und U(0x1b)
|
||||
#define MODE32_sys U(0x1f)
|
||||
|
||||
#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK)
|
||||
|
||||
#define SPSR_MODE32(mode, isa, endian, aif) \
|
||||
( \
|
||||
( \
|
||||
(MODE_RW_32 << MODE_RW_SHIFT) | \
|
||||
(((mode) & MODE32_MASK) << MODE32_SHIFT) | \
|
||||
(((isa) & SPSR_T_MASK) << SPSR_T_SHIFT) | \
|
||||
(((endian) & SPSR_E_MASK) << SPSR_E_SHIFT) | \
|
||||
(((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT) \
|
||||
) & \
|
||||
(~(SPSR_SSBS_BIT)) \
|
||||
)
|
||||
|
||||
/*
|
||||
* TTBR definitions
|
||||
*/
|
||||
#define TTBR_CNP_BIT ULL(0x1)
|
||||
|
||||
/*
|
||||
* CTR definitions
|
||||
*/
|
||||
#define CTR_CWG_SHIFT U(24)
|
||||
#define CTR_CWG_MASK U(0xf)
|
||||
#define CTR_ERG_SHIFT U(20)
|
||||
#define CTR_ERG_MASK U(0xf)
|
||||
#define CTR_DMINLINE_SHIFT U(16)
|
||||
#define CTR_DMINLINE_WIDTH U(4)
|
||||
#define CTR_DMINLINE_MASK ((U(1) << 4) - U(1))
|
||||
#define CTR_L1IP_SHIFT U(14)
|
||||
#define CTR_L1IP_MASK U(0x3)
|
||||
#define CTR_IMINLINE_SHIFT U(0)
|
||||
#define CTR_IMINLINE_MASK U(0xf)
|
||||
|
||||
#define MAX_CACHE_LINE_SIZE U(0x800) /* 2KB */
|
||||
|
||||
/* PMCR definitions */
|
||||
#define PMCR_N_SHIFT U(11)
|
||||
#define PMCR_N_MASK U(0x1f)
|
||||
#define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT)
|
||||
#define PMCR_LP_BIT (U(1) << 7)
|
||||
#define PMCR_LC_BIT (U(1) << 6)
|
||||
#define PMCR_DP_BIT (U(1) << 5)
|
||||
#define PMCR_RESET_VAL U(0x0)
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions of register offsets, fields and macros for CPU system
|
||||
* instructions.
|
||||
******************************************************************************/
|
||||
|
||||
#define TLBI_ADDR_SHIFT U(0)
|
||||
#define TLBI_ADDR_MASK U(0xFFFFF000)
|
||||
#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK)
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions of register offsets and fields in the CNTCTLBase Frame of the
|
||||
* system level implementation of the Generic Timer.
|
||||
******************************************************************************/
|
||||
#define CNTCTLBASE_CNTFRQ U(0x0)
|
||||
#define CNTNSAR U(0x4)
|
||||
#define CNTNSAR_NS_SHIFT(x) (x)
|
||||
|
||||
#define CNTACR_BASE(x) (U(0x40) + ((x) << 2))
|
||||
#define CNTACR_RPCT_SHIFT U(0x0)
|
||||
#define CNTACR_RVCT_SHIFT U(0x1)
|
||||
#define CNTACR_RFRQ_SHIFT U(0x2)
|
||||
#define CNTACR_RVOFF_SHIFT U(0x3)
|
||||
#define CNTACR_RWVT_SHIFT U(0x4)
|
||||
#define CNTACR_RWPT_SHIFT U(0x5)
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions of register offsets and fields in the CNTBaseN Frame of the
|
||||
* system level implementation of the Generic Timer.
|
||||
******************************************************************************/
|
||||
/* Physical Count register. */
|
||||
#define CNTPCT_LO U(0x0)
|
||||
/* Counter Frequency register. */
|
||||
#define CNTBASEN_CNTFRQ U(0x10)
|
||||
/* Physical Timer CompareValue register. */
|
||||
#define CNTP_CVAL_LO U(0x20)
|
||||
/* Physical Timer Control register. */
|
||||
#define CNTP_CTL U(0x2c)
|
||||
|
||||
/* Physical timer control register bit fields shifts and masks */
|
||||
#define CNTP_CTL_ENABLE_SHIFT 0
|
||||
#define CNTP_CTL_IMASK_SHIFT 1
|
||||
#define CNTP_CTL_ISTATUS_SHIFT 2
|
||||
|
||||
#define CNTP_CTL_ENABLE_MASK U(1)
|
||||
#define CNTP_CTL_IMASK_MASK U(1)
|
||||
#define CNTP_CTL_ISTATUS_MASK U(1)
|
||||
|
||||
/* MAIR macros */
|
||||
#define MAIR0_ATTR_SET(attr, index) ((attr) << ((index) << U(3)))
|
||||
#define MAIR1_ATTR_SET(attr, index) ((attr) << (((index) - U(3)) << U(3)))
|
||||
|
||||
/* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */
|
||||
#define SCR p15, 0, c1, c1, 0
|
||||
#define SCTLR p15, 0, c1, c0, 0
|
||||
#define ACTLR p15, 0, c1, c0, 1
|
||||
#define SDCR p15, 0, c1, c3, 1
|
||||
#define MPIDR p15, 0, c0, c0, 5
|
||||
#define MIDR p15, 0, c0, c0, 0
|
||||
#define HVBAR p15, 4, c12, c0, 0
|
||||
#define VBAR p15, 0, c12, c0, 0
|
||||
#define MVBAR p15, 0, c12, c0, 1
|
||||
#define NSACR p15, 0, c1, c1, 2
|
||||
#define CPACR p15, 0, c1, c0, 2
|
||||
#define DCCIMVAC p15, 0, c7, c14, 1
|
||||
#define DCCMVAC p15, 0, c7, c10, 1
|
||||
#define DCIMVAC p15, 0, c7, c6, 1
|
||||
#define DCCISW p15, 0, c7, c14, 2
|
||||
#define DCCSW p15, 0, c7, c10, 2
|
||||
#define DCISW p15, 0, c7, c6, 2
|
||||
#define CTR p15, 0, c0, c0, 1
|
||||
#define CNTFRQ p15, 0, c14, c0, 0
|
||||
#define ID_MMFR4 p15, 0, c0, c2, 6
|
||||
#define ID_DFR0 p15, 0, c0, c1, 2
|
||||
#define ID_DFR1 p15, 0, c0, c3, 5
|
||||
#define ID_PFR0 p15, 0, c0, c1, 0
|
||||
#define ID_PFR1 p15, 0, c0, c1, 1
|
||||
#define MAIR0 p15, 0, c10, c2, 0
|
||||
#define MAIR1 p15, 0, c10, c2, 1
|
||||
#define TTBCR p15, 0, c2, c0, 2
|
||||
#define TTBR0 p15, 0, c2, c0, 0
|
||||
#define TTBR1 p15, 0, c2, c0, 1
|
||||
#define TLBIALL p15, 0, c8, c7, 0
|
||||
#define TLBIALLH p15, 4, c8, c7, 0
|
||||
#define TLBIALLIS p15, 0, c8, c3, 0
|
||||
#define TLBIMVA p15, 0, c8, c7, 1
|
||||
#define TLBIMVAA p15, 0, c8, c7, 3
|
||||
#define TLBIMVAAIS p15, 0, c8, c3, 3
|
||||
#define TLBIMVAHIS p15, 4, c8, c3, 1
|
||||
#define BPIALLIS p15, 0, c7, c1, 6
|
||||
#define BPIALL p15, 0, c7, c5, 6
|
||||
#define ICIALLU p15, 0, c7, c5, 0
|
||||
#define HSCTLR p15, 4, c1, c0, 0
|
||||
#define HCR p15, 4, c1, c1, 0
|
||||
#define HCPTR p15, 4, c1, c1, 2
|
||||
#define HSTR p15, 4, c1, c1, 3
|
||||
#define CNTHCTL p15, 4, c14, c1, 0
|
||||
#define CNTKCTL p15, 0, c14, c1, 0
|
||||
#define VPIDR p15, 4, c0, c0, 0
|
||||
#define VMPIDR p15, 4, c0, c0, 5
|
||||
#define ISR p15, 0, c12, c1, 0
|
||||
#define CLIDR p15, 1, c0, c0, 1
|
||||
#define CSSELR p15, 2, c0, c0, 0
|
||||
#define CCSIDR p15, 1, c0, c0, 0
|
||||
#define CCSIDR2 p15, 1, c0, c0, 2
|
||||
#define HTCR p15, 4, c2, c0, 2
|
||||
#define HMAIR0 p15, 4, c10, c2, 0
|
||||
#define ATS1CPR p15, 0, c7, c8, 0
|
||||
#define ATS1HR p15, 4, c7, c8, 0
|
||||
#define DBGOSDLR p14, 0, c1, c3, 4
|
||||
|
||||
/* Debug register defines. The format is: coproc, opt1, CRn, CRm, opt2 */
|
||||
#define HDCR p15, 4, c1, c1, 1
|
||||
#define PMCR p15, 0, c9, c12, 0
|
||||
#define CNTHP_TVAL p15, 4, c14, c2, 0
|
||||
#define CNTHP_CTL p15, 4, c14, c2, 1
|
||||
|
||||
/* AArch32 coproc registers for 32bit MMU descriptor support */
|
||||
#define PRRR p15, 0, c10, c2, 0
|
||||
#define NMRR p15, 0, c10, c2, 1
|
||||
#define DACR p15, 0, c3, c0, 0
|
||||
|
||||
/* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */
|
||||
#define ICC_IAR1 p15, 0, c12, c12, 0
|
||||
#define ICC_IAR0 p15, 0, c12, c8, 0
|
||||
#define ICC_EOIR1 p15, 0, c12, c12, 1
|
||||
#define ICC_EOIR0 p15, 0, c12, c8, 1
|
||||
#define ICC_HPPIR1 p15, 0, c12, c12, 2
|
||||
#define ICC_HPPIR0 p15, 0, c12, c8, 2
|
||||
#define ICC_BPR1 p15, 0, c12, c12, 3
|
||||
#define ICC_BPR0 p15, 0, c12, c8, 3
|
||||
#define ICC_DIR p15, 0, c12, c11, 1
|
||||
#define ICC_PMR p15, 0, c4, c6, 0
|
||||
#define ICC_RPR p15, 0, c12, c11, 3
|
||||
#define ICC_CTLR p15, 0, c12, c12, 4
|
||||
#define ICC_MCTLR p15, 6, c12, c12, 4
|
||||
#define ICC_SRE p15, 0, c12, c12, 5
|
||||
#define ICC_HSRE p15, 4, c12, c9, 5
|
||||
#define ICC_MSRE p15, 6, c12, c12, 5
|
||||
#define ICC_IGRPEN0 p15, 0, c12, c12, 6
|
||||
#define ICC_IGRPEN1 p15, 0, c12, c12, 7
|
||||
#define ICC_MGRPEN1 p15, 6, c12, c12, 7
|
||||
|
||||
/* 64 bit system register defines The format is: coproc, opt1, CRm */
|
||||
#define TTBR0_64 p15, 0, c2
|
||||
#define TTBR1_64 p15, 1, c2
|
||||
#define CNTVOFF_64 p15, 4, c14
|
||||
#define VTTBR_64 p15, 6, c2
|
||||
#define CNTPCT_64 p15, 0, c14
|
||||
#define HTTBR_64 p15, 4, c2
|
||||
#define CNTHP_CVAL_64 p15, 6, c14
|
||||
#define PAR_64 p15, 0, c7
|
||||
|
||||
/* 64 bit GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRm */
|
||||
#define ICC_SGI1R_EL1_64 p15, 0, c12
|
||||
#define ICC_ASGI1R_EL1_64 p15, 1, c12
|
||||
#define ICC_SGI0R_EL1_64 p15, 2, c12
|
||||
|
||||
/* Fault registers. The format is: coproc, opt1, CRn, CRm, opt2 */
|
||||
#define DFSR p15, 0, c5, c0, 0
|
||||
#define IFSR p15, 0, c5, c0, 1
|
||||
#define DFAR p15, 0, c6, c0, 0
|
||||
#define IFAR p15, 0, c6, c0, 2
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions of MAIR encodings for device and normal memory
|
||||
******************************************************************************/
|
||||
/*
|
||||
* MAIR encodings for device memory attributes.
|
||||
*/
|
||||
#define MAIR_DEV_nGnRnE U(0x0)
|
||||
#define MAIR_DEV_nGnRE U(0x4)
|
||||
#define MAIR_DEV_nGRE U(0x8)
|
||||
#define MAIR_DEV_GRE U(0xc)
|
||||
|
||||
/*
|
||||
* MAIR encodings for normal memory attributes.
|
||||
*
|
||||
* Cache Policy
|
||||
* WT: Write Through
|
||||
* WB: Write Back
|
||||
* NC: Non-Cacheable
|
||||
*
|
||||
* Transient Hint
|
||||
* NTR: Non-Transient
|
||||
* TR: Transient
|
||||
*
|
||||
* Allocation Policy
|
||||
* RA: Read Allocate
|
||||
* WA: Write Allocate
|
||||
* RWA: Read and Write Allocate
|
||||
* NA: No Allocation
|
||||
*/
|
||||
#define MAIR_NORM_WT_TR_WA U(0x1)
|
||||
#define MAIR_NORM_WT_TR_RA U(0x2)
|
||||
#define MAIR_NORM_WT_TR_RWA U(0x3)
|
||||
#define MAIR_NORM_NC U(0x4)
|
||||
#define MAIR_NORM_WB_TR_WA U(0x5)
|
||||
#define MAIR_NORM_WB_TR_RA U(0x6)
|
||||
#define MAIR_NORM_WB_TR_RWA U(0x7)
|
||||
#define MAIR_NORM_WT_NTR_NA U(0x8)
|
||||
#define MAIR_NORM_WT_NTR_WA U(0x9)
|
||||
#define MAIR_NORM_WT_NTR_RA U(0xa)
|
||||
#define MAIR_NORM_WT_NTR_RWA U(0xb)
|
||||
#define MAIR_NORM_WB_NTR_NA U(0xc)
|
||||
#define MAIR_NORM_WB_NTR_WA U(0xd)
|
||||
#define MAIR_NORM_WB_NTR_RA U(0xe)
|
||||
#define MAIR_NORM_WB_NTR_RWA U(0xf)
|
||||
|
||||
#define MAIR_NORM_OUTER_SHIFT U(4)
|
||||
|
||||
#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \
|
||||
((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
|
||||
|
||||
/* PAR fields */
|
||||
#define PAR_F_SHIFT U(0)
|
||||
#define PAR_F_MASK ULL(0x1)
|
||||
#define PAR_ADDR_SHIFT U(12)
|
||||
#define PAR_ADDR_MASK (BIT_64(40) - ULL(1)) /* 40-bits-wide page address */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions for system register interface to AMU for FEAT_AMUv1
|
||||
******************************************************************************/
|
||||
#define AMCR p15, 0, c13, c2, 0
|
||||
#define AMCFGR p15, 0, c13, c2, 1
|
||||
#define AMCGCR p15, 0, c13, c2, 2
|
||||
#define AMUSERENR p15, 0, c13, c2, 3
|
||||
#define AMCNTENCLR0 p15, 0, c13, c2, 4
|
||||
#define AMCNTENSET0 p15, 0, c13, c2, 5
|
||||
#define AMCNTENCLR1 p15, 0, c13, c3, 0
|
||||
#define AMCNTENSET1 p15, 0, c13, c3, 1
|
||||
|
||||
/* Activity Monitor Group 0 Event Counter Registers */
|
||||
#define AMEVCNTR00 p15, 0, c0
|
||||
#define AMEVCNTR01 p15, 1, c0
|
||||
#define AMEVCNTR02 p15, 2, c0
|
||||
#define AMEVCNTR03 p15, 3, c0
|
||||
|
||||
/* Activity Monitor Group 0 Event Type Registers */
|
||||
#define AMEVTYPER00 p15, 0, c13, c6, 0
|
||||
#define AMEVTYPER01 p15, 0, c13, c6, 1
|
||||
#define AMEVTYPER02 p15, 0, c13, c6, 2
|
||||
#define AMEVTYPER03 p15, 0, c13, c6, 3
|
||||
|
||||
/* Activity Monitor Group 1 Event Counter Registers */
|
||||
#define AMEVCNTR10 p15, 0, c4
|
||||
#define AMEVCNTR11 p15, 1, c4
|
||||
#define AMEVCNTR12 p15, 2, c4
|
||||
#define AMEVCNTR13 p15, 3, c4
|
||||
#define AMEVCNTR14 p15, 4, c4
|
||||
#define AMEVCNTR15 p15, 5, c4
|
||||
#define AMEVCNTR16 p15, 6, c4
|
||||
#define AMEVCNTR17 p15, 7, c4
|
||||
#define AMEVCNTR18 p15, 0, c5
|
||||
#define AMEVCNTR19 p15, 1, c5
|
||||
#define AMEVCNTR1A p15, 2, c5
|
||||
#define AMEVCNTR1B p15, 3, c5
|
||||
#define AMEVCNTR1C p15, 4, c5
|
||||
#define AMEVCNTR1D p15, 5, c5
|
||||
#define AMEVCNTR1E p15, 6, c5
|
||||
#define AMEVCNTR1F p15, 7, c5
|
||||
|
||||
/* Activity Monitor Group 1 Event Type Registers */
|
||||
#define AMEVTYPER10 p15, 0, c13, c14, 0
|
||||
#define AMEVTYPER11 p15, 0, c13, c14, 1
|
||||
#define AMEVTYPER12 p15, 0, c13, c14, 2
|
||||
#define AMEVTYPER13 p15, 0, c13, c14, 3
|
||||
#define AMEVTYPER14 p15, 0, c13, c14, 4
|
||||
#define AMEVTYPER15 p15, 0, c13, c14, 5
|
||||
#define AMEVTYPER16 p15, 0, c13, c14, 6
|
||||
#define AMEVTYPER17 p15, 0, c13, c14, 7
|
||||
#define AMEVTYPER18 p15, 0, c13, c15, 0
|
||||
#define AMEVTYPER19 p15, 0, c13, c15, 1
|
||||
#define AMEVTYPER1A p15, 0, c13, c15, 2
|
||||
#define AMEVTYPER1B p15, 0, c13, c15, 3
|
||||
#define AMEVTYPER1C p15, 0, c13, c15, 4
|
||||
#define AMEVTYPER1D p15, 0, c13, c15, 5
|
||||
#define AMEVTYPER1E p15, 0, c13, c15, 6
|
||||
#define AMEVTYPER1F p15, 0, c13, c15, 7
|
||||
|
||||
/* AMCNTENSET0 definitions */
|
||||
#define AMCNTENSET0_Pn_SHIFT U(0)
|
||||
#define AMCNTENSET0_Pn_MASK U(0xffff)
|
||||
|
||||
/* AMCNTENSET1 definitions */
|
||||
#define AMCNTENSET1_Pn_SHIFT U(0)
|
||||
#define AMCNTENSET1_Pn_MASK U(0xffff)
|
||||
|
||||
/* AMCNTENCLR0 definitions */
|
||||
#define AMCNTENCLR0_Pn_SHIFT U(0)
|
||||
#define AMCNTENCLR0_Pn_MASK U(0xffff)
|
||||
|
||||
/* AMCNTENCLR1 definitions */
|
||||
#define AMCNTENCLR1_Pn_SHIFT U(0)
|
||||
#define AMCNTENCLR1_Pn_MASK U(0xffff)
|
||||
|
||||
/* AMCR definitions */
|
||||
#define AMCR_CG1RZ_SHIFT U(17)
|
||||
#define AMCR_CG1RZ_BIT (ULL(1) << AMCR_CG1RZ_SHIFT)
|
||||
|
||||
/* AMCFGR definitions */
|
||||
#define AMCFGR_NCG_SHIFT U(28)
|
||||
#define AMCFGR_NCG_MASK U(0xf)
|
||||
#define AMCFGR_N_SHIFT U(0)
|
||||
#define AMCFGR_N_MASK U(0xff)
|
||||
|
||||
/* AMCGCR definitions */
|
||||
#define AMCGCR_CG0NC_SHIFT U(0)
|
||||
#define AMCGCR_CG0NC_MASK U(0xff)
|
||||
#define AMCGCR_CG1NC_SHIFT U(8)
|
||||
#define AMCGCR_CG1NC_MASK U(0xff)
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions for DynamicIQ Shared Unit registers
|
||||
******************************************************************************/
|
||||
#define CLUSTERPWRDN p15, 0, c15, c3, 6
|
||||
|
||||
/* CLUSTERPWRDN register definitions */
|
||||
#define DSU_CLUSTER_PWR_OFF 0
|
||||
#define DSU_CLUSTER_PWR_ON 1
|
||||
#define DSU_CLUSTER_PWR_MASK U(1)
|
||||
|
||||
#endif /* ARCH_H */
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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)
|
||||
{
|
||||
return ((read_id_pfr1() >> ID_PFR1_GENTIMER_SHIFT) &
|
||||
ID_PFR1_GENTIMER_MASK) != 0U;
|
||||
}
|
||||
|
||||
static inline bool is_armv8_2_ttcnp_present(void)
|
||||
{
|
||||
return ((read_id_mmfr4() >> ID_MMFR4_CNP_SHIFT) &
|
||||
ID_MMFR4_CNP_MASK) != 0U;
|
||||
}
|
||||
|
||||
#endif /* ARCH_FEATURES_H */
|
||||
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
|
||||
* Portions copyright (c) 2021-2022, ProvenRun S.A.S. 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_COPROCR_WRITE_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \
|
||||
static inline void write_## _name(u_register_t v) \
|
||||
{ \
|
||||
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
|
||||
}
|
||||
|
||||
#define _DEFINE_COPROCR_READ_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \
|
||||
static inline u_register_t read_ ## _name(void) \
|
||||
{ \
|
||||
u_register_t v; \
|
||||
__asm__ volatile ("mrc "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : "=r" (v));\
|
||||
return v; \
|
||||
}
|
||||
|
||||
/*
|
||||
* The undocumented %Q and %R extended asm are used to implemented the below
|
||||
* 64 bit `mrrc` and `mcrr` instructions.
|
||||
*/
|
||||
|
||||
#define _DEFINE_COPROCR_WRITE_FUNC_64(_name, coproc, opc1, CRm) \
|
||||
static inline void write64_## _name(uint64_t v) \
|
||||
{ \
|
||||
__asm__ volatile ("mcrr "#coproc","#opc1", %Q0, %R0,"#CRm : : "r" (v));\
|
||||
}
|
||||
|
||||
#define _DEFINE_COPROCR_READ_FUNC_64(_name, coproc, opc1, CRm) \
|
||||
static inline uint64_t read64_## _name(void) \
|
||||
{ uint64_t v; \
|
||||
__asm__ volatile ("mrrc "#coproc","#opc1", %Q0, %R0,"#CRm : "=r" (v));\
|
||||
return v; \
|
||||
}
|
||||
|
||||
#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 _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \
|
||||
static inline void write_ ## _name(const u_register_t v) \
|
||||
{ \
|
||||
__asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v)); \
|
||||
}
|
||||
|
||||
/* Define read function for coproc register */
|
||||
#define DEFINE_COPROCR_READ_FUNC(_name, ...) \
|
||||
_DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__)
|
||||
|
||||
/* Define write function for coproc register */
|
||||
#define DEFINE_COPROCR_WRITE_FUNC(_name, ...) \
|
||||
_DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__)
|
||||
|
||||
/* Define read & write function for coproc register */
|
||||
#define DEFINE_COPROCR_RW_FUNCS(_name, ...) \
|
||||
_DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__) \
|
||||
_DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__)
|
||||
|
||||
/* Define 64 bit read function for coproc register */
|
||||
#define DEFINE_COPROCR_READ_FUNC_64(_name, ...) \
|
||||
_DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__)
|
||||
|
||||
/* Define 64 bit write function for coproc register */
|
||||
#define DEFINE_COPROCR_WRITE_FUNC_64(_name, ...) \
|
||||
_DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__)
|
||||
|
||||
/* Define 64 bit read & write function for coproc register */
|
||||
#define DEFINE_COPROCR_RW_FUNCS_64(_name, ...) \
|
||||
_DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__) \
|
||||
_DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__)
|
||||
|
||||
/* 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)
|
||||
|
||||
/**********************************************************************
|
||||
* Macros to create inline functions for tlbi operations
|
||||
*********************************************************************/
|
||||
|
||||
#define _DEFINE_TLBIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \
|
||||
static inline void tlbi##_op(void) \
|
||||
{ \
|
||||
u_register_t v = 0; \
|
||||
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
|
||||
}
|
||||
|
||||
#define _DEFINE_BPIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \
|
||||
static inline void bpi##_op(void) \
|
||||
{ \
|
||||
u_register_t v = 0; \
|
||||
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
|
||||
}
|
||||
|
||||
#define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \
|
||||
static inline void tlbi##_op(u_register_t v) \
|
||||
{ \
|
||||
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
|
||||
}
|
||||
|
||||
/* Define function for simple TLBI operation */
|
||||
#define DEFINE_TLBIOP_FUNC(_op, ...) \
|
||||
_DEFINE_TLBIOP_FUNC(_op, __VA_ARGS__)
|
||||
|
||||
/* Define function for TLBI operation with register parameter */
|
||||
#define DEFINE_TLBIOP_PARAM_FUNC(_op, ...) \
|
||||
_DEFINE_TLBIOP_PARAM_FUNC(_op, __VA_ARGS__)
|
||||
|
||||
/* Define function for simple BPI operation */
|
||||
#define DEFINE_BPIOP_FUNC(_op, ...) \
|
||||
_DEFINE_BPIOP_FUNC(_op, __VA_ARGS__)
|
||||
|
||||
/**********************************************************************
|
||||
* Macros to create inline functions for DC operations
|
||||
*********************************************************************/
|
||||
#define _DEFINE_DCOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \
|
||||
static inline void dc##_op(u_register_t v) \
|
||||
{ \
|
||||
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
|
||||
}
|
||||
|
||||
/* Define function for DC operation with register parameter */
|
||||
#define DEFINE_DCOP_PARAM_FUNC(_op, ...) \
|
||||
_DEFINE_DCOP_PARAM_FUNC(_op, __VA_ARGS__)
|
||||
|
||||
/**********************************************************************
|
||||
* 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 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(u_register_t v) \
|
||||
{ \
|
||||
__asm__ (#_op " " #_type ", %0" : : "r" (v)); \
|
||||
}
|
||||
|
||||
void flush_dcache_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_secure(void);
|
||||
void disable_mmu_icache_secure(void);
|
||||
|
||||
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)
|
||||
|
||||
/* dmb ld is not valid for armv7/thumb machines */
|
||||
#if ARM_ARCH_MAJOR != 7
|
||||
DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
|
||||
#endif
|
||||
|
||||
DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
|
||||
DEFINE_SYSOP_TYPE_FUNC(dmb, ishst)
|
||||
DEFINE_SYSOP_FUNC(isb)
|
||||
|
||||
void __dead2 smc(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3,
|
||||
uint32_t r4, uint32_t r5, uint32_t r6, uint32_t r7);
|
||||
|
||||
DEFINE_SYSREG_RW_FUNCS(spsr)
|
||||
DEFINE_SYSREG_RW_FUNCS(cpsr)
|
||||
|
||||
/*******************************************************************************
|
||||
* System register accessor prototypes
|
||||
******************************************************************************/
|
||||
DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR)
|
||||
DEFINE_COPROCR_READ_FUNC(midr, MIDR)
|
||||
DEFINE_COPROCR_READ_FUNC(id_mmfr4, ID_MMFR4)
|
||||
DEFINE_COPROCR_READ_FUNC(id_dfr0, ID_DFR0)
|
||||
DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0)
|
||||
DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1)
|
||||
DEFINE_COPROCR_READ_FUNC(isr, ISR)
|
||||
DEFINE_COPROCR_READ_FUNC(clidr, CLIDR)
|
||||
DEFINE_COPROCR_READ_FUNC_64(cntpct, CNTPCT_64)
|
||||
|
||||
DEFINE_COPROCR_RW_FUNCS(scr, SCR)
|
||||
DEFINE_COPROCR_RW_FUNCS(ctr, CTR)
|
||||
DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR)
|
||||
DEFINE_COPROCR_RW_FUNCS(actlr, ACTLR)
|
||||
DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR)
|
||||
DEFINE_COPROCR_RW_FUNCS(hcr, HCR)
|
||||
DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR)
|
||||
DEFINE_COPROCR_RW_FUNCS(cntfrq, CNTFRQ)
|
||||
DEFINE_COPROCR_RW_FUNCS(cnthctl, CNTHCTL)
|
||||
DEFINE_COPROCR_RW_FUNCS(mair0, MAIR0)
|
||||
DEFINE_COPROCR_RW_FUNCS(mair1, MAIR1)
|
||||
DEFINE_COPROCR_RW_FUNCS(hmair0, HMAIR0)
|
||||
DEFINE_COPROCR_RW_FUNCS(ttbcr, TTBCR)
|
||||
DEFINE_COPROCR_RW_FUNCS(htcr, HTCR)
|
||||
DEFINE_COPROCR_RW_FUNCS(ttbr0, TTBR0)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(ttbr0, TTBR0_64)
|
||||
DEFINE_COPROCR_RW_FUNCS(ttbr1, TTBR1)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(httbr, HTTBR_64)
|
||||
DEFINE_COPROCR_RW_FUNCS(vpidr, VPIDR)
|
||||
DEFINE_COPROCR_RW_FUNCS(vmpidr, VMPIDR)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(vttbr, VTTBR_64)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64)
|
||||
DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR)
|
||||
DEFINE_COPROCR_RW_FUNCS(hstr, HSTR)
|
||||
DEFINE_COPROCR_RW_FUNCS(cnthp_ctl_el2, CNTHP_CTL)
|
||||
DEFINE_COPROCR_RW_FUNCS(cnthp_tval_el2, CNTHP_TVAL)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(cnthp_cval_el2, CNTHP_CVAL_64)
|
||||
|
||||
#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_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_sre_el3, ICC_MSRE)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_pmr_el1, ICC_PMR)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_rpr_el1, ICC_RPR)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el3, ICC_MGRPEN1)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_hppir0_el1, ICC_HPPIR0)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_hppir1_el1, ICC_HPPIR1)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_iar0_el1, ICC_IAR0)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_iar1_el1, ICC_IAR1)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_eoir0_el1, ICC_EOIR0)
|
||||
DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64)
|
||||
DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64)
|
||||
DEFINE_COPROCR_WRITE_FUNC_64(icc_asgi1r, ICC_ASGI1R_EL1_64)
|
||||
|
||||
DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR)
|
||||
DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
|
||||
DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
|
||||
DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
|
||||
|
||||
/*
|
||||
* Address translation
|
||||
*/
|
||||
DEFINE_COPROCR_WRITE_FUNC(ats1cpr, ATS1CPR)
|
||||
DEFINE_COPROCR_WRITE_FUNC(ats1hr, ATS1HR)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(par, PAR_64)
|
||||
|
||||
DEFINE_COPROCR_RW_FUNCS(nsacr, NSACR)
|
||||
|
||||
/* AArch32 coproc registers for 32bit MMU descriptor support */
|
||||
DEFINE_COPROCR_RW_FUNCS(prrr, PRRR)
|
||||
DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR)
|
||||
DEFINE_COPROCR_RW_FUNCS(dacr, DACR)
|
||||
|
||||
/* Coproc registers for 32bit AMU support */
|
||||
DEFINE_COPROCR_READ_FUNC(amcfgr, AMCFGR)
|
||||
DEFINE_COPROCR_READ_FUNC(amcgcr, AMCGCR)
|
||||
DEFINE_COPROCR_RW_FUNCS(amcr, AMCR)
|
||||
|
||||
DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0)
|
||||
DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1)
|
||||
DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0)
|
||||
DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1)
|
||||
|
||||
/* Coproc registers for 64bit AMU support */
|
||||
DEFINE_COPROCR_RW_FUNCS_64(amevcntr00, AMEVCNTR00)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(amevcntr01, AMEVCNTR01)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(amevcntr02, AMEVCNTR02)
|
||||
DEFINE_COPROCR_RW_FUNCS_64(amevcntr03, AMEVCNTR03)
|
||||
|
||||
/*
|
||||
* TLBI operation prototypes
|
||||
*/
|
||||
DEFINE_TLBIOP_FUNC(all, TLBIALL)
|
||||
DEFINE_TLBIOP_FUNC(allis, TLBIALLIS)
|
||||
DEFINE_TLBIOP_PARAM_FUNC(mva, TLBIMVA)
|
||||
DEFINE_TLBIOP_PARAM_FUNC(mvaa, TLBIMVAA)
|
||||
DEFINE_TLBIOP_PARAM_FUNC(mvaais, TLBIMVAAIS)
|
||||
DEFINE_TLBIOP_PARAM_FUNC(mvahis, TLBIMVAHIS)
|
||||
|
||||
/*
|
||||
* BPI operation prototypes.
|
||||
*/
|
||||
DEFINE_BPIOP_FUNC(allis, BPIALLIS)
|
||||
|
||||
/*
|
||||
* DC operation prototypes
|
||||
*/
|
||||
DEFINE_DCOP_PARAM_FUNC(civac, DCCIMVAC)
|
||||
DEFINE_DCOP_PARAM_FUNC(ivac, DCIMVAC)
|
||||
#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319
|
||||
DEFINE_DCOP_PARAM_FUNC(cvac, DCCIMVAC)
|
||||
#else
|
||||
DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DynamIQ Shared Unit power management
|
||||
*/
|
||||
DEFINE_COPROCR_RW_FUNCS(clusterpwrdn, CLUSTERPWRDN)
|
||||
|
||||
/* Previously defined accessor functions with incomplete register names */
|
||||
#define dsb() dsbsy()
|
||||
#define dmb() dmbsy()
|
||||
|
||||
/* dmb ld is not valid for armv7/thumb machines, so alias it to dmb */
|
||||
#if ARM_ARCH_MAJOR == 7
|
||||
#define dmbld() dmb()
|
||||
#endif
|
||||
|
||||
#define IS_IN_SECURE() \
|
||||
(GET_NS_BIT(read_scr()) == 0)
|
||||
|
||||
#define IS_IN_HYP() (GET_M32(read_cpsr()) == MODE32_hyp)
|
||||
#define IS_IN_SVC() (GET_M32(read_cpsr()) == MODE32_svc)
|
||||
#define IS_IN_MON() (GET_M32(read_cpsr()) == MODE32_mon)
|
||||
#define IS_IN_EL2() IS_IN_HYP()
|
||||
/* If EL3 is AArch32, then secure PL1 and monitor mode correspond to EL3 */
|
||||
#define IS_IN_EL3() \
|
||||
((GET_M32(read_cpsr()) == MODE32_mon) || \
|
||||
(IS_IN_SECURE() && (GET_M32(read_cpsr()) != MODE32_usr)))
|
||||
|
||||
static inline unsigned int get_current_el(void)
|
||||
{
|
||||
if (IS_IN_EL3()) {
|
||||
return 3U;
|
||||
} else if (IS_IN_EL2()) {
|
||||
return 2U;
|
||||
} else {
|
||||
return 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/* Macros for compatibility with AArch64 system registers */
|
||||
#define read_mpidr_el1() read_mpidr()
|
||||
|
||||
#define read_scr_el3() read_scr()
|
||||
#define write_scr_el3(_v) write_scr(_v)
|
||||
|
||||
#define read_hcr_el2() read_hcr()
|
||||
#define write_hcr_el2(_v) write_hcr(_v)
|
||||
|
||||
#define read_cpacr_el1() read_cpacr()
|
||||
#define write_cpacr_el1(_v) write_cpacr(_v)
|
||||
|
||||
#define read_cntfrq_el0() read_cntfrq()
|
||||
#define write_cntfrq_el0(_v) write_cntfrq(_v)
|
||||
#define read_isr_el1() read_isr()
|
||||
|
||||
#define read_cntpct_el0() read64_cntpct()
|
||||
|
||||
#define read_ctr_el0() read_ctr()
|
||||
|
||||
#define write_icc_sgi0r_el1(_v) write64_icc_sgi0r_el1(_v)
|
||||
#define write_icc_sgi1r(_v) write64_icc_sgi1r(_v)
|
||||
#define write_icc_asgi1r(_v) write64_icc_asgi1r(_v)
|
||||
|
||||
#define read_daif() read_cpsr()
|
||||
#define write_daif(flags) write_cpsr(flags)
|
||||
|
||||
#define read_cnthp_cval_el2() read64_cnthp_cval_el2()
|
||||
#define write_cnthp_cval_el2(v) write64_cnthp_cval_el2(v)
|
||||
|
||||
#define read_amcntenset0_el0() read_amcntenset0()
|
||||
#define read_amcntenset1_el0() read_amcntenset1()
|
||||
|
||||
/* Helper functions to manipulate CPSR */
|
||||
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();
|
||||
__asm__ volatile ("cpsie i");
|
||||
isb();
|
||||
}
|
||||
|
||||
static inline void enable_serror(void)
|
||||
{
|
||||
COMPILER_BARRIER();
|
||||
__asm__ volatile ("cpsie a");
|
||||
isb();
|
||||
}
|
||||
|
||||
static inline void enable_fiq(void)
|
||||
{
|
||||
COMPILER_BARRIER();
|
||||
__asm__ volatile ("cpsie f");
|
||||
isb();
|
||||
}
|
||||
|
||||
static inline void disable_irq(void)
|
||||
{
|
||||
COMPILER_BARRIER();
|
||||
__asm__ volatile ("cpsid i");
|
||||
isb();
|
||||
}
|
||||
|
||||
static inline void disable_serror(void)
|
||||
{
|
||||
COMPILER_BARRIER();
|
||||
__asm__ volatile ("cpsid a");
|
||||
isb();
|
||||
}
|
||||
|
||||
static inline void disable_fiq(void)
|
||||
{
|
||||
COMPILER_BARRIER();
|
||||
__asm__ volatile ("cpsid f");
|
||||
isb();
|
||||
}
|
||||
|
||||
#endif /* ARCH_HELPERS_H */
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, 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.
|
||||
*/
|
||||
#if ERRATA_A57_813419
|
||||
#define TLB_INVALIDATE(_reg, _coproc) \
|
||||
stcopr _reg, _coproc; \
|
||||
dsb ish; \
|
||||
stcopr _reg, _coproc
|
||||
#else
|
||||
#define TLB_INVALIDATE(_reg, _coproc) \
|
||||
stcopr _reg, _coproc
|
||||
#endif
|
||||
|
||||
#define WORD_SIZE 4
|
||||
|
||||
/*
|
||||
* Co processor register accessors
|
||||
*/
|
||||
.macro ldcopr reg, coproc, opc1, CRn, CRm, opc2
|
||||
mrc \coproc, \opc1, \reg, \CRn, \CRm, \opc2
|
||||
.endm
|
||||
|
||||
.macro ldcopr16 reg1, reg2, coproc, opc1, CRm
|
||||
mrrc \coproc, \opc1, \reg1, \reg2, \CRm
|
||||
.endm
|
||||
|
||||
.macro stcopr reg, coproc, opc1, CRn, CRm, opc2
|
||||
mcr \coproc, \opc1, \reg, \CRn, \CRm, \opc2
|
||||
.endm
|
||||
|
||||
.macro stcopr16 reg1, reg2, coproc, opc1, CRm
|
||||
mcrr \coproc, \opc1, \reg1, \reg2, \CRm
|
||||
.endm
|
||||
|
||||
/* Cache line size helpers */
|
||||
.macro dcache_line_size reg, tmp
|
||||
ldcopr \tmp, CTR
|
||||
ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH
|
||||
mov \reg, #WORD_SIZE
|
||||
lsl \reg, \reg, \tmp
|
||||
.endm
|
||||
|
||||
.macro icache_line_size reg, tmp
|
||||
ldcopr \tmp, CTR
|
||||
and \tmp, \tmp, #CTR_IMINLINE_MASK
|
||||
mov \reg, #WORD_SIZE
|
||||
lsl \reg, \reg, \tmp
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Declare the exception vector table, enforcing it is aligned on a
|
||||
* 32 byte boundary.
|
||||
*/
|
||||
.macro vector_base label
|
||||
.section .vectors, "ax"
|
||||
.align 5
|
||||
\label:
|
||||
.endm
|
||||
|
||||
/*
|
||||
* This macro calculates the base address of the current CPU's multi
|
||||
* processor(MP) stack using the plat_my_core_pos() index, the name of
|
||||
* the stack storage and the size of each stack.
|
||||
* Out: r0 = physical address of stack base
|
||||
* Clobber: r14, r1, r2
|
||||
*/
|
||||
.macro get_my_mp_stack _name, _size
|
||||
bl plat_my_core_pos
|
||||
ldr r2, =(\_name + \_size)
|
||||
mov r1, #\_size
|
||||
mla r0, r0, r1, r2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* This macro calculates the base address of a uniprocessor(UP) stack
|
||||
* using the name of the stack storage and the size of the stack
|
||||
* Out: r0 = physical address of stack base
|
||||
*/
|
||||
.macro get_up_stack _name, _size
|
||||
ldr r0, =(\_name + \_size)
|
||||
.endm
|
||||
|
||||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
||||
/*
|
||||
* Macro for mitigating against speculative execution.
|
||||
* ARMv7 cores without Virtualization extension do not support the
|
||||
* eret instruction.
|
||||
*/
|
||||
.macro exception_return
|
||||
movs pc, lr
|
||||
dsb nsh
|
||||
isb
|
||||
.endm
|
||||
|
||||
#else
|
||||
/*
|
||||
* 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
|
||||
|
||||
#if (ARM_ARCH_MAJOR == 7)
|
||||
/* ARMv7 does not support stl instruction */
|
||||
.macro stl _reg, _write_lock
|
||||
dmb
|
||||
str \_reg, \_write_lock
|
||||
dsb
|
||||
.endm
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper macro to generate the best mov/movw/movt combinations
|
||||
* according to the value to be moved.
|
||||
*/
|
||||
.macro mov_imm _reg, _val
|
||||
.if ((\_val) & 0xffff0000) == 0
|
||||
mov \_reg, #(\_val)
|
||||
.else
|
||||
movw \_reg, #((\_val) & 0xffff)
|
||||
movt \_reg, #((\_val) >> 16)
|
||||
.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
|
||||
|
||||
/*
|
||||
* Helper macro to OR the bottom 32 bits of `_val` into `_reg_l`
|
||||
* and the top 32 bits of `_val` into `_reg_h`. If either the bottom
|
||||
* or top word of `_val` is zero, the corresponding OR operation
|
||||
* is skipped.
|
||||
*/
|
||||
.macro orr64_imm _reg_l, _reg_h, _val
|
||||
.if (\_val >> 32)
|
||||
orr \_reg_h, \_reg_h, #(\_val >> 32)
|
||||
.endif
|
||||
.if (\_val & 0xffffffff)
|
||||
orr \_reg_l, \_reg_l, #(\_val & 0xffffffff)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Helper macro to bitwise-clear bits in `_reg_l` and
|
||||
* `_reg_h` given a 64 bit immediate `_val`. The set bits
|
||||
* in the bottom word of `_val` dictate which bits from
|
||||
* `_reg_l` should be cleared. Similarly, the set bits in
|
||||
* the top word of `_val` dictate which bits from `_reg_h`
|
||||
* should be cleared. If either the bottom or top word of
|
||||
* `_val` is zero, the corresponding BIC operation is skipped.
|
||||
*/
|
||||
.macro bic64_imm _reg_l, _reg_h, _val
|
||||
.if (\_val >> 32)
|
||||
bic \_reg_h, \_reg_h, #(\_val >> 32)
|
||||
.endif
|
||||
.if (\_val & 0xffffffff)
|
||||
bic \_reg_l, \_reg_l, #(\_val & 0xffffffff)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Helper macro for carrying out division in software when
|
||||
* hardware division is not suported. \top holds the dividend
|
||||
* in the function call and the remainder after
|
||||
* the function is executed. \bot holds the divisor. \div holds
|
||||
* the quotient and \temp is a temporary registed used in calcualtion.
|
||||
* The division algorithm has been obtained from:
|
||||
* http://www.keil.com/support/man/docs/armasm/armasm_dom1359731155623.htm
|
||||
*/
|
||||
.macro softudiv div:req,top:req,bot:req,temp:req
|
||||
|
||||
mov \temp, \bot
|
||||
cmp \temp, \top, lsr #1
|
||||
div1:
|
||||
movls \temp, \temp, lsl #1
|
||||
cmp \temp, \top, lsr #1
|
||||
bls div1
|
||||
mov \div, #0
|
||||
|
||||
div2:
|
||||
cmp \top, \temp
|
||||
subcs \top, \top,\temp
|
||||
ADC \div, \div, \div
|
||||
mov \temp, \temp, lsr #1
|
||||
cmp \temp, \bot
|
||||
bhs div2
|
||||
.endm
|
||||
#endif /* ASM_MACROS_S */
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 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. We assume that the stack is
|
||||
* initialized prior to invoking 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 ;\
|
||||
ldr r0, =.L_assert_filename ;\
|
||||
ldr r1, =__LINE__ ;\
|
||||
b asm_assert;\
|
||||
300:
|
||||
|
||||
#endif /* ASSERT_MACROS_S */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2018-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 r0 and a valid return address in lr.
|
||||
*/
|
||||
.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
|
||||
ldr r1, =console_\_driver\()_putc
|
||||
.else
|
||||
mov r1, #0
|
||||
.endif
|
||||
str r1, [r0, #CONSOLE_T_PUTC]
|
||||
|
||||
.ifne \getc
|
||||
ldr r1, =console_\_driver\()_getc
|
||||
.else
|
||||
mov r1, #0
|
||||
.endif
|
||||
str r1, [r0, #CONSOLE_T_GETC]
|
||||
|
||||
.ifne \flush
|
||||
ldr r1, =console_\_driver\()_flush
|
||||
.else
|
||||
mov r1, #0
|
||||
.endif
|
||||
str r1, [r0, #CONSOLE_T_FLUSH]
|
||||
|
||||
mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
|
||||
str r1, [r0, #CONSOLE_T_FLAGS]
|
||||
b console_register
|
||||
.endm
|
||||
|
||||
#endif /* CONSOLE_MACROS_S */
|
||||
+458
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* Copyright (c) 2016-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 <lib/xlat_tables/xlat_tables_defs.h>
|
||||
|
||||
#define PAGE_START_MASK ~(PAGE_SIZE_MASK)
|
||||
|
||||
/*
|
||||
* Helper macro to initialise EL3 registers we care about.
|
||||
*/
|
||||
.macro el3_arch_init_common
|
||||
/* ---------------------------------------------------------------------
|
||||
* SCTLR has already been initialised - read current value before
|
||||
* modifying.
|
||||
*
|
||||
* SCTLR.I: Enable the instruction cache.
|
||||
*
|
||||
* SCTLR.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.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldr r1, =(SCTLR_I_BIT | SCTLR_A_BIT)
|
||||
ldcopr r0, SCTLR
|
||||
orr r0, r0, r1
|
||||
stcopr r0, SCTLR
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise SCR, setting all fields rather than relying on the hw.
|
||||
*
|
||||
* SCR.SIF: Enabled so that Secure state instruction fetches from
|
||||
* Non-secure memory are not permitted.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =(SCR_RESET_VAL | SCR_SIF_BIT)
|
||||
stcopr r0, SCR
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Enable the Asynchronous data abort now that the
|
||||
* exception vectors have been setup.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
cpsie a
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise NSACR, setting all the fields, except for the
|
||||
* IMPLEMENTATION DEFINED field, rather than relying on the hw. Some
|
||||
* fields are architecturally UNKNOWN on reset.
|
||||
*
|
||||
* NSACR_ENABLE_FP_ACCESS: Represents NSACR.cp11 and NSACR.cp10. The
|
||||
* cp11 field is ignored, but is set to same value as cp10. The cp10
|
||||
* field is set to allow access to Advanced SIMD and floating point
|
||||
* features from both Security states.
|
||||
*
|
||||
* NSACR.NSTRCDIS: When system register trace implemented, Set to one
|
||||
* so that NS System register accesses to all implemented trace
|
||||
* registers are disabled.
|
||||
* When system register trace is not implemented, this bit is RES0 and
|
||||
* hence set to zero.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldcopr r0, NSACR
|
||||
and r0, r0, #NSACR_IMP_DEF_MASK
|
||||
orr r0, r0, #(NSACR_RESET_VAL | NSACR_ENABLE_FP_ACCESS)
|
||||
ldcopr r1, ID_DFR0
|
||||
ubfx r1, r1, #ID_DFR0_COPTRC_SHIFT, #ID_DFR0_COPTRC_LENGTH
|
||||
cmp r1, #ID_DFR0_COPTRC_SUPPORTED
|
||||
bne 1f
|
||||
orr r0, r0, #NSTRCDIS_BIT
|
||||
1:
|
||||
stcopr r0, NSACR
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise CPACR, setting all fields rather than relying on hw. Some
|
||||
* fields are architecturally UNKNOWN on reset.
|
||||
*
|
||||
* CPACR.TRCDIS: Trap control for PL0 and PL1 System register accesses
|
||||
* to trace registers. Set to zero to allow access.
|
||||
*
|
||||
* CPACR_ENABLE_FP_ACCESS: Represents CPACR.cp11 and CPACR.cp10. The
|
||||
* cp11 field is ignored, but is set to same value as cp10. The cp10
|
||||
* field is set to allow full access from PL0 and PL1 to floating-point
|
||||
* and Advanced SIMD features.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =((CPACR_RESET_VAL | CPACR_ENABLE_FP_ACCESS) & ~(TRCDIS_BIT))
|
||||
stcopr r0, CPACR
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise FPEXC, setting all fields rather than relying on hw. Some
|
||||
* fields are architecturally UNKNOWN on reset and are set to zero
|
||||
* except for field(s) listed below.
|
||||
*
|
||||
* FPEXC.EN: Enable access to Advanced SIMD and floating point features
|
||||
* from all exception levels.
|
||||
*
|
||||
* __SOFTFP__: Predefined macro exposed by soft-float toolchain.
|
||||
* ARMv7 and Cortex-A32(ARMv8/aarch32) has both soft-float and
|
||||
* hard-float variants of toolchain, avoid compiling below code with
|
||||
* soft-float toolchain as "vmsr" instruction will not be recognized.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
#if ((ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_VFP)) && !(__SOFTFP__)
|
||||
ldr r0, =(FPEXC_RESET_VAL | FPEXC_EN_BIT)
|
||||
vmsr FPEXC, r0
|
||||
isb
|
||||
#endif
|
||||
|
||||
#if (ARM_ARCH_MAJOR > 7)
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise SDCR, setting all the fields rather than relying on hw.
|
||||
*
|
||||
* SDCR.SPD: Disable AArch32 privileged debug. Debug exceptions from
|
||||
* Secure EL1 are disabled.
|
||||
*
|
||||
* SDCR.SCCD: Set to one so that cycle counting by PMCCNTR is prohibited
|
||||
* in Secure state. This bit is RES0 in versions of the architecture
|
||||
* earlier than ARMv8.5, setting it to 1 doesn't have any effect on
|
||||
* them.
|
||||
*
|
||||
* SDCR.TTRF: Set to one so that access to trace filter control
|
||||
* registers in non-monitor mode generate Monitor 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.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =((SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE) | \
|
||||
SDCR_SCCD_BIT) & ~SDCR_TTRF_BIT)
|
||||
ldcopr r1, ID_DFR0
|
||||
ubfx r1, r1, #ID_DFR0_TRACEFILT_SHIFT, #ID_DFR0_TRACEFILT_LENGTH
|
||||
cmp r1, #ID_DFR0_TRACEFILT_SUPPORTED
|
||||
bne 1f
|
||||
orr r0, r0, #SDCR_TTRF_BIT
|
||||
1:
|
||||
stcopr r0, SDCR
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise PMCR, setting all fields rather than relying
|
||||
* on hw. Some fields are architecturally UNKNOWN on reset.
|
||||
*
|
||||
* PMCR.LP: Set to one so that event counter overflow, that
|
||||
* is recorded in PMOVSCLR[0-30], occurs on the increment
|
||||
* that changes PMEVCNTR<n>[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.
|
||||
* This bit is Reserved, UNK/SBZP in ARMv7.
|
||||
*
|
||||
* PMCR.LC: Set to one so that cycle counter overflow, that
|
||||
* is recorded in PMOVSCLR[31], occurs on the increment
|
||||
* that changes PMCCNTR[63] from 1 to 0.
|
||||
* This bit is Reserved, UNK/SBZP in ARMv7.
|
||||
*
|
||||
* PMCR.DP: Set to one to prohibit cycle counting whilst in Secure mode.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =(PMCR_RESET_VAL | PMCR_DP_BIT | PMCR_LC_BIT | \
|
||||
PMCR_LP_BIT)
|
||||
#else
|
||||
ldr r0, =(PMCR_RESET_VAL | PMCR_DP_BIT)
|
||||
#endif
|
||||
stcopr r0, PMCR
|
||||
|
||||
/*
|
||||
* If Data Independent Timing (DIT) functionality is implemented,
|
||||
* always enable DIT in EL3
|
||||
*/
|
||||
ldcopr r0, ID_PFR0
|
||||
and r0, r0, #(ID_PFR0_DIT_MASK << ID_PFR0_DIT_SHIFT)
|
||||
cmp r0, #ID_PFR0_DIT_SUPPORTED
|
||||
bne 1f
|
||||
mrs r0, cpsr
|
||||
orr r0, r0, #CPSR_DIT_BIT
|
||||
msr cpsr_cxsf, r0
|
||||
1:
|
||||
.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 BL32 (SP_MIN).
|
||||
*
|
||||
* 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 the SCTLR register 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
|
||||
|
||||
/* Make sure we are in Secure Mode */
|
||||
#if ENABLE_ASSERTIONS
|
||||
ldcopr r0, SCR
|
||||
tst r0, #SCR_NS_BIT
|
||||
ASM_ASSERT(eq)
|
||||
#endif
|
||||
|
||||
.if \_init_sctlr
|
||||
/* -------------------------------------------------------------
|
||||
* This is the initialisation of SCTLR and so must ensure that
|
||||
* all fields are explicitly set rather than relying on hw. Some
|
||||
* fields reset to an IMPLEMENTATION DEFINED value.
|
||||
*
|
||||
* SCTLR.TE: Set to zero so that exceptions to an Exception
|
||||
* Level executing at PL1 are taken to A32 state.
|
||||
*
|
||||
* SCTLR.EE: Set the CPU endianness before doing anything that
|
||||
* might involve memory reads or writes. Set to zero to select
|
||||
* Little Endian.
|
||||
*
|
||||
* SCTLR.V: Set to zero to select the normal exception vectors
|
||||
* with base address held in VBAR.
|
||||
*
|
||||
* SCTLR.DSSBS: Set to zero to disable speculation store bypass
|
||||
* safe behaviour upon exception entry to EL3.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =(SCTLR_RESET_VAL & ~(SCTLR_TE_BIT | SCTLR_EE_BIT | \
|
||||
SCTLR_V_BIT | SCTLR_DSSBS_BIT))
|
||||
stcopr r0, SCTLR
|
||||
isb
|
||||
.endif /* _init_sctlr */
|
||||
|
||||
/* Switch to monitor mode */
|
||||
cps #MODE32_mon
|
||||
isb
|
||||
|
||||
#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
|
||||
cmp r0, #0
|
||||
bxne r0
|
||||
.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 r0, =pie_fixup
|
||||
ldr r1, =PAGE_START_MASK
|
||||
and r0, r0, r1
|
||||
mov_imm r1, \_pie_fixup_size
|
||||
add r1, r1, r0
|
||||
bl fixup_gdt_reloc
|
||||
#endif /* ENABLE_PIE */
|
||||
.endif /* _pie_fixup_size */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Set the exception vectors (VBAR/MVBAR).
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =\_exception_vectors
|
||||
stcopr r0, VBAR
|
||||
stcopr r0, MVBAR
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* It is a cold boot.
|
||||
* Perform any processor specific actions upon reset e.g. cache, TLB
|
||||
* invalidations etc.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
bl reset_handler
|
||||
|
||||
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
|
||||
cmp r0, #0
|
||||
bne 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 */
|
||||
no_ret plat_panic_handler
|
||||
|
||||
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_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3)
|
||||
/* -----------------------------------------------------------------
|
||||
* Invalidate the RW memory used by the 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
|
||||
ldr r0, =__TEXT_START__
|
||||
#else
|
||||
ldr r0, =__RO_START__
|
||||
#endif /* SEPARATE_CODE_AND_RODATA */
|
||||
#else
|
||||
ldr r0, =__RW_START__
|
||||
#endif /* ENABLE_PIE */
|
||||
ldr r1, =__RW_END__
|
||||
sub r1, r1, r0
|
||||
bl inv_dcache_range
|
||||
#if defined(IMAGE_BL2) && SEPARATE_BL2_NOLOAD_REGION
|
||||
ldr r0, =__BL2_NOLOAD_START__
|
||||
ldr r1, =__BL2_NOLOAD_END__
|
||||
sub r1, r1, r0
|
||||
bl inv_dcache_range
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* zeromem uses r12 whereas it is used to save previous BL arg3,
|
||||
* save it in r7
|
||||
*/
|
||||
mov r7, r12
|
||||
ldr r0, =__BSS_START__
|
||||
ldr r1, =__BSS_END__
|
||||
sub r1, r1, r0
|
||||
bl zeromem
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
ldr r0, =__COHERENT_RAM_START__
|
||||
ldr r1, =__COHERENT_RAM_END_UNALIGNED__
|
||||
sub r1, r1, r0
|
||||
bl zeromem
|
||||
#endif
|
||||
|
||||
/* Restore r12 */
|
||||
mov r12, r7
|
||||
|
||||
#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM)
|
||||
/* -----------------------------------------------------
|
||||
* Copy data from ROM to RAM.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
ldr r0, =__DATA_RAM_START__
|
||||
ldr r1, =__DATA_ROM_START__
|
||||
ldr r2, =__DATA_RAM_END__
|
||||
sub r2, r2, r0
|
||||
bl memcpy4
|
||||
#endif
|
||||
.endif /* _init_c_runtime */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* 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
|
||||
|
||||
#endif /* EL3_COMMON_MACROS_S */
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019, 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>
|
||||
|
||||
/* These are offsets to registers in smc_ctx_t */
|
||||
#define SMC_CTX_GPREG_R0 U(0x0)
|
||||
#define SMC_CTX_GPREG_R1 U(0x4)
|
||||
#define SMC_CTX_GPREG_R2 U(0x8)
|
||||
#define SMC_CTX_GPREG_R3 U(0xC)
|
||||
#define SMC_CTX_GPREG_R4 U(0x10)
|
||||
#define SMC_CTX_GPREG_R5 U(0x14)
|
||||
#define SMC_CTX_SP_USR U(0x34)
|
||||
#define SMC_CTX_SPSR_MON U(0x78)
|
||||
#define SMC_CTX_SP_MON U(0x7C)
|
||||
#define SMC_CTX_LR_MON U(0x80)
|
||||
#define SMC_CTX_SCR U(0x84)
|
||||
#define SMC_CTX_PMCR U(0x88)
|
||||
#define SMC_CTX_SIZE U(0x90)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lib/cassert.h>
|
||||
|
||||
/*
|
||||
* The generic structure to save arguments and callee saved registers during
|
||||
* an SMC. Also this structure is used to store the result return values after
|
||||
* the completion of SMC service.
|
||||
*/
|
||||
typedef struct smc_ctx {
|
||||
u_register_t r0;
|
||||
u_register_t r1;
|
||||
u_register_t r2;
|
||||
u_register_t r3;
|
||||
u_register_t r4;
|
||||
u_register_t r5;
|
||||
u_register_t r6;
|
||||
u_register_t r7;
|
||||
u_register_t r8;
|
||||
u_register_t r9;
|
||||
u_register_t r10;
|
||||
u_register_t r11;
|
||||
u_register_t r12;
|
||||
/* spsr_usr doesn't exist */
|
||||
u_register_t sp_usr;
|
||||
u_register_t lr_usr;
|
||||
u_register_t spsr_irq;
|
||||
u_register_t sp_irq;
|
||||
u_register_t lr_irq;
|
||||
u_register_t spsr_fiq;
|
||||
u_register_t sp_fiq;
|
||||
u_register_t lr_fiq;
|
||||
u_register_t spsr_svc;
|
||||
u_register_t sp_svc;
|
||||
u_register_t lr_svc;
|
||||
u_register_t spsr_abt;
|
||||
u_register_t sp_abt;
|
||||
u_register_t lr_abt;
|
||||
u_register_t spsr_und;
|
||||
u_register_t sp_und;
|
||||
u_register_t lr_und;
|
||||
u_register_t spsr_mon;
|
||||
/*
|
||||
* `sp_mon` will point to the C runtime stack in monitor mode. But prior
|
||||
* to exit from SMC, this will point to the `smc_ctx_t` so that
|
||||
* on next entry due to SMC, the `smc_ctx_t` can be easily accessed.
|
||||
*/
|
||||
u_register_t sp_mon;
|
||||
u_register_t lr_mon;
|
||||
u_register_t scr;
|
||||
u_register_t pmcr;
|
||||
/*
|
||||
* The workaround for CVE-2017-5715 requires storing information in
|
||||
* the bottom 3 bits of the stack pointer. Add a padding field to
|
||||
* force the size of the struct to be a multiple of 8.
|
||||
*/
|
||||
u_register_t pad;
|
||||
} smc_ctx_t __aligned(8);
|
||||
|
||||
/*
|
||||
* Compile time assertions related to the 'smc_context' structure to
|
||||
* ensure that the assembler and the compiler view of the offsets of
|
||||
* the structure members is the same.
|
||||
*/
|
||||
CASSERT(SMC_CTX_GPREG_R0 == __builtin_offsetof(smc_ctx_t, r0), \
|
||||
assert_smc_ctx_greg_r0_offset_mismatch);
|
||||
CASSERT(SMC_CTX_GPREG_R1 == __builtin_offsetof(smc_ctx_t, r1), \
|
||||
assert_smc_ctx_greg_r1_offset_mismatch);
|
||||
CASSERT(SMC_CTX_GPREG_R2 == __builtin_offsetof(smc_ctx_t, r2), \
|
||||
assert_smc_ctx_greg_r2_offset_mismatch);
|
||||
CASSERT(SMC_CTX_GPREG_R3 == __builtin_offsetof(smc_ctx_t, r3), \
|
||||
assert_smc_ctx_greg_r3_offset_mismatch);
|
||||
CASSERT(SMC_CTX_GPREG_R4 == __builtin_offsetof(smc_ctx_t, r4), \
|
||||
assert_smc_ctx_greg_r4_offset_mismatch);
|
||||
CASSERT(SMC_CTX_SP_USR == __builtin_offsetof(smc_ctx_t, sp_usr), \
|
||||
assert_smc_ctx_sp_usr_offset_mismatch);
|
||||
CASSERT(SMC_CTX_LR_MON == __builtin_offsetof(smc_ctx_t, lr_mon), \
|
||||
assert_smc_ctx_lr_mon_offset_mismatch);
|
||||
CASSERT(SMC_CTX_SPSR_MON == __builtin_offsetof(smc_ctx_t, spsr_mon), \
|
||||
assert_smc_ctx_spsr_mon_offset_mismatch);
|
||||
|
||||
CASSERT((sizeof(smc_ctx_t) & 0x7U) == 0U, assert_smc_ctx_not_aligned);
|
||||
CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch);
|
||||
|
||||
/* Convenience macros to return from SMC handler */
|
||||
#define SMC_RET0(_h) { \
|
||||
return (uintptr_t)(_h); \
|
||||
}
|
||||
#define SMC_RET1(_h, _r0) { \
|
||||
((smc_ctx_t *)(_h))->r0 = (_r0); \
|
||||
SMC_RET0(_h); \
|
||||
}
|
||||
#define SMC_RET2(_h, _r0, _r1) { \
|
||||
((smc_ctx_t *)(_h))->r1 = (_r1); \
|
||||
SMC_RET1(_h, (_r0)); \
|
||||
}
|
||||
#define SMC_RET3(_h, _r0, _r1, _r2) { \
|
||||
((smc_ctx_t *)(_h))->r2 = (_r2); \
|
||||
SMC_RET2(_h, (_r0), (_r1)); \
|
||||
}
|
||||
#define SMC_RET4(_h, _r0, _r1, _r2, _r3) { \
|
||||
((smc_ctx_t *)(_h))->r3 = (_r3); \
|
||||
SMC_RET3(_h, (_r0), (_r1), (_r2)); \
|
||||
}
|
||||
#define SMC_RET5(_h, _r0, _r1, _r2, _r3, _r4) { \
|
||||
((smc_ctx_t *)(_h))->r4 = (_r4); \
|
||||
SMC_RET4(_h, (_r0), (_r1), (_r2), (_r3)); \
|
||||
}
|
||||
#define SMC_RET6(_h, _r0, _r1, _r2, _r3, _r4, _r5) { \
|
||||
((smc_ctx_t *)(_h))->r5 = (_r5); \
|
||||
SMC_RET5(_h, (_r0), (_r1), (_r2), (_r3), (_r4)); \
|
||||
}
|
||||
#define SMC_RET7(_h, _r0, _r1, _r2, _r3, _r4, _r5, _r6) { \
|
||||
((smc_ctx_t *)(_h))->r6 = (_r6); \
|
||||
SMC_RET6(_h, (_r0), (_r1), (_r2), (_r3), (_r4), (_r5)); \
|
||||
}
|
||||
#define SMC_RET8(_h, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) { \
|
||||
((smc_ctx_t *)(_h))->r7 = (_r7); \
|
||||
SMC_RET7(_h, (_r0), (_r1), (_r2), (_r3), (_r4), (_r5), (_r6)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper macro to retrieve the SMC parameters from smc_ctx_t.
|
||||
*/
|
||||
#define get_smc_params_from_ctx(_hdl, _r1, _r2, _r3, _r4) { \
|
||||
_r1 = ((smc_ctx_t *)_hdl)->r1; \
|
||||
_r2 = ((smc_ctx_t *)_hdl)->r2; \
|
||||
_r3 = ((smc_ctx_t *)_hdl)->r3; \
|
||||
_r4 = ((smc_ctx_t *)_hdl)->r4; \
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Helper APIs for setting and retrieving appropriate `smc_ctx_t`.
|
||||
* These functions need to implemented by the BL including this library.
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Get the pointer to `smc_ctx_t` corresponding to the security state. */
|
||||
void *smc_get_ctx(unsigned int security_state);
|
||||
|
||||
/* Set the next `smc_ctx_t` corresponding to the security state. */
|
||||
void smc_set_next_ctx(unsigned int security_state);
|
||||
|
||||
/* Get the pointer to next `smc_ctx_t` already set by `smc_set_next_ctx()`. */
|
||||
void *smc_get_next_ctx(void);
|
||||
|
||||
#endif /*__ASSEMBLER__*/
|
||||
|
||||
#endif /* SMCCC_HELPERS_H */
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef SMCCC_MACROS_S
|
||||
#define SMCCC_MACROS_S
|
||||
|
||||
#include <arch.h>
|
||||
|
||||
/*
|
||||
* Macro to save the General purpose registers (r0 - r12), the banked
|
||||
* spsr, lr, sp registers and the `scr` register to the SMC context on entry
|
||||
* due a SMC call. The `lr` of the current mode (monitor) is expected to be
|
||||
* already saved. The `sp` must point to the `smc_ctx_t` to save to.
|
||||
* Additionally, also save the 'pmcr' register as this is updated whilst
|
||||
* executing in the secure world.
|
||||
*/
|
||||
.macro smccc_save_gp_mode_regs
|
||||
/* Save r0 - r12 in the SMC context */
|
||||
stm sp, {r0-r12}
|
||||
mov r0, sp
|
||||
add r0, r0, #SMC_CTX_SP_USR
|
||||
|
||||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
||||
/* Must be in secure state to restore Monitor mode */
|
||||
ldcopr r4, SCR
|
||||
bic r2, r4, #SCR_NS_BIT
|
||||
stcopr r2, SCR
|
||||
isb
|
||||
|
||||
cps #MODE32_sys
|
||||
stm r0!, {sp, lr}
|
||||
|
||||
cps #MODE32_irq
|
||||
mrs r2, spsr
|
||||
stm r0!, {r2, sp, lr}
|
||||
|
||||
cps #MODE32_fiq
|
||||
mrs r2, spsr
|
||||
stm r0!, {r2, sp, lr}
|
||||
|
||||
cps #MODE32_svc
|
||||
mrs r2, spsr
|
||||
stm r0!, {r2, sp, lr}
|
||||
|
||||
cps #MODE32_abt
|
||||
mrs r2, spsr
|
||||
stm r0!, {r2, sp, lr}
|
||||
|
||||
cps #MODE32_und
|
||||
mrs r2, spsr
|
||||
stm r0!, {r2, sp, lr}
|
||||
|
||||
/* lr_mon is already saved by caller */
|
||||
cps #MODE32_mon
|
||||
mrs r2, spsr
|
||||
stm r0!, {r2}
|
||||
|
||||
stcopr r4, SCR
|
||||
#else
|
||||
/* Save the banked registers including the current SPSR and LR */
|
||||
mrs r4, sp_usr
|
||||
mrs r5, lr_usr
|
||||
mrs r6, spsr_irq
|
||||
mrs r7, sp_irq
|
||||
mrs r8, lr_irq
|
||||
mrs r9, spsr_fiq
|
||||
mrs r10, sp_fiq
|
||||
mrs r11, lr_fiq
|
||||
mrs r12, spsr_svc
|
||||
stm r0!, {r4-r12}
|
||||
|
||||
mrs r4, sp_svc
|
||||
mrs r5, lr_svc
|
||||
mrs r6, spsr_abt
|
||||
mrs r7, sp_abt
|
||||
mrs r8, lr_abt
|
||||
mrs r9, spsr_und
|
||||
mrs r10, sp_und
|
||||
mrs r11, lr_und
|
||||
mrs r12, spsr
|
||||
stm r0!, {r4-r12}
|
||||
/* lr_mon is already saved by caller */
|
||||
|
||||
ldcopr r4, SCR
|
||||
|
||||
#if ARM_ARCH_MAJOR > 7
|
||||
/*
|
||||
* Check if earlier initialization of SDCR.SCCD to 1
|
||||
* failed, meaning that ARMv8-PMU is not implemented,
|
||||
* cycle counting is not disabled and PMCR should be
|
||||
* saved in Non-secure context.
|
||||
*/
|
||||
ldcopr r5, SDCR
|
||||
tst r5, #SDCR_SCCD_BIT
|
||||
bne 1f
|
||||
#endif
|
||||
/* Secure Cycle Counter is not disabled */
|
||||
#endif
|
||||
ldcopr r5, PMCR
|
||||
|
||||
/* Check caller's security state */
|
||||
tst r4, #SCR_NS_BIT
|
||||
beq 2f
|
||||
|
||||
/* Save PMCR if called from Non-secure state */
|
||||
str r5, [sp, #SMC_CTX_PMCR]
|
||||
|
||||
/* Disable cycle counter when event counting is prohibited */
|
||||
2: orr r5, r5, #PMCR_DP_BIT
|
||||
stcopr r5, PMCR
|
||||
isb
|
||||
1: str r4, [sp, #SMC_CTX_SCR]
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Macro to restore the `smc_ctx_t`, which includes the General purpose
|
||||
* registers and banked mode registers, and exit from the monitor mode.
|
||||
* r0 must point to the `smc_ctx_t` to restore from.
|
||||
*/
|
||||
.macro monitor_exit
|
||||
/*
|
||||
* Save the current sp and restore the smc context
|
||||
* pointer to sp which will be used for handling the
|
||||
* next SMC.
|
||||
*/
|
||||
str sp, [r0, #SMC_CTX_SP_MON]
|
||||
mov sp, r0
|
||||
|
||||
/*
|
||||
* Restore SCR first so that we access the right banked register
|
||||
* when the other mode registers are restored.
|
||||
*/
|
||||
ldr r1, [r0, #SMC_CTX_SCR]
|
||||
stcopr r1, SCR
|
||||
isb
|
||||
|
||||
/*
|
||||
* Restore PMCR when returning to Non-secure state
|
||||
*/
|
||||
tst r1, #SCR_NS_BIT
|
||||
beq 2f
|
||||
|
||||
/*
|
||||
* Back to Non-secure state
|
||||
*/
|
||||
#if ARM_ARCH_MAJOR > 7
|
||||
/*
|
||||
* Check if earlier initialization SDCR.SCCD to 1
|
||||
* failed, meaning that ARMv8-PMU is not implemented and
|
||||
* PMCR should be restored from Non-secure context.
|
||||
*/
|
||||
ldcopr r1, SDCR
|
||||
tst r1, #SDCR_SCCD_BIT
|
||||
bne 2f
|
||||
#endif
|
||||
/*
|
||||
* Restore the PMCR register.
|
||||
*/
|
||||
ldr r1, [r0, #SMC_CTX_PMCR]
|
||||
stcopr r1, PMCR
|
||||
2:
|
||||
/* Restore the banked registers including the current SPSR */
|
||||
add r1, r0, #SMC_CTX_SP_USR
|
||||
|
||||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
||||
/* Must be in secure state to restore Monitor mode */
|
||||
ldcopr r4, SCR
|
||||
bic r2, r4, #SCR_NS_BIT
|
||||
stcopr r2, SCR
|
||||
isb
|
||||
|
||||
cps #MODE32_sys
|
||||
ldm r1!, {sp, lr}
|
||||
|
||||
cps #MODE32_irq
|
||||
ldm r1!, {r2, sp, lr}
|
||||
msr spsr_fsxc, r2
|
||||
|
||||
cps #MODE32_fiq
|
||||
ldm r1!, {r2, sp, lr}
|
||||
msr spsr_fsxc, r2
|
||||
|
||||
cps #MODE32_svc
|
||||
ldm r1!, {r2, sp, lr}
|
||||
msr spsr_fsxc, r2
|
||||
|
||||
cps #MODE32_abt
|
||||
ldm r1!, {r2, sp, lr}
|
||||
msr spsr_fsxc, r2
|
||||
|
||||
cps #MODE32_und
|
||||
ldm r1!, {r2, sp, lr}
|
||||
msr spsr_fsxc, r2
|
||||
|
||||
cps #MODE32_mon
|
||||
ldm r1!, {r2}
|
||||
msr spsr_fsxc, r2
|
||||
|
||||
stcopr r4, SCR
|
||||
isb
|
||||
#else
|
||||
ldm r1!, {r4-r12}
|
||||
msr sp_usr, r4
|
||||
msr lr_usr, r5
|
||||
msr spsr_irq, r6
|
||||
msr sp_irq, r7
|
||||
msr lr_irq, r8
|
||||
msr spsr_fiq, r9
|
||||
msr sp_fiq, r10
|
||||
msr lr_fiq, r11
|
||||
msr spsr_svc, r12
|
||||
|
||||
ldm r1!, {r4-r12}
|
||||
msr sp_svc, r4
|
||||
msr lr_svc, r5
|
||||
msr spsr_abt, r6
|
||||
msr sp_abt, r7
|
||||
msr lr_abt, r8
|
||||
msr spsr_und, r9
|
||||
msr sp_und, r10
|
||||
msr lr_und, r11
|
||||
/*
|
||||
* Use the `_fsxc` suffix explicitly to instruct the assembler
|
||||
* to update all the 32 bits of SPSR. Else, by default, the
|
||||
* assembler assumes `_fc` suffix which only modifies
|
||||
* f->[31:24] and c->[7:0] bits of SPSR.
|
||||
*/
|
||||
msr spsr_fsxc, r12
|
||||
#endif
|
||||
|
||||
/* Restore the LR */
|
||||
ldr lr, [r0, #SMC_CTX_LR_MON]
|
||||
|
||||
/* Restore the rest of the general purpose registers */
|
||||
ldm r0, {r0-r12}
|
||||
exception_return
|
||||
.endm
|
||||
|
||||
#endif /* SMCCC_MACROS_S */
|
||||
Reference in New Issue
Block a user