• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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