Home | History | Annotate | Download | only in el3_runtime
      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. */
    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