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