1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu#ifndef CPU_MACROS_S 7*91f16700Schasinglulu#define CPU_MACROS_S 8*91f16700Schasinglulu 9*91f16700Schasinglulu#include <lib/cpus/cpu_ops.h> 10*91f16700Schasinglulu#include <lib/cpus/errata.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu /* 13*91f16700Schasinglulu * Write given expressions as words 14*91f16700Schasinglulu * 15*91f16700Schasinglulu * _count: 16*91f16700Schasinglulu * Write at least _count words. If the given number of expressions 17*91f16700Schasinglulu * is less than _count, repeat the last expression to fill _count 18*91f16700Schasinglulu * words in total 19*91f16700Schasinglulu * _rest: 20*91f16700Schasinglulu * Optional list of expressions. _this is for parameter extraction 21*91f16700Schasinglulu * only, and has no significance to the caller 22*91f16700Schasinglulu * 23*91f16700Schasinglulu * Invoked as: 24*91f16700Schasinglulu * fill_constants 2, foo, bar, blah, ... 25*91f16700Schasinglulu */ 26*91f16700Schasinglulu .macro fill_constants _count:req, _this, _rest:vararg 27*91f16700Schasinglulu .ifgt \_count 28*91f16700Schasinglulu /* Write the current expression */ 29*91f16700Schasinglulu .ifb \_this 30*91f16700Schasinglulu .error "Nothing to fill" 31*91f16700Schasinglulu .endif 32*91f16700Schasinglulu .word \_this 33*91f16700Schasinglulu 34*91f16700Schasinglulu /* Invoke recursively for remaining expressions */ 35*91f16700Schasinglulu .ifnb \_rest 36*91f16700Schasinglulu fill_constants \_count-1, \_rest 37*91f16700Schasinglulu .else 38*91f16700Schasinglulu fill_constants \_count-1, \_this 39*91f16700Schasinglulu .endif 40*91f16700Schasinglulu .endif 41*91f16700Schasinglulu .endm 42*91f16700Schasinglulu 43*91f16700Schasinglulu /* 44*91f16700Schasinglulu * Declare CPU operations 45*91f16700Schasinglulu * 46*91f16700Schasinglulu * _name: 47*91f16700Schasinglulu * Name of the CPU for which operations are being specified 48*91f16700Schasinglulu * _midr: 49*91f16700Schasinglulu * Numeric value expected to read from CPU's MIDR 50*91f16700Schasinglulu * _resetfunc: 51*91f16700Schasinglulu * Reset function for the CPU. If there's no CPU reset function, 52*91f16700Schasinglulu * specify CPU_NO_RESET_FUNC 53*91f16700Schasinglulu * _power_down_ops: 54*91f16700Schasinglulu * Comma-separated list of functions to perform power-down 55*91f16700Schasinglulu * operatios on the CPU. At least one, and up to 56*91f16700Schasinglulu * CPU_MAX_PWR_DWN_OPS number of functions may be specified. 57*91f16700Schasinglulu * Starting at power level 0, these functions shall handle power 58*91f16700Schasinglulu * down at subsequent power levels. If there aren't exactly 59*91f16700Schasinglulu * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be 60*91f16700Schasinglulu * used to handle power down at subsequent levels 61*91f16700Schasinglulu */ 62*91f16700Schasinglulu .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ 63*91f16700Schasinglulu _power_down_ops:vararg 64*91f16700Schasinglulu .section .cpu_ops, "a" 65*91f16700Schasinglulu .align 2 66*91f16700Schasinglulu .type cpu_ops_\_name, %object 67*91f16700Schasinglulu .word \_midr 68*91f16700Schasinglulu#if defined(IMAGE_AT_EL3) 69*91f16700Schasinglulu .word \_resetfunc 70*91f16700Schasinglulu#endif 71*91f16700Schasinglulu#ifdef IMAGE_BL32 72*91f16700Schasinglulu /* Insert list of functions */ 73*91f16700Schasinglulu fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops 74*91f16700Schasinglulu#endif 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* 77*91f16700Schasinglulu * It is possible (although unlikely) that a cpu may have no errata in 78*91f16700Schasinglulu * code. In that case the start label will not be defined. The list is 79*91f16700Schasinglulu * inteded to be used in a loop, so define it as zero-length for 80*91f16700Schasinglulu * predictable behaviour. Since this macro is always called at the end 81*91f16700Schasinglulu * of the cpu file (after all errata have been parsed) we can be sure 82*91f16700Schasinglulu * that we are at the end of the list. Some cpus call the macro twice, 83*91f16700Schasinglulu * so only do this once. 84*91f16700Schasinglulu */ 85*91f16700Schasinglulu .pushsection .rodata.errata_entries 86*91f16700Schasinglulu .ifndef \_name\()_errata_list_start 87*91f16700Schasinglulu \_name\()_errata_list_start: 88*91f16700Schasinglulu .endif 89*91f16700Schasinglulu /* some call this multiple times, so only do this once */ 90*91f16700Schasinglulu .ifndef \_name\()_errata_list_end 91*91f16700Schasinglulu \_name\()_errata_list_end: 92*91f16700Schasinglulu .endif 93*91f16700Schasinglulu .popsection 94*91f16700Schasinglulu 95*91f16700Schasinglulu /* and now put them in cpu_ops */ 96*91f16700Schasinglulu .word \_name\()_errata_list_start 97*91f16700Schasinglulu .word \_name\()_errata_list_end 98*91f16700Schasinglulu 99*91f16700Schasinglulu#if REPORT_ERRATA 100*91f16700Schasinglulu .ifndef \_name\()_cpu_str 101*91f16700Schasinglulu /* 102*91f16700Schasinglulu * Place errata reported flag, and the spinlock to arbitrate access to 103*91f16700Schasinglulu * it in the data section. 104*91f16700Schasinglulu */ 105*91f16700Schasinglulu .pushsection .data 106*91f16700Schasinglulu define_asm_spinlock \_name\()_errata_lock 107*91f16700Schasinglulu \_name\()_errata_reported: 108*91f16700Schasinglulu .word 0 109*91f16700Schasinglulu .popsection 110*91f16700Schasinglulu 111*91f16700Schasinglulu /* Place CPU string in rodata */ 112*91f16700Schasinglulu .pushsection .rodata 113*91f16700Schasinglulu \_name\()_cpu_str: 114*91f16700Schasinglulu .asciz "\_name" 115*91f16700Schasinglulu .popsection 116*91f16700Schasinglulu .endif 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* 119*91f16700Schasinglulu * Mandatory errata status printing function for CPUs of 120*91f16700Schasinglulu * this class. 121*91f16700Schasinglulu */ 122*91f16700Schasinglulu .word \_name\()_errata_report 123*91f16700Schasinglulu .word \_name\()_cpu_str 124*91f16700Schasinglulu 125*91f16700Schasinglulu#ifdef IMAGE_BL32 126*91f16700Schasinglulu /* Pointers to errata lock and reported flag */ 127*91f16700Schasinglulu .word \_name\()_errata_lock 128*91f16700Schasinglulu .word \_name\()_errata_reported 129*91f16700Schasinglulu#endif 130*91f16700Schasinglulu#endif 131*91f16700Schasinglulu .endm 132*91f16700Schasinglulu 133*91f16700Schasinglulu#if REPORT_ERRATA 134*91f16700Schasinglulu /* 135*91f16700Schasinglulu * Print status of a CPU errata 136*91f16700Schasinglulu * 137*91f16700Schasinglulu * _chosen: 138*91f16700Schasinglulu * Identifier indicating whether or not a CPU errata has been 139*91f16700Schasinglulu * compiled in. 140*91f16700Schasinglulu * _cpu: 141*91f16700Schasinglulu * Name of the CPU 142*91f16700Schasinglulu * _id: 143*91f16700Schasinglulu * Errata identifier 144*91f16700Schasinglulu * _rev_var: 145*91f16700Schasinglulu * Register containing the combined value CPU revision and variant 146*91f16700Schasinglulu * - typically the return value of cpu_get_rev_var 147*91f16700Schasinglulu */ 148*91f16700Schasinglulu .macro report_errata _chosen, _cpu, _id, _rev_var=r4 149*91f16700Schasinglulu /* Stash a string with errata ID */ 150*91f16700Schasinglulu .pushsection .rodata 151*91f16700Schasinglulu \_cpu\()_errata_\_id\()_str: 152*91f16700Schasinglulu .asciz "\_id" 153*91f16700Schasinglulu .popsection 154*91f16700Schasinglulu 155*91f16700Schasinglulu /* Check whether errata applies */ 156*91f16700Schasinglulu mov r0, \_rev_var 157*91f16700Schasinglulu bl check_errata_\_id 158*91f16700Schasinglulu 159*91f16700Schasinglulu .ifeq \_chosen 160*91f16700Schasinglulu /* 161*91f16700Schasinglulu * Errata workaround has not been compiled in. If the errata would have 162*91f16700Schasinglulu * applied had it been compiled in, print its status as missing. 163*91f16700Schasinglulu */ 164*91f16700Schasinglulu cmp r0, #0 165*91f16700Schasinglulu movne r0, #ERRATA_MISSING 166*91f16700Schasinglulu .endif 167*91f16700Schasinglulu ldr r1, =\_cpu\()_cpu_str 168*91f16700Schasinglulu ldr r2, =\_cpu\()_errata_\_id\()_str 169*91f16700Schasinglulu bl errata_print_msg 170*91f16700Schasinglulu .endm 171*91f16700Schasinglulu#endif 172*91f16700Schasinglulu /* 173*91f16700Schasinglulu * Helper macro that reads the part number of the current CPU and jumps 174*91f16700Schasinglulu * to the given label if it matches the CPU MIDR provided. 175*91f16700Schasinglulu * 176*91f16700Schasinglulu * Clobbers: r0-r1 177*91f16700Schasinglulu */ 178*91f16700Schasinglulu .macro jump_if_cpu_midr _cpu_midr, _label 179*91f16700Schasinglulu ldcopr r0, MIDR 180*91f16700Schasinglulu ubfx r0, r0, #MIDR_PN_SHIFT, #12 181*91f16700Schasinglulu ldr r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 182*91f16700Schasinglulu cmp r0, r1 183*91f16700Schasinglulu beq \_label 184*91f16700Schasinglulu .endm 185*91f16700Schasinglulu 186*91f16700Schasinglulu/* 187*91f16700Schasinglulu * NOTE an erratum and CVE id could clash. However, both numbers are very large 188*91f16700Schasinglulu * and the probablity is minuscule. Working around this makes code very 189*91f16700Schasinglulu * complicated and extremely difficult to read so it is not considered. In the 190*91f16700Schasinglulu * unlikely event that this does happen, prepending the CVE id with a 0 should 191*91f16700Schasinglulu * resolve the conflict 192*91f16700Schasinglulu */ 193*91f16700Schasinglulu 194*91f16700Schasinglulu/* 195*91f16700Schasinglulu * Add an entry for this erratum to the errata framework 196*91f16700Schasinglulu * 197*91f16700Schasinglulu * _cpu: 198*91f16700Schasinglulu * Name of cpu as given to declare_cpu_ops 199*91f16700Schasinglulu * 200*91f16700Schasinglulu * _cve: 201*91f16700Schasinglulu * Whether erratum is a CVE. CVE year if yes, 0 otherwise 202*91f16700Schasinglulu * 203*91f16700Schasinglulu * _id: 204*91f16700Schasinglulu * Erratum or CVE number. Please combine with the previous field with the 205*91f16700Schasinglulu * ERRATUM or CVE macros 206*91f16700Schasinglulu * 207*91f16700Schasinglulu * _chosen: 208*91f16700Schasinglulu * Compile time flag on whether the erratum is included 209*91f16700Schasinglulu * 210*91f16700Schasinglulu * _special: 211*91f16700Schasinglulu * The special non-standard name of an erratum 212*91f16700Schasinglulu */ 213*91f16700Schasinglulu.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _special 214*91f16700Schasinglulu .pushsection .rodata.errata_entries 215*91f16700Schasinglulu .align 2 216*91f16700Schasinglulu .ifndef \_cpu\()_errata_list_start 217*91f16700Schasinglulu \_cpu\()_errata_list_start: 218*91f16700Schasinglulu .endif 219*91f16700Schasinglulu 220*91f16700Schasinglulu /* unused on AArch32, maintain for portability */ 221*91f16700Schasinglulu .word 0 222*91f16700Schasinglulu /* TODO(errata ABI): this prevents all checker functions from 223*91f16700Schasinglulu * being optimised away. Can be done away with unless the ABI 224*91f16700Schasinglulu * needs them */ 225*91f16700Schasinglulu .ifnb \_special 226*91f16700Schasinglulu .word check_errata_\_special 227*91f16700Schasinglulu .elseif \_cve 228*91f16700Schasinglulu .word check_errata_cve_\_cve\()_\_id 229*91f16700Schasinglulu .else 230*91f16700Schasinglulu .word check_errata_\_id 231*91f16700Schasinglulu .endif 232*91f16700Schasinglulu /* Will fit CVEs with up to 10 character in the ID field */ 233*91f16700Schasinglulu .word \_id 234*91f16700Schasinglulu .hword \_cve 235*91f16700Schasinglulu .byte \_chosen 236*91f16700Schasinglulu /* TODO(errata ABI): mitigated field for known but unmitigated 237*91f16700Schasinglulu * errata*/ 238*91f16700Schasinglulu .byte 0x1 239*91f16700Schasinglulu .popsection 240*91f16700Schasinglulu.endm 241*91f16700Schasinglulu 242*91f16700Schasinglulu/* 243*91f16700Schasinglulu * Maintain compatibility with the old scheme of "each cpu has its own reporter". 244*91f16700Schasinglulu * TODO remove entirely once all cpus have been converted. This includes the 245*91f16700Schasinglulu * cpu_ops entry, as print_errata_status can call this directly for all cpus 246*91f16700Schasinglulu */ 247*91f16700Schasinglulu.macro errata_report_shim _cpu:req 248*91f16700Schasinglulu #if REPORT_ERRATA 249*91f16700Schasinglulu func \_cpu\()_errata_report 250*91f16700Schasinglulu push {r12, lr} 251*91f16700Schasinglulu 252*91f16700Schasinglulu bl generic_errata_report 253*91f16700Schasinglulu 254*91f16700Schasinglulu pop {r12, lr} 255*91f16700Schasinglulu bx lr 256*91f16700Schasinglulu endfunc \_cpu\()_errata_report 257*91f16700Schasinglulu #endif 258*91f16700Schasinglulu.endm 259*91f16700Schasinglulu#endif /* CPU_MACROS_S */ 260