Home | History | Annotate | Download | only in aarch32
      1 /*
      2  * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * SPDX-License-Identifier: BSD-3-Clause
      5  */
      6 
      7 #ifndef __ARCH_HELPERS_H__
      8 #define __ARCH_HELPERS_H__
      9 
     10 #include <arch.h>	/* for additional register definitions */
     11 #include <stdint.h>
     12 #include <sys/types.h>
     13 
     14 /**********************************************************************
     15  * Macros which create inline functions to read or write CPU system
     16  * registers
     17  *********************************************************************/
     18 
     19 #define _DEFINE_COPROCR_WRITE_FUNC(_name, coproc, opc1, CRn, CRm, opc2)	\
     20 static inline void write_## _name(u_register_t v)			\
     21 {									\
     22 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
     23 }
     24 
     25 #define _DEFINE_COPROCR_READ_FUNC(_name, coproc, opc1, CRn, CRm, opc2)	\
     26 static inline u_register_t read_ ## _name(void)				\
     27 {									\
     28 	u_register_t v;							\
     29 	__asm__ volatile ("mrc "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : "=r" (v));\
     30 	return v;							\
     31 }
     32 
     33 /*
     34  *  The undocumented %Q and %R extended asm are used to implemented the below
     35  *  64 bit `mrrc` and `mcrr` instructions. It works only on Little Endian
     36  *  systems for GCC versions < 4.6. Above GCC 4.6, both Little Endian and
     37  *  Big Endian systems generate the right instruction encoding.
     38  */
     39 #if !(__clang__ || __GNUC__ > (4) || __GNUC__ == (4) && __GNUC_MINOR__ >= (6))
     40 #error "clang or GCC 4.6 or above is required to build AArch32 Trusted Firmware"
     41 #endif
     42 
     43 #define _DEFINE_COPROCR_WRITE_FUNC_64(_name, coproc, opc1, CRm)		\
     44 static inline void write64_## _name(uint64_t v)				\
     45 {									\
     46 	__asm__ volatile ("mcrr "#coproc","#opc1", %Q0, %R0,"#CRm : : "r" (v));\
     47 }
     48 
     49 #define _DEFINE_COPROCR_READ_FUNC_64(_name, coproc, opc1, CRm)		\
     50 static inline uint64_t read64_## _name(void)				\
     51 {	uint64_t v;							\
     52 	__asm__ volatile ("mrrc "#coproc","#opc1", %Q0, %R0,"#CRm : "=r" (v));\
     53 	return v;							\
     54 }
     55 
     56 #define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name)			\
     57 static inline u_register_t read_ ## _name(void)				\
     58 {									\
     59 	u_register_t v;							\
     60 	__asm__ volatile ("mrs %0, " #_reg_name : "=r" (v));		\
     61 	return v;							\
     62 }
     63 
     64 #define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)			\
     65 static inline void write_ ## _name(u_register_t v)			\
     66 {									\
     67 	__asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v));	\
     68 }
     69 
     70 #define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name)		\
     71 static inline void write_ ## _name(const u_register_t v)		\
     72 {									\
     73 	__asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v));	\
     74 }
     75 
     76 /* Define read function for coproc register */
     77 #define DEFINE_COPROCR_READ_FUNC(_name, ...) 				\
     78 	_DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__)
     79 
     80 /* Define read & write function for coproc register */
     81 #define DEFINE_COPROCR_RW_FUNCS(_name, ...) 				\
     82 	_DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__)			\
     83 	_DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__)
     84 
     85 /* Define 64 bit read function for coproc register */
     86 #define DEFINE_COPROCR_READ_FUNC_64(_name, ...) 			\
     87 	_DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__)
     88 
     89 /* Define 64 bit read & write function for coproc register */
     90 #define DEFINE_COPROCR_RW_FUNCS_64(_name, ...) 				\
     91 	_DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__)		\
     92 	_DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__)
     93 
     94 /* Define read & write function for system register */
     95 #define DEFINE_SYSREG_RW_FUNCS(_name)					\
     96 	_DEFINE_SYSREG_READ_FUNC(_name, _name)				\
     97 	_DEFINE_SYSREG_WRITE_FUNC(_name, _name)
     98 
     99 /**********************************************************************
    100  * Macros to create inline functions for tlbi operations
    101  *********************************************************************/
    102 
    103 #if ERRATA_A57_813419
    104 /*
    105  * Define function for TLBI instruction with type specifier that
    106  * implements the workaround for errata 813419 of Cortex-A57
    107  */
    108 #define _DEFINE_TLBIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2)		\
    109 static inline void tlbi##_op(void)					\
    110 {									\
    111 	u_register_t v = 0;						\
    112 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    113 	__asm__ volatile ("dsb ish");\
    114 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    115 }
    116 
    117 #define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2)	\
    118 static inline void tlbi##_op(u_register_t v)				\
    119 {									\
    120 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    121 	__asm__ volatile ("dsb ish");\
    122 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    123 }
    124 #else
    125 #define _DEFINE_TLBIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2)		\
    126 static inline void tlbi##_op(void)					\
    127 {									\
    128 	u_register_t v = 0;						\
    129 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    130 }
    131 
    132 #define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2)	\
    133 static inline void tlbi##_op(u_register_t v)				\
    134 {									\
    135 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    136 }
    137 #endif /* ERRATA_A57_813419 */
    138 
    139 #define _DEFINE_BPIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2)		\
    140 static inline void bpi##_op(void)					\
    141 {									\
    142 	u_register_t v = 0;						\
    143 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    144 }
    145 
    146 /* Define function for simple TLBI operation */
    147 #define DEFINE_TLBIOP_FUNC(_op, ...)					\
    148 	_DEFINE_TLBIOP_FUNC(_op, __VA_ARGS__)
    149 
    150 /* Define function for TLBI operation with register parameter */
    151 #define DEFINE_TLBIOP_PARAM_FUNC(_op, ...)				\
    152 	_DEFINE_TLBIOP_PARAM_FUNC(_op, __VA_ARGS__)
    153 
    154 /* Define function for simple BPI operation */
    155 #define DEFINE_BPIOP_FUNC(_op, ...)					\
    156 	_DEFINE_BPIOP_FUNC(_op, __VA_ARGS__)
    157 
    158 /**********************************************************************
    159  * Macros to create inline functions for DC operations
    160  *********************************************************************/
    161 #define _DEFINE_DCOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2)	\
    162 static inline void dc##_op(u_register_t v)				\
    163 {									\
    164 	__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
    165 }
    166 
    167 /* Define function for DC operation with register parameter */
    168 #define DEFINE_DCOP_PARAM_FUNC(_op, ...)				\
    169 	_DEFINE_DCOP_PARAM_FUNC(_op, __VA_ARGS__)
    170 
    171 /**********************************************************************
    172  * Macros to create inline functions for system instructions
    173  *********************************************************************/
    174  /* Define function for simple system instruction */
    175 #define DEFINE_SYSOP_FUNC(_op)						\
    176 static inline void _op(void)						\
    177 {									\
    178 	__asm__ (#_op);							\
    179 }
    180 
    181 
    182 /* Define function for system instruction with type specifier */
    183 #define DEFINE_SYSOP_TYPE_FUNC(_op, _type)				\
    184 static inline void _op ## _type(void)					\
    185 {									\
    186 	__asm__ (#_op " " #_type);					\
    187 }
    188 
    189 /* Define function for system instruction with register parameter */
    190 #define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type)			\
    191 static inline void _op ## _type(u_register_t v)				\
    192 {									\
    193 	 __asm__ (#_op " " #_type ", %0" : : "r" (v));			\
    194 }
    195 
    196 void flush_dcache_range(uintptr_t addr, size_t size);
    197 void clean_dcache_range(uintptr_t addr, size_t size);
    198 void inv_dcache_range(uintptr_t addr, size_t size);
    199 
    200 void dcsw_op_louis(u_register_t op_type);
    201 void dcsw_op_all(u_register_t op_type);
    202 
    203 void disable_mmu_secure(void);
    204 void disable_mmu_icache_secure(void);
    205 
    206 DEFINE_SYSOP_FUNC(wfi)
    207 DEFINE_SYSOP_FUNC(wfe)
    208 DEFINE_SYSOP_FUNC(sev)
    209 DEFINE_SYSOP_TYPE_FUNC(dsb, sy)
    210 DEFINE_SYSOP_TYPE_FUNC(dmb, sy)
    211 DEFINE_SYSOP_TYPE_FUNC(dmb, st)
    212 DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
    213 DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
    214 DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
    215 DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
    216 DEFINE_SYSOP_TYPE_FUNC(dmb, ishst)
    217 DEFINE_SYSOP_FUNC(isb)
    218 
    219 void __dead2 smc(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3,
    220 		 uint32_t r4, uint32_t r5, uint32_t r6, uint32_t r7);
    221 
    222 DEFINE_SYSREG_RW_FUNCS(spsr)
    223 DEFINE_SYSREG_RW_FUNCS(cpsr)
    224 
    225 /*******************************************************************************
    226  * System register accessor prototypes
    227  ******************************************************************************/
    228 DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR)
    229 DEFINE_COPROCR_READ_FUNC(midr, MIDR)
    230 DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1)
    231 DEFINE_COPROCR_READ_FUNC(isr, ISR)
    232 DEFINE_COPROCR_READ_FUNC(clidr, CLIDR)
    233 DEFINE_COPROCR_READ_FUNC_64(cntpct, CNTPCT_64)
    234 
    235 DEFINE_COPROCR_RW_FUNCS(scr, SCR)
    236 DEFINE_COPROCR_RW_FUNCS(ctr, CTR)
    237 DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR)
    238 DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR)
    239 DEFINE_COPROCR_RW_FUNCS(hcr, HCR)
    240 DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR)
    241 DEFINE_COPROCR_RW_FUNCS(cntfrq, CNTFRQ)
    242 DEFINE_COPROCR_RW_FUNCS(cnthctl, CNTHCTL)
    243 DEFINE_COPROCR_RW_FUNCS(mair0, MAIR0)
    244 DEFINE_COPROCR_RW_FUNCS(mair1, MAIR1)
    245 DEFINE_COPROCR_RW_FUNCS(ttbcr, TTBCR)
    246 DEFINE_COPROCR_RW_FUNCS(ttbr0, TTBR0)
    247 DEFINE_COPROCR_RW_FUNCS_64(ttbr0, TTBR0_64)
    248 DEFINE_COPROCR_RW_FUNCS(ttbr1, TTBR1)
    249 DEFINE_COPROCR_RW_FUNCS(vpidr, VPIDR)
    250 DEFINE_COPROCR_RW_FUNCS(vmpidr, VMPIDR)
    251 DEFINE_COPROCR_RW_FUNCS_64(vttbr, VTTBR_64)
    252 DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64)
    253 DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64)
    254 DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR)
    255 DEFINE_COPROCR_RW_FUNCS(hstr, HSTR)
    256 
    257 DEFINE_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE)
    258 DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE)
    259 DEFINE_COPROCR_RW_FUNCS(icc_sre_el3, ICC_MSRE)
    260 DEFINE_COPROCR_RW_FUNCS(icc_pmr_el1, ICC_PMR)
    261 DEFINE_COPROCR_RW_FUNCS(icc_rpr_el1, ICC_RPR)
    262 DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el3, ICC_MGRPEN1)
    263 DEFINE_COPROCR_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0)
    264 DEFINE_COPROCR_RW_FUNCS(icc_hppir0_el1, ICC_HPPIR0)
    265 DEFINE_COPROCR_RW_FUNCS(icc_hppir1_el1, ICC_HPPIR1)
    266 DEFINE_COPROCR_RW_FUNCS(icc_iar0_el1, ICC_IAR0)
    267 DEFINE_COPROCR_RW_FUNCS(icc_iar1_el1, ICC_IAR1)
    268 DEFINE_COPROCR_RW_FUNCS(icc_eoir0_el1, ICC_EOIR0)
    269 DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1)
    270 DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64)
    271 
    272 DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
    273 DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
    274 DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
    275 
    276 /*
    277  * TLBI operation prototypes
    278  */
    279 DEFINE_TLBIOP_FUNC(all, TLBIALL)
    280 DEFINE_TLBIOP_FUNC(allis, TLBIALLIS)
    281 DEFINE_TLBIOP_PARAM_FUNC(mva, TLBIMVA)
    282 DEFINE_TLBIOP_PARAM_FUNC(mvaa, TLBIMVAA)
    283 DEFINE_TLBIOP_PARAM_FUNC(mvaais, TLBIMVAAIS)
    284 
    285 /*
    286  * BPI operation prototypes.
    287  */
    288 DEFINE_BPIOP_FUNC(allis, BPIALLIS)
    289 
    290 /*
    291  * DC operation prototypes
    292  */
    293 DEFINE_DCOP_PARAM_FUNC(civac, DCCIMVAC)
    294 DEFINE_DCOP_PARAM_FUNC(ivac, DCIMVAC)
    295 DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC)
    296 
    297 /* Previously defined accessor functions with incomplete register names  */
    298 #define dsb()			dsbsy()
    299 
    300 #define IS_IN_SECURE() \
    301 	(GET_NS_BIT(read_scr()) == 0)
    302 
    303  /*
    304   * If EL3 is AArch32, then secure PL1 and monitor mode correspond to EL3
    305   */
    306 #define IS_IN_EL3() \
    307 	((GET_M32(read_cpsr()) == MODE32_mon) ||	\
    308 		(IS_IN_SECURE() && (GET_M32(read_cpsr()) != MODE32_usr)))
    309 
    310 /* Macros for compatibility with AArch64 system registers */
    311 #define read_mpidr_el1()	read_mpidr()
    312 
    313 #define read_scr_el3()		read_scr()
    314 #define write_scr_el3(_v)	write_scr(_v)
    315 
    316 #define read_hcr_el2()		read_hcr()
    317 #define write_hcr_el2(_v)	write_hcr(_v)
    318 
    319 #define read_cpacr_el1()	read_cpacr()
    320 #define write_cpacr_el1(_v)	write_cpacr(_v)
    321 
    322 #define read_cntfrq_el0()	read_cntfrq()
    323 #define write_cntfrq_el0(_v)	write_cntfrq(_v)
    324 #define read_isr_el1()		read_isr()
    325 
    326 #define read_cntpct_el0()	read64_cntpct()
    327 
    328 #define read_ctr_el0()		read_ctr()
    329 
    330 #define write_icc_sgi0r_el1(_v) \
    331 		write64_icc_sgi0r_el1(_v)
    332 
    333 #endif /* __ARCH_HELPERS_H__ */
    334