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