1532ed618SSoby Mathew /* 2b07c317fSBoyan Karatotev * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved. 3532ed618SSoby Mathew * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5532ed618SSoby Mathew */ 6532ed618SSoby Mathew 743534997SAntonio Nino Diaz #ifndef CPU_DATA_H 843534997SAntonio Nino Diaz #define CPU_DATA_H 9532ed618SSoby Mathew 1086606eb5SEtienne Carriere #include <platform_def.h> /* CACHE_WRITEBACK_GRANULE required */ 1186606eb5SEtienne Carriere 1209d40e0eSAntonio Nino Diaz #include <bl31/ehf.h> 1334a22a02SBoyan Karatotev #include <context.h> 14*4779becdSBoyan Karatotev #include <lib/utils_def.h> 15*4779becdSBoyan Karatotev #include <lib/cpus/cpu_ops.h> 16ed108b56SAlexei Fedorov 17ed108b56SAlexei Fedorov /* need enough space in crash buffer to save 8 registers */ 18*4779becdSBoyan Karatotev #define CPU_DATA_CRASH_BUF_BYTES 64 19872be88aSdp-arm #if ENABLE_RUNTIME_INSTRUMENTATION 20872be88aSdp-arm /* Temporary space to store PMF timestamps from assembly code */ 21872be88aSdp-arm #define CPU_DATA_PMF_TS_COUNT 1 22872be88aSdp-arm #define CPU_DATA_PMF_TS0_IDX 0 23532ed618SSoby Mathew #endif 24532ed618SSoby Mathew 25*4779becdSBoyan Karatotev #ifdef __aarch64__ 26*4779becdSBoyan Karatotev #define CPU_DATA_CPU_CONTEXT_SIZE (CPU_CONTEXT_NUM * CPU_WORD_SIZE) 27*4779becdSBoyan Karatotev #else /* __aarch64__ */ 28*4779becdSBoyan Karatotev #define CPU_DATA_CPU_CONTEXT_SIZE 0 29*4779becdSBoyan Karatotev #endif /* __aarch64__ */ 30*4779becdSBoyan Karatotev #define CPU_DATA_WARMBOOT_EP_INFO_SIZE CPU_WORD_SIZE 31*4779becdSBoyan Karatotev #define CPU_DATA_WARMBOOT_EP_INFO_ALIGN CPU_WORD_SIZE 32*4779becdSBoyan Karatotev #define CPU_DATA_CPU_OPS_PTR_SIZE CPU_WORD_SIZE 33*4779becdSBoyan Karatotev #define CPU_DATA_CPU_OPS_PTR_ALIGN CPU_WORD_SIZE 34*4779becdSBoyan Karatotev #define CPU_DATA_PSCI_SVC_CPU_DATA_SIZE 12 35*4779becdSBoyan Karatotev #define CPU_DATA_PSCI_SVC_CPU_DATA_ALIGN CPU_WORD_SIZE 36*4779becdSBoyan Karatotev #if ENABLE_PAUTH 37*4779becdSBoyan Karatotev /* uint64_t apiakey[2] */ 38*4779becdSBoyan Karatotev #define CPU_DATA_APIAKEY_SIZE 16 39*4779becdSBoyan Karatotev /* uint64_t alignement */ 40*4779becdSBoyan Karatotev #define CPU_DATA_APIAKEY_ALIGN 8 41*4779becdSBoyan Karatotev #else /* ENABLE_PAUTH */ 42*4779becdSBoyan Karatotev #define CPU_DATA_APIAKEY_SIZE 0 43*4779becdSBoyan Karatotev #define CPU_DATA_APIAKEY_ALIGN 1 44*4779becdSBoyan Karatotev #endif /* ENABLE_PAUTH */ 45*4779becdSBoyan Karatotev #if CRASH_REPORTING 46*4779becdSBoyan Karatotev #define CPU_DATA_CRASH_BUF_SIZE ((CPU_DATA_CRASH_BUF_BYTES >> 3) * CPU_WORD_SIZE) 47*4779becdSBoyan Karatotev #define CPU_DATA_CRASH_BUF_ALIGN CPU_WORD_SIZE 48*4779becdSBoyan Karatotev #else /* CRASH_REPORTING */ 49*4779becdSBoyan Karatotev #define CPU_DATA_CRASH_BUF_SIZE 0 50*4779becdSBoyan Karatotev #define CPU_DATA_CRASH_BUF_ALIGN 1 51*4779becdSBoyan Karatotev #endif /* CRASH_REPORTING */ 52*4779becdSBoyan Karatotev #if ENABLE_RUNTIME_INSTRUMENTATION 53*4779becdSBoyan Karatotev #define CPU_DATA_CPU_DATA_PMF_TS_SIZE (CPU_DATA_PMF_TS_COUNT * 8) 54*4779becdSBoyan Karatotev /* uint64_t alignement */ 55*4779becdSBoyan Karatotev #define CPU_DATA_CPU_DATA_PMF_TS_ALIGN 8 56*4779becdSBoyan Karatotev #else /* ENABLE_RUNTIME_INSTRUMENTATION */ 57*4779becdSBoyan Karatotev #define CPU_DATA_CPU_DATA_PMF_TS_SIZE 0 58*4779becdSBoyan Karatotev #define CPU_DATA_CPU_DATA_PMF_TS_ALIGN 1 59*4779becdSBoyan Karatotev #endif /* ENABLE_RUNTIME_INSTRUMENTATION */ 60*4779becdSBoyan Karatotev #ifdef PLAT_PCPU_DATA_SIZE 61*4779becdSBoyan Karatotev #define CPU_DATA_PLATFORM_CPU_DATA_SIZE PLAT_PCPU_DATA_SIZE 62*4779becdSBoyan Karatotev #define CPU_DATA_PLATFORM_CPU_DATA_ALIGN 1 63*4779becdSBoyan Karatotev #else /* PLAT_PCPU_DATA_SIZE */ 64*4779becdSBoyan Karatotev #define CPU_DATA_PLATFORM_CPU_DATA_SIZE 0 65*4779becdSBoyan Karatotev #define CPU_DATA_PLATFORM_CPU_DATA_ALIGN 1 66*4779becdSBoyan Karatotev #endif /* PLAT_PCPU_DATA_SIZE */ 67*4779becdSBoyan Karatotev #if EL3_EXCEPTION_HANDLING 68*4779becdSBoyan Karatotev /* buffer space for EHF data is sizeof(pe_exc_data_t) */ 69*4779becdSBoyan Karatotev #define CPU_DATA_EHF_DATA_SIZE 8 70*4779becdSBoyan Karatotev /* hardcoded to 64 bit alignment */ 71*4779becdSBoyan Karatotev #define CPU_DATA_EHF_DATA_ALIGN 8 72*4779becdSBoyan Karatotev #else /* EL3_EXCEPTION_HANDLING */ 73*4779becdSBoyan Karatotev #define CPU_DATA_EHF_DATA_SIZE 0 74*4779becdSBoyan Karatotev #define CPU_DATA_EHF_DATA_ALIGN 1 75*4779becdSBoyan Karatotev #endif 76*4779becdSBoyan Karatotev /* cpu_data size is the data size rounded up to the platform cache line size */ 77*4779becdSBoyan Karatotev #define CPU_DATA_SIZE_ALIGN CACHE_WRITEBACK_GRANULE 78*4779becdSBoyan Karatotev 79*4779becdSBoyan Karatotev #define CPU_DATA_CPU_CONTEXT 0 80*4779becdSBoyan Karatotev #define CPU_DATA_WARMBOOT_EP_INFO ROUND_UP_2EVAL((CPU_DATA_CPU_CONTEXT + CPU_DATA_CPU_CONTEXT_SIZE), CPU_DATA_CPU_OPS_PTR_ALIGN) 81*4779becdSBoyan Karatotev #define CPU_DATA_CPU_OPS_PTR ROUND_UP_2EVAL((CPU_DATA_WARMBOOT_EP_INFO + CPU_DATA_WARMBOOT_EP_INFO_SIZE), CPU_DATA_CPU_OPS_PTR_ALIGN) 82*4779becdSBoyan Karatotev #define CPU_DATA_PSCI_SVC_CPU_DATA ROUND_UP_2EVAL((CPU_DATA_CPU_OPS_PTR + CPU_DATA_CPU_OPS_PTR_SIZE), CPU_DATA_PSCI_SVC_CPU_DATA_ALIGN) 83*4779becdSBoyan Karatotev #define CPU_DATA_APIAKEY ROUND_UP_2EVAL((CPU_DATA_PSCI_SVC_CPU_DATA + CPU_DATA_PSCI_SVC_CPU_DATA_SIZE), CPU_DATA_APIAKEY_ALIGN) 84*4779becdSBoyan Karatotev #define CPU_DATA_CRASH_BUF ROUND_UP_2EVAL((CPU_DATA_APIAKEY + CPU_DATA_APIAKEY_SIZE), CPU_DATA_CRASH_BUF_ALIGN) 85*4779becdSBoyan Karatotev #define CPU_DATA_CPU_DATA_PMF_TS ROUND_UP_2EVAL((CPU_DATA_CRASH_BUF + CPU_DATA_CRASH_BUF_SIZE), CPU_DATA_CPU_DATA_PMF_TS_ALIGN) 86*4779becdSBoyan Karatotev #define CPU_DATA_PLATFORM_CPU_DATA ROUND_UP_2EVAL((CPU_DATA_CPU_DATA_PMF_TS + CPU_DATA_CPU_DATA_PMF_TS_SIZE), CPU_DATA_PLATFORM_CPU_DATA_ALIGN) 87*4779becdSBoyan Karatotev #define CPU_DATA_EHF_DATA ROUND_UP_2EVAL((CPU_DATA_PLATFORM_CPU_DATA + CPU_DATA_PLATFORM_CPU_DATA_SIZE), CPU_DATA_EHF_DATA_ALIGN) 88*4779becdSBoyan Karatotev #define CPU_DATA_SIZE ROUND_UP_2EVAL((CPU_DATA_EHF_DATA + CPU_DATA_EHF_DATA_SIZE), CPU_DATA_SIZE_ALIGN) 89*4779becdSBoyan Karatotev 90d5dfdeb6SJulius Werner #ifndef __ASSEMBLER__ 91532ed618SSoby Mathew 92c5ea4f8aSZelalem Aweke #include <assert.h> 93c5ea4f8aSZelalem Aweke #include <stdint.h> 94c5ea4f8aSZelalem Aweke 95532ed618SSoby Mathew #include <arch_helpers.h> 9609d40e0eSAntonio Nino Diaz #include <lib/cassert.h> 9709d40e0eSAntonio Nino Diaz #include <lib/psci/psci.h> 98c5ea4f8aSZelalem Aweke 99532ed618SSoby Mathew #include <platform_def.h> 100532ed618SSoby Mathew 101532ed618SSoby Mathew /******************************************************************************* 102532ed618SSoby Mathew * Function & variable prototypes 103532ed618SSoby Mathew ******************************************************************************/ 104532ed618SSoby Mathew 105532ed618SSoby Mathew /******************************************************************************* 106532ed618SSoby Mathew * Cache of frequently used per-cpu data: 107c5ea4f8aSZelalem Aweke * Pointers to non-secure, realm, and secure security state contexts 108532ed618SSoby Mathew * Address of the crash stack 109532ed618SSoby Mathew * It is aligned to the cache line boundary to allow efficient concurrent 110532ed618SSoby Mathew * manipulation of these pointers on different cpus 111532ed618SSoby Mathew * 112532ed618SSoby Mathew * The data structure and the _cpu_data accessors should not be used directly 113532ed618SSoby Mathew * by components that have per-cpu members. The member access macros should be 114532ed618SSoby Mathew * used for this. 115532ed618SSoby Mathew ******************************************************************************/ 116532ed618SSoby Mathew typedef struct cpu_data { 117402b3cf8SJulius Werner #ifdef __aarch64__ 11834a22a02SBoyan Karatotev void *cpu_context[CPU_CONTEXT_NUM]; 119c5ea4f8aSZelalem Aweke #endif /* __aarch64__ */ 120ef738d19SManish Pandey entry_point_info_t *warmboot_ep_info; 121d43b2ea6SBoyan Karatotev struct cpu_ops *cpu_ops_ptr; 122ed108b56SAlexei Fedorov struct psci_cpu_data psci_svc_cpu_data; 123ed108b56SAlexei Fedorov #if ENABLE_PAUTH 124ed108b56SAlexei Fedorov uint64_t apiakey[2]; 125ed108b56SAlexei Fedorov #endif 126532ed618SSoby Mathew #if CRASH_REPORTING 127*4779becdSBoyan Karatotev u_register_t crash_buf[CPU_DATA_CRASH_BUF_BYTES >> 3]; 128532ed618SSoby Mathew #endif 129872be88aSdp-arm #if ENABLE_RUNTIME_INSTRUMENTATION 130872be88aSdp-arm uint64_t cpu_data_pmf_ts[CPU_DATA_PMF_TS_COUNT]; 131872be88aSdp-arm #endif 132532ed618SSoby Mathew #if PLAT_PCPU_DATA_SIZE 133532ed618SSoby Mathew uint8_t platform_cpu_data[PLAT_PCPU_DATA_SIZE]; 134532ed618SSoby Mathew #endif 13501b3d394SBoyan Karatotev #if EL3_EXCEPTION_HANDLING 13621b818c0SJeenu Viswambharan pe_exc_data_t ehf_data; 13721b818c0SJeenu Viswambharan #endif 138532ed618SSoby Mathew } __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t; 139532ed618SSoby Mathew 1407fabe1a8SRoberto Vargas extern cpu_data_t percpu_data[PLATFORM_CORE_COUNT]; 1417fabe1a8SRoberto Vargas 142*4779becdSBoyan Karatotev #define CPU_DATA_ASSERT_OFFSET(left, right) \ 143*4779becdSBoyan Karatotev CASSERT(CPU_DATA_ ## left == __builtin_offsetof \ 144*4779becdSBoyan Karatotev (cpu_data_t, right), \ 145*4779becdSBoyan Karatotev assert_cpu_data_ ## right ## _mismatch) 146ed108b56SAlexei Fedorov 147532ed618SSoby Mathew /* verify assembler offsets match data structures */ 148*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(WARMBOOT_EP_INFO, warmboot_ep_info); 149*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(CPU_OPS_PTR, cpu_ops_ptr); 150*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(PSCI_SVC_CPU_DATA, psci_svc_cpu_data); 151*4779becdSBoyan Karatotev #if ENABLE_PAUTH 152*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(APIAKEY, apiakey); 153532ed618SSoby Mathew #endif 154*4779becdSBoyan Karatotev #if CRASH_REPORTING 155*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(CRASH_BUF, crash_buf); 156*4779becdSBoyan Karatotev #endif 157*4779becdSBoyan Karatotev #if ENABLE_RUNTIME_INSTRUMENTATION 158*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(CPU_DATA_PMF_TS, cpu_data_pmf_ts); 159*4779becdSBoyan Karatotev #endif 160*4779becdSBoyan Karatotev #if PLAT_PCPU_DATA_SIZE 161*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(PLATFORM_CPU_DATA, platform_cpu_data); 162*4779becdSBoyan Karatotev #endif 16301b3d394SBoyan Karatotev #if EL3_EXCEPTION_HANDLING 164*4779becdSBoyan Karatotev CPU_DATA_ASSERT_OFFSET(EHF_DATA, ehf_data); 165483dc2e4SOmkar Anand Kulkarni #endif 166483dc2e4SOmkar Anand Kulkarni 16786606eb5SEtienne Carriere CASSERT(CPU_DATA_SIZE == sizeof(cpu_data_t), 16886606eb5SEtienne Carriere assert_cpu_data_size_mismatch); 169532ed618SSoby Mathew 170d43b2ea6SBoyan Karatotev static inline cpu_data_t *_cpu_data_by_index(unsigned int cpu_index) 171d43b2ea6SBoyan Karatotev { 172d43b2ea6SBoyan Karatotev return &percpu_data[cpu_index]; 173d43b2ea6SBoyan Karatotev } 174532ed618SSoby Mathew 175402b3cf8SJulius Werner #ifdef __aarch64__ 176532ed618SSoby Mathew /* Return the cpu_data structure for the current CPU. */ 177d43b2ea6SBoyan Karatotev static inline cpu_data_t *_cpu_data(void) 178532ed618SSoby Mathew { 179532ed618SSoby Mathew return (cpu_data_t *)read_tpidr_el3(); 180532ed618SSoby Mathew } 181e33b78a6SSoby Mathew #else 182d43b2ea6SBoyan Karatotev cpu_data_t *_cpu_data(void); 183e33b78a6SSoby Mathew #endif 184532ed618SSoby Mathew 185532ed618SSoby Mathew /************************************************************************** 186532ed618SSoby Mathew * APIs for initialising and accessing per-cpu data 187532ed618SSoby Mathew *************************************************************************/ 188532ed618SSoby Mathew 189022fcb48SBoyan Karatotev void cpu_data_init_cpu_ops(void); 190532ed618SSoby Mathew 191532ed618SSoby Mathew #define get_cpu_data(_m) _cpu_data()->_m 192a0fee747SAntonio Nino Diaz #define set_cpu_data(_m, _v) _cpu_data()->_m = (_v) 193532ed618SSoby Mathew #define get_cpu_data_by_index(_ix, _m) _cpu_data_by_index(_ix)->_m 194a0fee747SAntonio Nino Diaz #define set_cpu_data_by_index(_ix, _m, _v) _cpu_data_by_index(_ix)->_m = (_v) 1952614ea3eSJoel Hutton /* ((cpu_data_t *)0)->_m is a dummy to get the sizeof the struct member _m */ 196532ed618SSoby Mathew #define flush_cpu_data(_m) flush_dcache_range((uintptr_t) \ 197532ed618SSoby Mathew &(_cpu_data()->_m), \ 1982614ea3eSJoel Hutton sizeof(((cpu_data_t *)0)->_m)) 199532ed618SSoby Mathew #define inv_cpu_data(_m) inv_dcache_range((uintptr_t) \ 200532ed618SSoby Mathew &(_cpu_data()->_m), \ 2012614ea3eSJoel Hutton sizeof(((cpu_data_t *)0)->_m)) 202532ed618SSoby Mathew #define flush_cpu_data_by_index(_ix, _m) \ 203532ed618SSoby Mathew flush_dcache_range((uintptr_t) \ 204532ed618SSoby Mathew &(_cpu_data_by_index(_ix)->_m), \ 2052614ea3eSJoel Hutton sizeof(((cpu_data_t *)0)->_m)) 206532ed618SSoby Mathew 207532ed618SSoby Mathew 208d5dfdeb6SJulius Werner #endif /* __ASSEMBLER__ */ 20943534997SAntonio Nino Diaz #endif /* CPU_DATA_H */ 210