1 /*
2  * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef __CPU_DATA_H__
8 #define __CPU_DATA_H__
9 
10 #include <platform_def.h>	/* CACHE_WRITEBACK_GRANULE required */
11 
12 #ifdef AARCH32
13 
14 #if CRASH_REPORTING
15 #error "Crash reporting is not supported in AArch32"
16 #endif
17 #define CPU_DATA_CPU_OPS_PTR		0x0
18 #define CPU_DATA_CRASH_BUF_OFFSET	0x4
19 
20 #else /* AARCH32 */
21 
22 /* Offsets for the cpu_data structure */
23 #define CPU_DATA_CRASH_BUF_OFFSET	0x18
24 /* need enough space in crash buffer to save 8 registers */
25 #define CPU_DATA_CRASH_BUF_SIZE		64
26 #define CPU_DATA_CPU_OPS_PTR		0x10
27 
28 #endif /* AARCH32 */
29 
30 #if CRASH_REPORTING
31 #define CPU_DATA_CRASH_BUF_END		(CPU_DATA_CRASH_BUF_OFFSET + \
32 						CPU_DATA_CRASH_BUF_SIZE)
33 #else
34 #define CPU_DATA_CRASH_BUF_END		CPU_DATA_CRASH_BUF_OFFSET
35 #endif
36 
37 /* cpu_data size is the data size rounded up to the platform cache line size */
38 #define CPU_DATA_SIZE			(((CPU_DATA_CRASH_BUF_END + \
39 					CACHE_WRITEBACK_GRANULE - 1) / \
40 						CACHE_WRITEBACK_GRANULE) * \
41 							CACHE_WRITEBACK_GRANULE)
42 
43 #if ENABLE_RUNTIME_INSTRUMENTATION
44 /* Temporary space to store PMF timestamps from assembly code */
45 #define CPU_DATA_PMF_TS_COUNT		1
46 #define CPU_DATA_PMF_TS0_OFFSET		CPU_DATA_CRASH_BUF_END
47 #define CPU_DATA_PMF_TS0_IDX		0
48 #endif
49 
50 #ifndef __ASSEMBLY__
51 
52 #include <arch_helpers.h>
53 #include <cassert.h>
54 #include <platform_def.h>
55 #include <psci.h>
56 #include <stdint.h>
57 
58 /* Offsets for the cpu_data structure */
59 #define CPU_DATA_PSCI_LOCK_OFFSET	__builtin_offsetof\
60 		(cpu_data_t, psci_svc_cpu_data.pcpu_bakery_info)
61 
62 #if PLAT_PCPU_DATA_SIZE
63 #define CPU_DATA_PLAT_PCPU_OFFSET	__builtin_offsetof\
64 		(cpu_data_t, platform_cpu_data)
65 #endif
66 
67 /*******************************************************************************
68  * Function & variable prototypes
69  ******************************************************************************/
70 
71 /*******************************************************************************
72  * Cache of frequently used per-cpu data:
73  *   Pointers to non-secure and secure security state contexts
74  *   Address of the crash stack
75  * It is aligned to the cache line boundary to allow efficient concurrent
76  * manipulation of these pointers on different cpus
77  *
78  * TODO: Add other commonly used variables to this (tf_issues#90)
79  *
80  * The data structure and the _cpu_data accessors should not be used directly
81  * by components that have per-cpu members. The member access macros should be
82  * used for this.
83  ******************************************************************************/
84 typedef struct cpu_data {
85 #ifndef AARCH32
86 	void *cpu_context[2];
87 #endif
88 	uintptr_t cpu_ops_ptr;
89 #if CRASH_REPORTING
90 	u_register_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3];
91 #endif
92 #if ENABLE_RUNTIME_INSTRUMENTATION
93 	uint64_t cpu_data_pmf_ts[CPU_DATA_PMF_TS_COUNT];
94 #endif
95 	struct psci_cpu_data psci_svc_cpu_data;
96 #if PLAT_PCPU_DATA_SIZE
97 	uint8_t platform_cpu_data[PLAT_PCPU_DATA_SIZE];
98 #endif
99 } __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t;
100 
101 #if CRASH_REPORTING
102 /* verify assembler offsets match data structures */
103 CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof
104 	(cpu_data_t, crash_buf),
105 	assert_cpu_data_crash_stack_offset_mismatch);
106 #endif
107 
108 CASSERT(CPU_DATA_SIZE == sizeof(cpu_data_t),
109 		assert_cpu_data_size_mismatch);
110 
111 CASSERT(CPU_DATA_CPU_OPS_PTR == __builtin_offsetof
112 		(cpu_data_t, cpu_ops_ptr),
113 		assert_cpu_data_cpu_ops_ptr_offset_mismatch);
114 
115 #if ENABLE_RUNTIME_INSTRUMENTATION
116 CASSERT(CPU_DATA_PMF_TS0_OFFSET == __builtin_offsetof
117 		(cpu_data_t, cpu_data_pmf_ts[0]),
118 		assert_cpu_data_pmf_ts0_offset_mismatch);
119 #endif
120 
121 struct cpu_data *_cpu_data_by_index(uint32_t cpu_index);
122 
123 #ifndef AARCH32
124 /* Return the cpu_data structure for the current CPU. */
_cpu_data(void)125 static inline struct cpu_data *_cpu_data(void)
126 {
127 	return (cpu_data_t *)read_tpidr_el3();
128 }
129 #else
130 struct cpu_data *_cpu_data(void);
131 #endif
132 
133 /**************************************************************************
134  * APIs for initialising and accessing per-cpu data
135  *************************************************************************/
136 
137 void init_cpu_data_ptr(void);
138 void init_cpu_ops(void);
139 
140 #define get_cpu_data(_m)		   _cpu_data()->_m
141 #define set_cpu_data(_m, _v)		   _cpu_data()->_m = _v
142 #define get_cpu_data_by_index(_ix, _m)	   _cpu_data_by_index(_ix)->_m
143 #define set_cpu_data_by_index(_ix, _m, _v) _cpu_data_by_index(_ix)->_m = _v
144 /* ((cpu_data_t *)0)->_m is a dummy to get the sizeof the struct member _m */
145 #define flush_cpu_data(_m)	   flush_dcache_range((uintptr_t)	  \
146 						&(_cpu_data()->_m), \
147 						sizeof(((cpu_data_t *)0)->_m))
148 #define inv_cpu_data(_m)	   inv_dcache_range((uintptr_t)	  	  \
149 						&(_cpu_data()->_m), \
150 						sizeof(((cpu_data_t *)0)->_m))
151 #define flush_cpu_data_by_index(_ix, _m)	\
152 				   flush_dcache_range((uintptr_t)	  \
153 					 &(_cpu_data_by_index(_ix)->_m),  \
154 						sizeof(((cpu_data_t *)0)->_m))
155 
156 
157 #endif /* __ASSEMBLY__ */
158 #endif /* __CPU_DATA_H__ */
159