xref: /arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #ifndef CPU_DATA_H
8*91f16700Schasinglulu #define CPU_DATA_H
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <platform_def.h>	/* CACHE_WRITEBACK_GRANULE required */
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <bl31/ehf.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu /* Size of psci_cpu_data structure */
15*91f16700Schasinglulu #define PSCI_CPU_DATA_SIZE		12
16*91f16700Schasinglulu 
17*91f16700Schasinglulu #ifdef __aarch64__
18*91f16700Schasinglulu 
19*91f16700Schasinglulu /* 8-bytes aligned size of psci_cpu_data structure */
20*91f16700Schasinglulu #define PSCI_CPU_DATA_SIZE_ALIGNED	((PSCI_CPU_DATA_SIZE + 7) & ~7)
21*91f16700Schasinglulu 
22*91f16700Schasinglulu #if ENABLE_RME
23*91f16700Schasinglulu /* Size of cpu_context array */
24*91f16700Schasinglulu #define CPU_DATA_CONTEXT_NUM		3
25*91f16700Schasinglulu /* Offset of cpu_ops_ptr, size 8 bytes */
26*91f16700Schasinglulu #define CPU_DATA_CPU_OPS_PTR		0x18
27*91f16700Schasinglulu #else /* ENABLE_RME */
28*91f16700Schasinglulu #define CPU_DATA_CONTEXT_NUM		2
29*91f16700Schasinglulu #define CPU_DATA_CPU_OPS_PTR		0x10
30*91f16700Schasinglulu #endif /* ENABLE_RME */
31*91f16700Schasinglulu 
32*91f16700Schasinglulu #if ENABLE_PAUTH
33*91f16700Schasinglulu /* 8-bytes aligned offset of apiakey[2], size 16 bytes */
34*91f16700Schasinglulu #define	CPU_DATA_APIAKEY_OFFSET		(0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \
35*91f16700Schasinglulu 					     + CPU_DATA_CPU_OPS_PTR)
36*91f16700Schasinglulu #define CPU_DATA_CRASH_BUF_OFFSET	(0x10 + CPU_DATA_APIAKEY_OFFSET)
37*91f16700Schasinglulu #else /* ENABLE_PAUTH */
38*91f16700Schasinglulu #define CPU_DATA_CRASH_BUF_OFFSET	(0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \
39*91f16700Schasinglulu 					     + CPU_DATA_CPU_OPS_PTR)
40*91f16700Schasinglulu #endif /* ENABLE_PAUTH */
41*91f16700Schasinglulu 
42*91f16700Schasinglulu /* need enough space in crash buffer to save 8 registers */
43*91f16700Schasinglulu #define CPU_DATA_CRASH_BUF_SIZE		64
44*91f16700Schasinglulu 
45*91f16700Schasinglulu #else	/* !__aarch64__ */
46*91f16700Schasinglulu 
47*91f16700Schasinglulu #if CRASH_REPORTING
48*91f16700Schasinglulu #error "Crash reporting is not supported in AArch32"
49*91f16700Schasinglulu #endif
50*91f16700Schasinglulu #define CPU_DATA_CPU_OPS_PTR		0x0
51*91f16700Schasinglulu #define CPU_DATA_CRASH_BUF_OFFSET	(0x4 + PSCI_CPU_DATA_SIZE)
52*91f16700Schasinglulu 
53*91f16700Schasinglulu #endif	/* __aarch64__ */
54*91f16700Schasinglulu 
55*91f16700Schasinglulu #if CRASH_REPORTING
56*91f16700Schasinglulu #define CPU_DATA_CRASH_BUF_END		(CPU_DATA_CRASH_BUF_OFFSET + \
57*91f16700Schasinglulu 						CPU_DATA_CRASH_BUF_SIZE)
58*91f16700Schasinglulu #else
59*91f16700Schasinglulu #define CPU_DATA_CRASH_BUF_END		CPU_DATA_CRASH_BUF_OFFSET
60*91f16700Schasinglulu #endif
61*91f16700Schasinglulu 
62*91f16700Schasinglulu /* cpu_data size is the data size rounded up to the platform cache line size */
63*91f16700Schasinglulu #define CPU_DATA_SIZE			(((CPU_DATA_CRASH_BUF_END + \
64*91f16700Schasinglulu 					CACHE_WRITEBACK_GRANULE - 1) / \
65*91f16700Schasinglulu 						CACHE_WRITEBACK_GRANULE) * \
66*91f16700Schasinglulu 							CACHE_WRITEBACK_GRANULE)
67*91f16700Schasinglulu 
68*91f16700Schasinglulu #if ENABLE_RUNTIME_INSTRUMENTATION
69*91f16700Schasinglulu /* Temporary space to store PMF timestamps from assembly code */
70*91f16700Schasinglulu #define CPU_DATA_PMF_TS_COUNT		1
71*91f16700Schasinglulu #define CPU_DATA_PMF_TS0_OFFSET		CPU_DATA_CRASH_BUF_END
72*91f16700Schasinglulu #define CPU_DATA_PMF_TS0_IDX		0
73*91f16700Schasinglulu #endif
74*91f16700Schasinglulu 
75*91f16700Schasinglulu #ifndef __ASSEMBLER__
76*91f16700Schasinglulu 
77*91f16700Schasinglulu #include <assert.h>
78*91f16700Schasinglulu #include <stdint.h>
79*91f16700Schasinglulu 
80*91f16700Schasinglulu #include <arch_helpers.h>
81*91f16700Schasinglulu #include <lib/cassert.h>
82*91f16700Schasinglulu #include <lib/psci/psci.h>
83*91f16700Schasinglulu 
84*91f16700Schasinglulu #include <platform_def.h>
85*91f16700Schasinglulu 
86*91f16700Schasinglulu /* Offsets for the cpu_data structure */
87*91f16700Schasinglulu #define CPU_DATA_PSCI_LOCK_OFFSET	__builtin_offsetof\
88*91f16700Schasinglulu 		(cpu_data_t, psci_svc_cpu_data.pcpu_bakery_info)
89*91f16700Schasinglulu 
90*91f16700Schasinglulu #if PLAT_PCPU_DATA_SIZE
91*91f16700Schasinglulu #define CPU_DATA_PLAT_PCPU_OFFSET	__builtin_offsetof\
92*91f16700Schasinglulu 		(cpu_data_t, platform_cpu_data)
93*91f16700Schasinglulu #endif
94*91f16700Schasinglulu 
95*91f16700Schasinglulu typedef enum context_pas {
96*91f16700Schasinglulu 	CPU_CONTEXT_SECURE = 0,
97*91f16700Schasinglulu 	CPU_CONTEXT_NS,
98*91f16700Schasinglulu #if ENABLE_RME
99*91f16700Schasinglulu 	CPU_CONTEXT_REALM,
100*91f16700Schasinglulu #endif
101*91f16700Schasinglulu 	CPU_CONTEXT_NUM
102*91f16700Schasinglulu } context_pas_t;
103*91f16700Schasinglulu 
104*91f16700Schasinglulu /*******************************************************************************
105*91f16700Schasinglulu  * Function & variable prototypes
106*91f16700Schasinglulu  ******************************************************************************/
107*91f16700Schasinglulu 
108*91f16700Schasinglulu /*******************************************************************************
109*91f16700Schasinglulu  * Cache of frequently used per-cpu data:
110*91f16700Schasinglulu  *   Pointers to non-secure, realm, and secure security state contexts
111*91f16700Schasinglulu  *   Address of the crash stack
112*91f16700Schasinglulu  * It is aligned to the cache line boundary to allow efficient concurrent
113*91f16700Schasinglulu  * manipulation of these pointers on different cpus
114*91f16700Schasinglulu  *
115*91f16700Schasinglulu  * The data structure and the _cpu_data accessors should not be used directly
116*91f16700Schasinglulu  * by components that have per-cpu members. The member access macros should be
117*91f16700Schasinglulu  * used for this.
118*91f16700Schasinglulu  ******************************************************************************/
119*91f16700Schasinglulu typedef struct cpu_data {
120*91f16700Schasinglulu #ifdef __aarch64__
121*91f16700Schasinglulu 	void *cpu_context[CPU_DATA_CONTEXT_NUM];
122*91f16700Schasinglulu #endif /* __aarch64__ */
123*91f16700Schasinglulu 	uintptr_t cpu_ops_ptr;
124*91f16700Schasinglulu 	struct psci_cpu_data psci_svc_cpu_data;
125*91f16700Schasinglulu #if ENABLE_PAUTH
126*91f16700Schasinglulu 	uint64_t apiakey[2];
127*91f16700Schasinglulu #endif
128*91f16700Schasinglulu #if CRASH_REPORTING
129*91f16700Schasinglulu 	u_register_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3];
130*91f16700Schasinglulu #endif
131*91f16700Schasinglulu #if ENABLE_RUNTIME_INSTRUMENTATION
132*91f16700Schasinglulu 	uint64_t cpu_data_pmf_ts[CPU_DATA_PMF_TS_COUNT];
133*91f16700Schasinglulu #endif
134*91f16700Schasinglulu #if PLAT_PCPU_DATA_SIZE
135*91f16700Schasinglulu 	uint8_t platform_cpu_data[PLAT_PCPU_DATA_SIZE];
136*91f16700Schasinglulu #endif
137*91f16700Schasinglulu #if defined(IMAGE_BL31) && EL3_EXCEPTION_HANDLING
138*91f16700Schasinglulu 	pe_exc_data_t ehf_data;
139*91f16700Schasinglulu #endif
140*91f16700Schasinglulu } __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t;
141*91f16700Schasinglulu 
142*91f16700Schasinglulu extern cpu_data_t percpu_data[PLATFORM_CORE_COUNT];
143*91f16700Schasinglulu 
144*91f16700Schasinglulu #ifdef __aarch64__
145*91f16700Schasinglulu CASSERT(CPU_DATA_CONTEXT_NUM == CPU_CONTEXT_NUM,
146*91f16700Schasinglulu 		assert_cpu_data_context_num_mismatch);
147*91f16700Schasinglulu #endif
148*91f16700Schasinglulu 
149*91f16700Schasinglulu #if ENABLE_PAUTH
150*91f16700Schasinglulu CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof
151*91f16700Schasinglulu 	(cpu_data_t, apiakey),
152*91f16700Schasinglulu 	assert_cpu_data_pauth_stack_offset_mismatch);
153*91f16700Schasinglulu #endif
154*91f16700Schasinglulu 
155*91f16700Schasinglulu #if CRASH_REPORTING
156*91f16700Schasinglulu /* verify assembler offsets match data structures */
157*91f16700Schasinglulu CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof
158*91f16700Schasinglulu 	(cpu_data_t, crash_buf),
159*91f16700Schasinglulu 	assert_cpu_data_crash_stack_offset_mismatch);
160*91f16700Schasinglulu #endif
161*91f16700Schasinglulu 
162*91f16700Schasinglulu CASSERT(CPU_DATA_SIZE == sizeof(cpu_data_t),
163*91f16700Schasinglulu 		assert_cpu_data_size_mismatch);
164*91f16700Schasinglulu 
165*91f16700Schasinglulu CASSERT(CPU_DATA_CPU_OPS_PTR == __builtin_offsetof
166*91f16700Schasinglulu 		(cpu_data_t, cpu_ops_ptr),
167*91f16700Schasinglulu 		assert_cpu_data_cpu_ops_ptr_offset_mismatch);
168*91f16700Schasinglulu 
169*91f16700Schasinglulu #if ENABLE_RUNTIME_INSTRUMENTATION
170*91f16700Schasinglulu CASSERT(CPU_DATA_PMF_TS0_OFFSET == __builtin_offsetof
171*91f16700Schasinglulu 		(cpu_data_t, cpu_data_pmf_ts[0]),
172*91f16700Schasinglulu 		assert_cpu_data_pmf_ts0_offset_mismatch);
173*91f16700Schasinglulu #endif
174*91f16700Schasinglulu 
175*91f16700Schasinglulu struct cpu_data *_cpu_data_by_index(uint32_t cpu_index);
176*91f16700Schasinglulu 
177*91f16700Schasinglulu #ifdef __aarch64__
178*91f16700Schasinglulu /* Return the cpu_data structure for the current CPU. */
179*91f16700Schasinglulu static inline struct cpu_data *_cpu_data(void)
180*91f16700Schasinglulu {
181*91f16700Schasinglulu 	return (cpu_data_t *)read_tpidr_el3();
182*91f16700Schasinglulu }
183*91f16700Schasinglulu #else
184*91f16700Schasinglulu struct cpu_data *_cpu_data(void);
185*91f16700Schasinglulu #endif
186*91f16700Schasinglulu 
187*91f16700Schasinglulu /*
188*91f16700Schasinglulu  * Returns the index of the cpu_context array for the given security state.
189*91f16700Schasinglulu  * All accesses to cpu_context should be through this helper to make sure
190*91f16700Schasinglulu  * an access is not out-of-bounds. The function assumes security_state is
191*91f16700Schasinglulu  * valid.
192*91f16700Schasinglulu  */
193*91f16700Schasinglulu static inline context_pas_t get_cpu_context_index(uint32_t security_state)
194*91f16700Schasinglulu {
195*91f16700Schasinglulu 	if (security_state == SECURE) {
196*91f16700Schasinglulu 		return CPU_CONTEXT_SECURE;
197*91f16700Schasinglulu 	} else {
198*91f16700Schasinglulu #if ENABLE_RME
199*91f16700Schasinglulu 		if (security_state == NON_SECURE) {
200*91f16700Schasinglulu 			return CPU_CONTEXT_NS;
201*91f16700Schasinglulu 		} else {
202*91f16700Schasinglulu 			assert(security_state == REALM);
203*91f16700Schasinglulu 			return CPU_CONTEXT_REALM;
204*91f16700Schasinglulu 		}
205*91f16700Schasinglulu #else
206*91f16700Schasinglulu 		assert(security_state == NON_SECURE);
207*91f16700Schasinglulu 		return CPU_CONTEXT_NS;
208*91f16700Schasinglulu #endif
209*91f16700Schasinglulu 	}
210*91f16700Schasinglulu }
211*91f16700Schasinglulu 
212*91f16700Schasinglulu /**************************************************************************
213*91f16700Schasinglulu  * APIs for initialising and accessing per-cpu data
214*91f16700Schasinglulu  *************************************************************************/
215*91f16700Schasinglulu 
216*91f16700Schasinglulu void init_cpu_data_ptr(void);
217*91f16700Schasinglulu void init_cpu_ops(void);
218*91f16700Schasinglulu 
219*91f16700Schasinglulu #define get_cpu_data(_m)		   _cpu_data()->_m
220*91f16700Schasinglulu #define set_cpu_data(_m, _v)		   _cpu_data()->_m = (_v)
221*91f16700Schasinglulu #define get_cpu_data_by_index(_ix, _m)	   _cpu_data_by_index(_ix)->_m
222*91f16700Schasinglulu #define set_cpu_data_by_index(_ix, _m, _v) _cpu_data_by_index(_ix)->_m = (_v)
223*91f16700Schasinglulu /* ((cpu_data_t *)0)->_m is a dummy to get the sizeof the struct member _m */
224*91f16700Schasinglulu #define flush_cpu_data(_m)	   flush_dcache_range((uintptr_t)	  \
225*91f16700Schasinglulu 						&(_cpu_data()->_m), \
226*91f16700Schasinglulu 						sizeof(((cpu_data_t *)0)->_m))
227*91f16700Schasinglulu #define inv_cpu_data(_m)	   inv_dcache_range((uintptr_t)	  	  \
228*91f16700Schasinglulu 						&(_cpu_data()->_m), \
229*91f16700Schasinglulu 						sizeof(((cpu_data_t *)0)->_m))
230*91f16700Schasinglulu #define flush_cpu_data_by_index(_ix, _m)	\
231*91f16700Schasinglulu 				   flush_dcache_range((uintptr_t)	  \
232*91f16700Schasinglulu 					 &(_cpu_data_by_index(_ix)->_m),  \
233*91f16700Schasinglulu 						sizeof(((cpu_data_t *)0)->_m))
234*91f16700Schasinglulu 
235*91f16700Schasinglulu 
236*91f16700Schasinglulu #endif /* __ASSEMBLER__ */
237*91f16700Schasinglulu #endif /* CPU_DATA_H */
238