1/* 2 * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6#ifndef CPU_MACROS_S 7#define CPU_MACROS_S 8 9#include <lib/cpus/cpu_ops.h> 10#include <lib/cpus/errata.h> 11 12 /* 13 * Write given expressions as words 14 * 15 * _count: 16 * Write at least _count words. If the given number of expressions 17 * is less than _count, repeat the last expression to fill _count 18 * words in total 19 * _rest: 20 * Optional list of expressions. _this is for parameter extraction 21 * only, and has no significance to the caller 22 * 23 * Invoked as: 24 * fill_constants 2, foo, bar, blah, ... 25 */ 26 .macro fill_constants _count:req, _this, _rest:vararg 27 .ifgt \_count 28 /* Write the current expression */ 29 .ifb \_this 30 .error "Nothing to fill" 31 .endif 32 .word \_this 33 34 /* Invoke recursively for remaining expressions */ 35 .ifnb \_rest 36 fill_constants \_count-1, \_rest 37 .else 38 fill_constants \_count-1, \_this 39 .endif 40 .endif 41 .endm 42 43 /* 44 * Declare CPU operations 45 * 46 * _name: 47 * Name of the CPU for which operations are being specified 48 * _midr: 49 * Numeric value expected to read from CPU's MIDR 50 * _resetfunc: 51 * Reset function for the CPU 52 * _power_down_ops: 53 * Comma-separated list of functions to perform power-down 54 * operatios on the CPU. At least one, and up to 55 * CPU_MAX_PWR_DWN_OPS number of functions may be specified. 56 * Starting at power level 0, these functions shall handle power 57 * down at subsequent power levels. If there aren't exactly 58 * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be 59 * used to handle power down at subsequent levels 60 */ 61 .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ 62 _power_down_ops:vararg 63 .section .cpu_ops, "a" 64 .align 2 65 .type cpu_ops_\_name, %object 66 .word \_midr 67#if defined(IMAGE_AT_EL3) 68 .word \_resetfunc 69#endif 70#ifdef IMAGE_BL32 71 /* Insert list of functions */ 72 fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops 73#endif 74 75 /* 76 * It is possible (although unlikely) that a cpu may have no errata in 77 * code. In that case the start label will not be defined. The list is 78 * inteded to be used in a loop, so define it as zero-length for 79 * predictable behaviour. Since this macro is always called at the end 80 * of the cpu file (after all errata have been parsed) we can be sure 81 * that we are at the end of the list. Some cpus call the macro twice, 82 * so only do this once. 83 */ 84 .pushsection .rodata.errata_entries 85 .ifndef \_name\()_errata_list_start 86 \_name\()_errata_list_start: 87 .endif 88 /* some call this multiple times, so only do this once */ 89 .ifndef \_name\()_errata_list_end 90 \_name\()_errata_list_end: 91 .endif 92 .popsection 93 94 /* and now put them in cpu_ops */ 95 .word \_name\()_errata_list_start 96 .word \_name\()_errata_list_end 97 98#if REPORT_ERRATA 99 .ifndef \_name\()_cpu_str 100 /* 101 * Place errata reported flag, and the spinlock to arbitrate access to 102 * it in the data section. 103 */ 104 .pushsection .data 105 define_asm_spinlock \_name\()_errata_lock 106 \_name\()_errata_reported: 107 .word 0 108 .popsection 109 110 /* Place CPU string in rodata */ 111 .pushsection .rodata 112 \_name\()_cpu_str: 113 .asciz "\_name" 114 .popsection 115 .endif 116 117 .word \_name\()_cpu_str 118 119#ifdef IMAGE_BL32 120 /* Pointers to errata lock and reported flag */ 121 .word \_name\()_errata_lock 122 .word \_name\()_errata_reported 123#endif 124#endif 125 .endm 126 127 /* 128 * Helper macro that reads the part number of the current CPU and jumps 129 * to the given label if it matches the CPU MIDR provided. 130 * 131 * Clobbers: r0-r1 132 */ 133 .macro jump_if_cpu_midr _cpu_midr, _label 134 ldcopr r0, MIDR 135 ubfx r0, r0, #MIDR_PN_SHIFT, #12 136 ldr r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 137 cmp r0, r1 138 beq \_label 139 .endm 140 141/* 142 * NOTE an erratum and CVE id could clash. However, both numbers are very large 143 * and the probablity is minuscule. Working around this makes code very 144 * complicated and extremely difficult to read so it is not considered. In the 145 * unlikely event that this does happen, prepending the CVE id with a 0 should 146 * resolve the conflict 147 */ 148 149/* 150 * Add an entry for this erratum to the errata framework 151 * 152 * _cpu: 153 * Name of cpu as given to declare_cpu_ops 154 * 155 * _cve: 156 * Whether erratum is a CVE. CVE year if yes, 0 otherwise 157 * 158 * _id: 159 * Erratum or CVE number. Please combine with the previous field with the 160 * ERRATUM or CVE macros 161 * 162 * _chosen: 163 * Compile time flag on whether the erratum is included 164 * 165 * _special: 166 * The special non-standard name of an erratum 167 */ 168.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _special 169 .pushsection .rodata.errata_entries 170 .align 2 171 .ifndef \_cpu\()_errata_list_start 172 \_cpu\()_errata_list_start: 173 .endif 174 175 .ifnb \_special 176 .word check_errata_\_special 177 .elseif \_cve 178 .word check_errata_cve_\_cve\()_\_id 179 .else 180 .word check_errata_\_id 181 .endif 182 /* Will fit CVEs with up to 10 character in the ID field */ 183 .word \_id 184 .hword \_cve 185 .byte \_chosen 186 .byte 0x0 /* alignment */ 187 .popsection 188.endm 189 190#endif /* CPU_MACROS_S */ 191