Home | History | Annotate | Download | only in aarch64
      1 /*
      2  * Copyright (c) 2013-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 <cdefs.h>	/* For __dead2 */
     12 #include <stdint.h>
     13 #include <sys/types.h>
     14 
     15 /**********************************************************************
     16  * Macros which create inline functions to read or write CPU system
     17  * registers
     18  *********************************************************************/
     19 
     20 #define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name)		\
     21 static inline uint64_t read_ ## _name(void)			\
     22 {								\
     23 	uint64_t v;						\
     24 	__asm__ volatile ("mrs %0, " #_reg_name : "=r" (v));	\
     25 	return v;						\
     26 }
     27 
     28 #define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)			\
     29 static inline void write_ ## _name(uint64_t v)				\
     30 {									\
     31 	__asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v));	\
     32 }
     33 
     34 #define SYSREG_WRITE_CONST(reg_name, v)				\
     35 	__asm__ volatile ("msr " #reg_name ", %0" : : "i" (v))
     36 
     37 /* Define read function for system register */
     38 #define DEFINE_SYSREG_READ_FUNC(_name) 			\
     39 	_DEFINE_SYSREG_READ_FUNC(_name, _name)
     40 
     41 /* Define read & write function for system register */
     42 #define DEFINE_SYSREG_RW_FUNCS(_name)			\
     43 	_DEFINE_SYSREG_READ_FUNC(_name, _name)		\
     44 	_DEFINE_SYSREG_WRITE_FUNC(_name, _name)
     45 
     46 /* Define read & write function for renamed system register */
     47 #define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name)	\
     48 	_DEFINE_SYSREG_READ_FUNC(_name, _reg_name)	\
     49 	_DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
     50 
     51 /* Define read function for renamed system register */
     52 #define DEFINE_RENAME_SYSREG_READ_FUNC(_name, _reg_name)	\
     53 	_DEFINE_SYSREG_READ_FUNC(_name, _reg_name)
     54 
     55 /* Define write function for renamed system register */
     56 #define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name)	\
     57 	_DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
     58 
     59 /**********************************************************************
     60  * Macros to create inline functions for system instructions
     61  *********************************************************************/
     62 
     63 /* Define function for simple system instruction */
     64 #define DEFINE_SYSOP_FUNC(_op)				\
     65 static inline void _op(void)				\
     66 {							\
     67 	__asm__ (#_op);					\
     68 }
     69 
     70 /* Define function for system instruction with type specifier */
     71 #define DEFINE_SYSOP_TYPE_FUNC(_op, _type)		\
     72 static inline void _op ## _type(void)			\
     73 {							\
     74 	__asm__ (#_op " " #_type);			\
     75 }
     76 
     77 /* Define function for system instruction with register parameter */
     78 #define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type)	\
     79 static inline void _op ## _type(uint64_t v)		\
     80 {							\
     81 	 __asm__ (#_op " " #_type ", %0" : : "r" (v));	\
     82 }
     83 
     84 /*******************************************************************************
     85  * TLB maintenance accessor prototypes
     86  ******************************************************************************/
     87 
     88 #if ERRATA_A57_813419
     89 /*
     90  * Define function for TLBI instruction with type specifier that implements
     91  * the workaround for errata 813419 of Cortex-A57.
     92  */
     93 #define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(_type)\
     94 static inline void tlbi ## _type(void)			\
     95 {							\
     96 	__asm__("tlbi " #_type "\n"			\
     97 		"dsb ish\n"				\
     98 		"tlbi " #_type);			\
     99 }
    100 
    101 /*
    102  * Define function for TLBI instruction with register parameter that implements
    103  * the workaround for errata 813419 of Cortex-A57.
    104  */
    105 #define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(_type)	\
    106 static inline void tlbi ## _type(uint64_t v)			\
    107 {								\
    108 	__asm__("tlbi " #_type ", %0\n"				\
    109 		"dsb ish\n"					\
    110 		"tlbi " #_type ", %0" : : "r" (v));		\
    111 }
    112 #endif /* ERRATA_A57_813419 */
    113 
    114 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
    115 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is)
    116 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2)
    117 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is)
    118 #if ERRATA_A57_813419
    119 DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(alle3)
    120 DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(alle3is)
    121 #else
    122 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3)
    123 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is)
    124 #endif
    125 DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1)
    126 
    127 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is)
    128 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is)
    129 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is)
    130 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is)
    131 #if ERRATA_A57_813419
    132 DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(vae3is)
    133 DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(vale3is)
    134 #else
    135 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae3is)
    136 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale3is)
    137 #endif
    138 
    139 /*******************************************************************************
    140  * Cache maintenance accessor prototypes
    141  ******************************************************************************/
    142 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw)
    143 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw)
    144 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw)
    145 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac)
    146 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac)
    147 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac)
    148 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau)
    149 DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva)
    150 
    151 /*******************************************************************************
    152  * Address translation accessor prototypes
    153  ******************************************************************************/
    154 DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1r)
    155 DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1w)
    156 DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0r)
    157 DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0w)
    158 
    159 void flush_dcache_range(uintptr_t addr, size_t size);
    160 void clean_dcache_range(uintptr_t addr, size_t size);
    161 void inv_dcache_range(uintptr_t addr, size_t size);
    162 
    163 void dcsw_op_louis(u_register_t op_type);
    164 void dcsw_op_all(u_register_t op_type);
    165 
    166 void disable_mmu_el1(void);
    167 void disable_mmu_el3(void);
    168 void disable_mmu_icache_el1(void);
    169 void disable_mmu_icache_el3(void);
    170 
    171 /*******************************************************************************
    172  * Misc. accessor prototypes
    173  ******************************************************************************/
    174 
    175 #define write_daifclr(val) SYSREG_WRITE_CONST(daifclr, val)
    176 #define write_daifset(val) SYSREG_WRITE_CONST(daifset, val)
    177 
    178 DEFINE_SYSREG_READ_FUNC(par_el1)
    179 DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
    180 DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
    181 DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1)
    182 DEFINE_SYSREG_READ_FUNC(CurrentEl)
    183 DEFINE_SYSREG_RW_FUNCS(daif)
    184 DEFINE_SYSREG_RW_FUNCS(spsr_el1)
    185 DEFINE_SYSREG_RW_FUNCS(spsr_el2)
    186 DEFINE_SYSREG_RW_FUNCS(spsr_el3)
    187 DEFINE_SYSREG_RW_FUNCS(elr_el1)
    188 DEFINE_SYSREG_RW_FUNCS(elr_el2)
    189 DEFINE_SYSREG_RW_FUNCS(elr_el3)
    190 
    191 DEFINE_SYSOP_FUNC(wfi)
    192 DEFINE_SYSOP_FUNC(wfe)
    193 DEFINE_SYSOP_FUNC(sev)
    194 DEFINE_SYSOP_TYPE_FUNC(dsb, sy)
    195 DEFINE_SYSOP_TYPE_FUNC(dmb, sy)
    196 DEFINE_SYSOP_TYPE_FUNC(dmb, st)
    197 DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
    198 DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
    199 DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
    200 DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
    201 DEFINE_SYSOP_TYPE_FUNC(dmb, ishst)
    202 DEFINE_SYSOP_FUNC(isb)
    203 
    204 uint32_t get_afflvl_shift(uint32_t);
    205 uint32_t mpidr_mask_lower_afflvls(uint64_t, uint32_t);
    206 
    207 
    208 void __dead2 eret(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3,
    209 		  uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7);
    210 void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3,
    211 		 uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7);
    212 
    213 /*******************************************************************************
    214  * System register accessor prototypes
    215  ******************************************************************************/
    216 DEFINE_SYSREG_READ_FUNC(midr_el1)
    217 DEFINE_SYSREG_READ_FUNC(mpidr_el1)
    218 DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1)
    219 
    220 DEFINE_SYSREG_RW_FUNCS(scr_el3)
    221 DEFINE_SYSREG_RW_FUNCS(hcr_el2)
    222 
    223 DEFINE_SYSREG_RW_FUNCS(vbar_el1)
    224 DEFINE_SYSREG_RW_FUNCS(vbar_el2)
    225 DEFINE_SYSREG_RW_FUNCS(vbar_el3)
    226 
    227 DEFINE_SYSREG_RW_FUNCS(sctlr_el1)
    228 DEFINE_SYSREG_RW_FUNCS(sctlr_el2)
    229 DEFINE_SYSREG_RW_FUNCS(sctlr_el3)
    230 
    231 DEFINE_SYSREG_RW_FUNCS(actlr_el1)
    232 DEFINE_SYSREG_RW_FUNCS(actlr_el2)
    233 DEFINE_SYSREG_RW_FUNCS(actlr_el3)
    234 
    235 DEFINE_SYSREG_RW_FUNCS(esr_el1)
    236 DEFINE_SYSREG_RW_FUNCS(esr_el2)
    237 DEFINE_SYSREG_RW_FUNCS(esr_el3)
    238 
    239 DEFINE_SYSREG_RW_FUNCS(afsr0_el1)
    240 DEFINE_SYSREG_RW_FUNCS(afsr0_el2)
    241 DEFINE_SYSREG_RW_FUNCS(afsr0_el3)
    242 
    243 DEFINE_SYSREG_RW_FUNCS(afsr1_el1)
    244 DEFINE_SYSREG_RW_FUNCS(afsr1_el2)
    245 DEFINE_SYSREG_RW_FUNCS(afsr1_el3)
    246 
    247 DEFINE_SYSREG_RW_FUNCS(far_el1)
    248 DEFINE_SYSREG_RW_FUNCS(far_el2)
    249 DEFINE_SYSREG_RW_FUNCS(far_el3)
    250 
    251 DEFINE_SYSREG_RW_FUNCS(mair_el1)
    252 DEFINE_SYSREG_RW_FUNCS(mair_el2)
    253 DEFINE_SYSREG_RW_FUNCS(mair_el3)
    254 
    255 DEFINE_SYSREG_RW_FUNCS(amair_el1)
    256 DEFINE_SYSREG_RW_FUNCS(amair_el2)
    257 DEFINE_SYSREG_RW_FUNCS(amair_el3)
    258 
    259 DEFINE_SYSREG_READ_FUNC(rvbar_el1)
    260 DEFINE_SYSREG_READ_FUNC(rvbar_el2)
    261 DEFINE_SYSREG_READ_FUNC(rvbar_el3)
    262 
    263 DEFINE_SYSREG_RW_FUNCS(rmr_el1)
    264 DEFINE_SYSREG_RW_FUNCS(rmr_el2)
    265 DEFINE_SYSREG_RW_FUNCS(rmr_el3)
    266 
    267 DEFINE_SYSREG_RW_FUNCS(tcr_el1)
    268 DEFINE_SYSREG_RW_FUNCS(tcr_el2)
    269 DEFINE_SYSREG_RW_FUNCS(tcr_el3)
    270 
    271 DEFINE_SYSREG_RW_FUNCS(ttbr0_el1)
    272 DEFINE_SYSREG_RW_FUNCS(ttbr0_el2)
    273 DEFINE_SYSREG_RW_FUNCS(ttbr0_el3)
    274 
    275 DEFINE_SYSREG_RW_FUNCS(ttbr1_el1)
    276 
    277 DEFINE_SYSREG_RW_FUNCS(vttbr_el2)
    278 
    279 DEFINE_SYSREG_RW_FUNCS(cptr_el2)
    280 DEFINE_SYSREG_RW_FUNCS(cptr_el3)
    281 
    282 DEFINE_SYSREG_RW_FUNCS(cpacr_el1)
    283 DEFINE_SYSREG_RW_FUNCS(cntfrq_el0)
    284 DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1)
    285 DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1)
    286 DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1)
    287 DEFINE_SYSREG_READ_FUNC(cntpct_el0)
    288 DEFINE_SYSREG_RW_FUNCS(cnthctl_el2)
    289 
    290 DEFINE_SYSREG_RW_FUNCS(tpidr_el3)
    291 
    292 DEFINE_SYSREG_RW_FUNCS(cntvoff_el2)
    293 
    294 DEFINE_SYSREG_RW_FUNCS(vpidr_el2)
    295 DEFINE_SYSREG_RW_FUNCS(vmpidr_el2)
    296 DEFINE_SYSREG_RW_FUNCS(cntp_ctl_el0)
    297 
    298 DEFINE_SYSREG_READ_FUNC(isr_el1)
    299 
    300 DEFINE_SYSREG_READ_FUNC(ctr_el0)
    301 
    302 DEFINE_SYSREG_RW_FUNCS(mdcr_el2)
    303 DEFINE_SYSREG_RW_FUNCS(hstr_el2)
    304 DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2)
    305 DEFINE_SYSREG_RW_FUNCS(pmcr_el0)
    306 
    307 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
    308 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2)
    309 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3)
    310 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1)
    311 DEFINE_RENAME_SYSREG_READ_FUNC(icc_rpr_el1, ICC_RPR_EL1)
    312 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el3, ICC_IGRPEN1_EL3)
    313 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0_EL1)
    314 DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir0_el1, ICC_HPPIR0_EL1)
    315 DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir1_el1, ICC_HPPIR1_EL1)
    316 DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar0_el1, ICC_IAR0_EL1)
    317 DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar1_el1, ICC_IAR1_EL1)
    318 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1)
    319 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1)
    320 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1)
    321 
    322 
    323 #define IS_IN_EL(x) \
    324 	(GET_EL(read_CurrentEl()) == MODE_EL##x)
    325 
    326 #define IS_IN_EL1() IS_IN_EL(1)
    327 #define IS_IN_EL3() IS_IN_EL(3)
    328 
    329 /*
    330  * Check if an EL is implemented from AA64PFR0 register fields. 'el' argument
    331  * must be one of 1, 2 or 3.
    332  */
    333 #define EL_IMPLEMENTED(el) \
    334 	((read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL##el##_SHIFT) \
    335 		& ID_AA64PFR0_ELX_MASK)
    336 
    337 /* Previously defined accesor functions with incomplete register names  */
    338 
    339 #define read_current_el()	read_CurrentEl()
    340 
    341 #define dsb()			dsbsy()
    342 
    343 #define read_midr()		read_midr_el1()
    344 
    345 #define read_mpidr()		read_mpidr_el1()
    346 
    347 #define read_scr()		read_scr_el3()
    348 #define write_scr(_v)		write_scr_el3(_v)
    349 
    350 #define read_hcr()		read_hcr_el2()
    351 #define write_hcr(_v)		write_hcr_el2(_v)
    352 
    353 #define read_cpacr()		read_cpacr_el1()
    354 #define write_cpacr(_v)		write_cpacr_el1(_v)
    355 
    356 #endif /* __ARCH_HELPERS_H__ */
    357