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