2 * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
10 #include <platform_def.h> /* CACHE_WRITEBACK_GRANULE required */
16 /* Offsets for the cpu_data structure */
17 #define CPU_DATA_CRASH_BUF_OFFSET 0x18
18 /* need enough space in crash buffer to save 8 registers */
19 #define CPU_DATA_CRASH_BUF_SIZE 64
20 #define CPU_DATA_CPU_OPS_PTR 0x10
22 #else /* __aarch64__ */
25 #error "Crash reporting is not supported in AArch32"
27 #define CPU_DATA_CPU_OPS_PTR 0x0
28 #define CPU_DATA_CRASH_BUF_OFFSET 0x4
30 #endif /* __aarch64__ */
33 #define CPU_DATA_CRASH_BUF_END (CPU_DATA_CRASH_BUF_OFFSET + \
34 CPU_DATA_CRASH_BUF_SIZE)
36 #define CPU_DATA_CRASH_BUF_END CPU_DATA_CRASH_BUF_OFFSET
39 /* cpu_data size is the data size rounded up to the platform cache line size */
40 #define CPU_DATA_SIZE (((CPU_DATA_CRASH_BUF_END + \
41 CACHE_WRITEBACK_GRANULE - 1) / \
42 CACHE_WRITEBACK_GRANULE) * \
43 CACHE_WRITEBACK_GRANULE)
45 #if ENABLE_RUNTIME_INSTRUMENTATION
46 /* Temporary space to store PMF timestamps from assembly code */
47 #define CPU_DATA_PMF_TS_COUNT 1
48 #define CPU_DATA_PMF_TS0_OFFSET CPU_DATA_CRASH_BUF_END
49 #define CPU_DATA_PMF_TS0_IDX 0
54 #include <arch_helpers.h>
55 #include <lib/cassert.h>
56 #include <lib/psci/psci.h>
57 #include <platform_def.h>
60 /* Offsets for the cpu_data structure */
61 #define CPU_DATA_PSCI_LOCK_OFFSET __builtin_offsetof\
62 (cpu_data_t, psci_svc_cpu_data.pcpu_bakery_info)
64 #if PLAT_PCPU_DATA_SIZE
65 #define CPU_DATA_PLAT_PCPU_OFFSET __builtin_offsetof\
66 (cpu_data_t, platform_cpu_data)
69 /*******************************************************************************
70 * Function & variable prototypes
71 ******************************************************************************/
73 /*******************************************************************************
74 * Cache of frequently used per-cpu data:
75 * Pointers to non-secure and secure security state contexts
76 * Address of the crash stack
77 * It is aligned to the cache line boundary to allow efficient concurrent
78 * manipulation of these pointers on different cpus
80 * TODO: Add other commonly used variables to this (tf_issues#90)
82 * The data structure and the _cpu_data accessors should not be used directly
83 * by components that have per-cpu members. The member access macros should be
85 ******************************************************************************/
86 typedef struct cpu_data
{
90 uintptr_t cpu_ops_ptr
;
92 u_register_t crash_buf
[CPU_DATA_CRASH_BUF_SIZE
>> 3];
94 #if ENABLE_RUNTIME_INSTRUMENTATION
95 uint64_t cpu_data_pmf_ts
[CPU_DATA_PMF_TS_COUNT
];
97 struct psci_cpu_data psci_svc_cpu_data
;
98 #if PLAT_PCPU_DATA_SIZE
99 uint8_t platform_cpu_data
[PLAT_PCPU_DATA_SIZE
];
101 #if defined(IMAGE_BL31) && EL3_EXCEPTION_HANDLING
102 pe_exc_data_t ehf_data
;
104 } __aligned(CACHE_WRITEBACK_GRANULE
) cpu_data_t
;
106 extern cpu_data_t percpu_data
[PLATFORM_CORE_COUNT
];
109 /* verify assembler offsets match data structures */
110 CASSERT(CPU_DATA_CRASH_BUF_OFFSET
== __builtin_offsetof
111 (cpu_data_t
, crash_buf
),
112 assert_cpu_data_crash_stack_offset_mismatch
);
115 CASSERT(CPU_DATA_SIZE
== sizeof(cpu_data_t
),
116 assert_cpu_data_size_mismatch
);
118 CASSERT(CPU_DATA_CPU_OPS_PTR
== __builtin_offsetof
119 (cpu_data_t
, cpu_ops_ptr
),
120 assert_cpu_data_cpu_ops_ptr_offset_mismatch
);
122 #if ENABLE_RUNTIME_INSTRUMENTATION
123 CASSERT(CPU_DATA_PMF_TS0_OFFSET
== __builtin_offsetof
124 (cpu_data_t
, cpu_data_pmf_ts
[0]),
125 assert_cpu_data_pmf_ts0_offset_mismatch
);
128 struct cpu_data
*_cpu_data_by_index(uint32_t cpu_index
);
131 /* Return the cpu_data structure for the current CPU. */
132 static inline struct cpu_data
*_cpu_data(void)
134 return (cpu_data_t
*)read_tpidr_el3();
137 struct cpu_data
*_cpu_data(void);
140 /**************************************************************************
141 * APIs for initialising and accessing per-cpu data
142 *************************************************************************/
144 void init_cpu_data_ptr(void);
145 void init_cpu_ops(void);
147 #define get_cpu_data(_m) _cpu_data()->_m
148 #define set_cpu_data(_m, _v) _cpu_data()->_m = (_v)
149 #define get_cpu_data_by_index(_ix, _m) _cpu_data_by_index(_ix)->_m
150 #define set_cpu_data_by_index(_ix, _m, _v) _cpu_data_by_index(_ix)->_m = (_v)
151 /* ((cpu_data_t *)0)->_m is a dummy to get the sizeof the struct member _m */
152 #define flush_cpu_data(_m) flush_dcache_range((uintptr_t) \
153 &(_cpu_data()->_m), \
154 sizeof(((cpu_data_t *)0)->_m))
155 #define inv_cpu_data(_m) inv_dcache_range((uintptr_t) \
156 &(_cpu_data()->_m), \
157 sizeof(((cpu_data_t *)0)->_m))
158 #define flush_cpu_data_by_index(_ix, _m) \
159 flush_dcache_range((uintptr_t) \
160 &(_cpu_data_by_index(_ix)->_m), \
161 sizeof(((cpu_data_t *)0)->_m))
164 #endif /* __ASSEMBLER__ */
165 #endif /* CPU_DATA_H */