1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2014-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 <assert_macros.S> 10*91f16700Schasinglulu#include <lib/cpus/cpu_ops.h> 11*91f16700Schasinglulu#include <lib/cpus/errata.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu /* 14*91f16700Schasinglulu * Write given expressions as quad words 15*91f16700Schasinglulu * 16*91f16700Schasinglulu * _count: 17*91f16700Schasinglulu * Write at least _count quad words. If the given number of 18*91f16700Schasinglulu * expressions is less than _count, repeat the last expression to 19*91f16700Schasinglulu * fill _count quad words in total 20*91f16700Schasinglulu * _rest: 21*91f16700Schasinglulu * Optional list of expressions. _this is for parameter extraction 22*91f16700Schasinglulu * only, and has no significance to the caller 23*91f16700Schasinglulu * 24*91f16700Schasinglulu * Invoked as: 25*91f16700Schasinglulu * fill_constants 2, foo, bar, blah, ... 26*91f16700Schasinglulu */ 27*91f16700Schasinglulu .macro fill_constants _count:req, _this, _rest:vararg 28*91f16700Schasinglulu .ifgt \_count 29*91f16700Schasinglulu /* Write the current expression */ 30*91f16700Schasinglulu .ifb \_this 31*91f16700Schasinglulu .error "Nothing to fill" 32*91f16700Schasinglulu .endif 33*91f16700Schasinglulu .quad \_this 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* Invoke recursively for remaining expressions */ 36*91f16700Schasinglulu .ifnb \_rest 37*91f16700Schasinglulu fill_constants \_count-1, \_rest 38*91f16700Schasinglulu .else 39*91f16700Schasinglulu fill_constants \_count-1, \_this 40*91f16700Schasinglulu .endif 41*91f16700Schasinglulu .endif 42*91f16700Schasinglulu .endm 43*91f16700Schasinglulu 44*91f16700Schasinglulu /* 45*91f16700Schasinglulu * Declare CPU operations 46*91f16700Schasinglulu * 47*91f16700Schasinglulu * _name: 48*91f16700Schasinglulu * Name of the CPU for which operations are being specified 49*91f16700Schasinglulu * _midr: 50*91f16700Schasinglulu * Numeric value expected to read from CPU's MIDR 51*91f16700Schasinglulu * _resetfunc: 52*91f16700Schasinglulu * Reset function for the CPU. If there's no CPU reset function, 53*91f16700Schasinglulu * specify CPU_NO_RESET_FUNC 54*91f16700Schasinglulu * _extra1: 55*91f16700Schasinglulu * This is a placeholder for future per CPU operations. Currently, 56*91f16700Schasinglulu * some CPUs use this entry to set a test function to determine if 57*91f16700Schasinglulu * the workaround for CVE-2017-5715 needs to be applied or not. 58*91f16700Schasinglulu * _extra2: 59*91f16700Schasinglulu * This is a placeholder for future per CPU operations. Currently 60*91f16700Schasinglulu * some CPUs use this entry to set a function to disable the 61*91f16700Schasinglulu * workaround for CVE-2018-3639. 62*91f16700Schasinglulu * _extra3: 63*91f16700Schasinglulu * This is a placeholder for future per CPU operations. Currently, 64*91f16700Schasinglulu * some CPUs use this entry to set a test function to determine if 65*91f16700Schasinglulu * the workaround for CVE-2022-23960 needs to be applied or not. 66*91f16700Schasinglulu * _e_handler: 67*91f16700Schasinglulu * This is a placeholder for future per CPU exception handlers. 68*91f16700Schasinglulu * _power_down_ops: 69*91f16700Schasinglulu * Comma-separated list of functions to perform power-down 70*91f16700Schasinglulu * operatios on the CPU. At least one, and up to 71*91f16700Schasinglulu * CPU_MAX_PWR_DWN_OPS number of functions may be specified. 72*91f16700Schasinglulu * Starting at power level 0, these functions shall handle power 73*91f16700Schasinglulu * down at subsequent power levels. If there aren't exactly 74*91f16700Schasinglulu * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be 75*91f16700Schasinglulu * used to handle power down at subsequent levels 76*91f16700Schasinglulu */ 77*91f16700Schasinglulu .macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \ 78*91f16700Schasinglulu _extra1:req, _extra2:req, _extra3:req, _e_handler:req, _power_down_ops:vararg 79*91f16700Schasinglulu .section .cpu_ops, "a" 80*91f16700Schasinglulu .align 3 81*91f16700Schasinglulu .type cpu_ops_\_name, %object 82*91f16700Schasinglulu .quad \_midr 83*91f16700Schasinglulu#if defined(IMAGE_AT_EL3) 84*91f16700Schasinglulu .quad \_resetfunc 85*91f16700Schasinglulu#endif 86*91f16700Schasinglulu .quad \_extra1 87*91f16700Schasinglulu .quad \_extra2 88*91f16700Schasinglulu .quad \_extra3 89*91f16700Schasinglulu .quad \_e_handler 90*91f16700Schasinglulu#ifdef IMAGE_BL31 91*91f16700Schasinglulu /* Insert list of functions */ 92*91f16700Schasinglulu fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops 93*91f16700Schasinglulu#endif 94*91f16700Schasinglulu /* 95*91f16700Schasinglulu * It is possible (although unlikely) that a cpu may have no errata in 96*91f16700Schasinglulu * code. In that case the start label will not be defined. The list is 97*91f16700Schasinglulu * intended to be used in a loop, so define it as zero-length for 98*91f16700Schasinglulu * predictable behaviour. Since this macro is always called at the end 99*91f16700Schasinglulu * of the cpu file (after all errata have been parsed) we can be sure 100*91f16700Schasinglulu * that we are at the end of the list. Some cpus call declare_cpu_ops 101*91f16700Schasinglulu * twice, so only do this once. 102*91f16700Schasinglulu */ 103*91f16700Schasinglulu .pushsection .rodata.errata_entries 104*91f16700Schasinglulu .ifndef \_name\()_errata_list_start 105*91f16700Schasinglulu \_name\()_errata_list_start: 106*91f16700Schasinglulu .endif 107*91f16700Schasinglulu .ifndef \_name\()_errata_list_end 108*91f16700Schasinglulu \_name\()_errata_list_end: 109*91f16700Schasinglulu .endif 110*91f16700Schasinglulu .popsection 111*91f16700Schasinglulu 112*91f16700Schasinglulu /* and now put them in cpu_ops */ 113*91f16700Schasinglulu .quad \_name\()_errata_list_start 114*91f16700Schasinglulu .quad \_name\()_errata_list_end 115*91f16700Schasinglulu 116*91f16700Schasinglulu#if REPORT_ERRATA 117*91f16700Schasinglulu .ifndef \_name\()_cpu_str 118*91f16700Schasinglulu /* 119*91f16700Schasinglulu * Place errata reported flag, and the spinlock to arbitrate access to 120*91f16700Schasinglulu * it in the data section. 121*91f16700Schasinglulu */ 122*91f16700Schasinglulu .pushsection .data 123*91f16700Schasinglulu define_asm_spinlock \_name\()_errata_lock 124*91f16700Schasinglulu \_name\()_errata_reported: 125*91f16700Schasinglulu .word 0 126*91f16700Schasinglulu .popsection 127*91f16700Schasinglulu 128*91f16700Schasinglulu /* Place CPU string in rodata */ 129*91f16700Schasinglulu .pushsection .rodata 130*91f16700Schasinglulu \_name\()_cpu_str: 131*91f16700Schasinglulu .asciz "\_name" 132*91f16700Schasinglulu .popsection 133*91f16700Schasinglulu .endif 134*91f16700Schasinglulu 135*91f16700Schasinglulu 136*91f16700Schasinglulu /* 137*91f16700Schasinglulu * Mandatory errata status printing function for CPUs of 138*91f16700Schasinglulu * this class. 139*91f16700Schasinglulu */ 140*91f16700Schasinglulu .quad \_name\()_errata_report 141*91f16700Schasinglulu .quad \_name\()_cpu_str 142*91f16700Schasinglulu 143*91f16700Schasinglulu#ifdef IMAGE_BL31 144*91f16700Schasinglulu /* Pointers to errata lock and reported flag */ 145*91f16700Schasinglulu .quad \_name\()_errata_lock 146*91f16700Schasinglulu .quad \_name\()_errata_reported 147*91f16700Schasinglulu#endif /* IMAGE_BL31 */ 148*91f16700Schasinglulu#endif /* REPORT_ERRATA */ 149*91f16700Schasinglulu 150*91f16700Schasinglulu#if defined(IMAGE_BL31) && CRASH_REPORTING 151*91f16700Schasinglulu .quad \_name\()_cpu_reg_dump 152*91f16700Schasinglulu#endif 153*91f16700Schasinglulu .endm 154*91f16700Schasinglulu 155*91f16700Schasinglulu .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ 156*91f16700Schasinglulu _power_down_ops:vararg 157*91f16700Schasinglulu declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, \ 158*91f16700Schasinglulu \_power_down_ops 159*91f16700Schasinglulu .endm 160*91f16700Schasinglulu 161*91f16700Schasinglulu .macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \ 162*91f16700Schasinglulu _e_handler:req, _power_down_ops:vararg 163*91f16700Schasinglulu declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 164*91f16700Schasinglulu 0, 0, 0, \_e_handler, \_power_down_ops 165*91f16700Schasinglulu .endm 166*91f16700Schasinglulu 167*91f16700Schasinglulu .macro declare_cpu_ops_wa _name:req, _midr:req, \ 168*91f16700Schasinglulu _resetfunc:req, _extra1:req, _extra2:req, \ 169*91f16700Schasinglulu _extra3:req, _power_down_ops:vararg 170*91f16700Schasinglulu declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 171*91f16700Schasinglulu \_extra1, \_extra2, \_extra3, 0, \_power_down_ops 172*91f16700Schasinglulu .endm 173*91f16700Schasinglulu 174*91f16700Schasinglulu/* TODO can be deleted once all CPUs have been converted */ 175*91f16700Schasinglulu#if REPORT_ERRATA 176*91f16700Schasinglulu /* 177*91f16700Schasinglulu * Print status of a CPU errata 178*91f16700Schasinglulu * 179*91f16700Schasinglulu * _chosen: 180*91f16700Schasinglulu * Identifier indicating whether or not a CPU errata has been 181*91f16700Schasinglulu * compiled in. 182*91f16700Schasinglulu * _cpu: 183*91f16700Schasinglulu * Name of the CPU 184*91f16700Schasinglulu * _id: 185*91f16700Schasinglulu * Errata identifier 186*91f16700Schasinglulu * _rev_var: 187*91f16700Schasinglulu * Register containing the combined value CPU revision and variant 188*91f16700Schasinglulu * - typically the return value of cpu_get_rev_var 189*91f16700Schasinglulu */ 190*91f16700Schasinglulu .macro report_errata _chosen, _cpu, _id, _rev_var=x8 191*91f16700Schasinglulu /* Stash a string with errata ID */ 192*91f16700Schasinglulu .pushsection .rodata 193*91f16700Schasinglulu \_cpu\()_errata_\_id\()_str: 194*91f16700Schasinglulu .asciz "\_id" 195*91f16700Schasinglulu .popsection 196*91f16700Schasinglulu 197*91f16700Schasinglulu /* Check whether errata applies */ 198*91f16700Schasinglulu mov x0, \_rev_var 199*91f16700Schasinglulu /* Shall clobber: x0-x7 */ 200*91f16700Schasinglulu bl check_errata_\_id 201*91f16700Schasinglulu 202*91f16700Schasinglulu .ifeq \_chosen 203*91f16700Schasinglulu /* 204*91f16700Schasinglulu * Errata workaround has not been compiled in. If the errata would have 205*91f16700Schasinglulu * applied had it been compiled in, print its status as missing. 206*91f16700Schasinglulu */ 207*91f16700Schasinglulu cbz x0, 900f 208*91f16700Schasinglulu mov x0, #ERRATA_MISSING 209*91f16700Schasinglulu .endif 210*91f16700Schasinglulu900: 211*91f16700Schasinglulu adr x1, \_cpu\()_cpu_str 212*91f16700Schasinglulu adr x2, \_cpu\()_errata_\_id\()_str 213*91f16700Schasinglulu bl errata_print_msg 214*91f16700Schasinglulu .endm 215*91f16700Schasinglulu#endif 216*91f16700Schasinglulu 217*91f16700Schasinglulu /* 218*91f16700Schasinglulu * This macro is used on some CPUs to detect if they are vulnerable 219*91f16700Schasinglulu * to CVE-2017-5715. 220*91f16700Schasinglulu */ 221*91f16700Schasinglulu .macro cpu_check_csv2 _reg _label 222*91f16700Schasinglulu mrs \_reg, id_aa64pfr0_el1 223*91f16700Schasinglulu ubfx \_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH 224*91f16700Schasinglulu /* 225*91f16700Schasinglulu * If the field equals 1, branch targets trained in one context cannot 226*91f16700Schasinglulu * affect speculative execution in a different context. 227*91f16700Schasinglulu * 228*91f16700Schasinglulu * If the field equals 2, it means that the system is also aware of 229*91f16700Schasinglulu * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we 230*91f16700Schasinglulu * expect users of the registers to do the right thing. 231*91f16700Schasinglulu * 232*91f16700Schasinglulu * Only apply mitigations if the value of this field is 0. 233*91f16700Schasinglulu */ 234*91f16700Schasinglulu#if ENABLE_ASSERTIONS 235*91f16700Schasinglulu cmp \_reg, #3 /* Only values 0 to 2 are expected */ 236*91f16700Schasinglulu ASM_ASSERT(lo) 237*91f16700Schasinglulu#endif 238*91f16700Schasinglulu 239*91f16700Schasinglulu cmp \_reg, #0 240*91f16700Schasinglulu bne \_label 241*91f16700Schasinglulu .endm 242*91f16700Schasinglulu 243*91f16700Schasinglulu /* 244*91f16700Schasinglulu * Helper macro that reads the part number of the current 245*91f16700Schasinglulu * CPU and jumps to the given label if it matches the CPU 246*91f16700Schasinglulu * MIDR provided. 247*91f16700Schasinglulu * 248*91f16700Schasinglulu * Clobbers x0. 249*91f16700Schasinglulu */ 250*91f16700Schasinglulu .macro jump_if_cpu_midr _cpu_midr, _label 251*91f16700Schasinglulu mrs x0, midr_el1 252*91f16700Schasinglulu ubfx x0, x0, MIDR_PN_SHIFT, #12 253*91f16700Schasinglulu cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 254*91f16700Schasinglulu b.eq \_label 255*91f16700Schasinglulu .endm 256*91f16700Schasinglulu 257*91f16700Schasinglulu 258*91f16700Schasinglulu/* 259*91f16700Schasinglulu * Workaround wrappers for errata that apply at reset or runtime. Reset errata 260*91f16700Schasinglulu * will be applied automatically 261*91f16700Schasinglulu * 262*91f16700Schasinglulu * _cpu: 263*91f16700Schasinglulu * Name of cpu as given to declare_cpu_ops 264*91f16700Schasinglulu * 265*91f16700Schasinglulu * _cve: 266*91f16700Schasinglulu * Whether erratum is a CVE. CVE year if yes, 0 otherwise 267*91f16700Schasinglulu * 268*91f16700Schasinglulu * _id: 269*91f16700Schasinglulu * Erratum or CVE number. Please combine with previous field with ERRATUM 270*91f16700Schasinglulu * or CVE macros 271*91f16700Schasinglulu * 272*91f16700Schasinglulu * _chosen: 273*91f16700Schasinglulu * Compile time flag on whether the erratum is included 274*91f16700Schasinglulu * 275*91f16700Schasinglulu * _apply_at_reset: 276*91f16700Schasinglulu * Whether the erratum should be automatically applied at reset 277*91f16700Schasinglulu */ 278*91f16700Schasinglulu.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req 279*91f16700Schasinglulu .pushsection .rodata.errata_entries 280*91f16700Schasinglulu .align 3 281*91f16700Schasinglulu .ifndef \_cpu\()_errata_list_start 282*91f16700Schasinglulu \_cpu\()_errata_list_start: 283*91f16700Schasinglulu .endif 284*91f16700Schasinglulu 285*91f16700Schasinglulu /* check if unused and compile out if no references */ 286*91f16700Schasinglulu .if \_apply_at_reset && \_chosen 287*91f16700Schasinglulu .quad erratum_\_cpu\()_\_id\()_wa 288*91f16700Schasinglulu .else 289*91f16700Schasinglulu .quad 0 290*91f16700Schasinglulu .endif 291*91f16700Schasinglulu /* TODO(errata ABI): this prevents all checker functions from 292*91f16700Schasinglulu * being optimised away. Can be done away with unless the ABI 293*91f16700Schasinglulu * needs them */ 294*91f16700Schasinglulu .quad check_erratum_\_cpu\()_\_id 295*91f16700Schasinglulu /* Will fit CVEs with up to 10 character in the ID field */ 296*91f16700Schasinglulu .word \_id 297*91f16700Schasinglulu .hword \_cve 298*91f16700Schasinglulu .byte \_chosen 299*91f16700Schasinglulu /* TODO(errata ABI): mitigated field for known but unmitigated 300*91f16700Schasinglulu * errata */ 301*91f16700Schasinglulu .byte 0x1 302*91f16700Schasinglulu .popsection 303*91f16700Schasinglulu.endm 304*91f16700Schasinglulu 305*91f16700Schasinglulu.macro _workaround_start _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req 306*91f16700Schasinglulu add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_apply_at_reset 307*91f16700Schasinglulu 308*91f16700Schasinglulu func erratum_\_cpu\()_\_id\()_wa 309*91f16700Schasinglulu mov x8, x30 310*91f16700Schasinglulu 311*91f16700Schasinglulu /* save rev_var for workarounds that might need it but don't 312*91f16700Schasinglulu * restore to x0 because few will care */ 313*91f16700Schasinglulu mov x7, x0 314*91f16700Schasinglulu bl check_erratum_\_cpu\()_\_id 315*91f16700Schasinglulu cbz x0, erratum_\_cpu\()_\_id\()_skip 316*91f16700Schasinglulu.endm 317*91f16700Schasinglulu 318*91f16700Schasinglulu.macro _workaround_end _cpu:req, _id:req 319*91f16700Schasinglulu erratum_\_cpu\()_\_id\()_skip: 320*91f16700Schasinglulu ret x8 321*91f16700Schasinglulu endfunc erratum_\_cpu\()_\_id\()_wa 322*91f16700Schasinglulu.endm 323*91f16700Schasinglulu 324*91f16700Schasinglulu/******************************************************************************* 325*91f16700Schasinglulu * Errata workaround wrappers 326*91f16700Schasinglulu ******************************************************************************/ 327*91f16700Schasinglulu/* 328*91f16700Schasinglulu * Workaround wrappers for errata that apply at reset or runtime. Reset errata 329*91f16700Schasinglulu * will be applied automatically 330*91f16700Schasinglulu * 331*91f16700Schasinglulu * _cpu: 332*91f16700Schasinglulu * Name of cpu as given to declare_cpu_ops 333*91f16700Schasinglulu * 334*91f16700Schasinglulu * _cve: 335*91f16700Schasinglulu * Whether erratum is a CVE. CVE year if yes, 0 otherwise 336*91f16700Schasinglulu * 337*91f16700Schasinglulu * _id: 338*91f16700Schasinglulu * Erratum or CVE number. Please combine with previous field with ERRATUM 339*91f16700Schasinglulu * or CVE macros 340*91f16700Schasinglulu * 341*91f16700Schasinglulu * _chosen: 342*91f16700Schasinglulu * Compile time flag on whether the erratum is included 343*91f16700Schasinglulu * 344*91f16700Schasinglulu * in body: 345*91f16700Schasinglulu * clobber x0 to x7 (please only use those) 346*91f16700Schasinglulu * argument x7 - cpu_rev_var 347*91f16700Schasinglulu * 348*91f16700Schasinglulu * _wa clobbers: x0-x8 (PCS compliant) 349*91f16700Schasinglulu */ 350*91f16700Schasinglulu.macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req 351*91f16700Schasinglulu _workaround_start \_cpu, \_cve, \_id, \_chosen, 1 352*91f16700Schasinglulu.endm 353*91f16700Schasinglulu 354*91f16700Schasinglulu/* 355*91f16700Schasinglulu * See `workaround_reset_start` for usage info. Additional arguments: 356*91f16700Schasinglulu * 357*91f16700Schasinglulu * _midr: 358*91f16700Schasinglulu * Check if CPU's MIDR matches the CPU it's meant for. Must be specified 359*91f16700Schasinglulu * for errata applied in generic code 360*91f16700Schasinglulu */ 361*91f16700Schasinglulu.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr 362*91f16700Schasinglulu /* 363*91f16700Schasinglulu * Let errata specify if they need MIDR checking. Sadly, storing the 364*91f16700Schasinglulu * MIDR in an .equ to retrieve automatically blows up as it stores some 365*91f16700Schasinglulu * brackets in the symbol 366*91f16700Schasinglulu */ 367*91f16700Schasinglulu .ifnb \_midr 368*91f16700Schasinglulu jump_if_cpu_midr \_midr, 1f 369*91f16700Schasinglulu b erratum_\_cpu\()_\_id\()_skip 370*91f16700Schasinglulu 371*91f16700Schasinglulu 1: 372*91f16700Schasinglulu .endif 373*91f16700Schasinglulu _workaround_start \_cpu, \_cve, \_id, \_chosen, 0 374*91f16700Schasinglulu.endm 375*91f16700Schasinglulu 376*91f16700Schasinglulu/* 377*91f16700Schasinglulu * Usage and arguments identical to `workaround_reset_start`. The _cve argument 378*91f16700Schasinglulu * is kept here so the same #define can be used as that macro 379*91f16700Schasinglulu */ 380*91f16700Schasinglulu.macro workaround_reset_end _cpu:req, _cve:req, _id:req 381*91f16700Schasinglulu _workaround_end \_cpu, \_id 382*91f16700Schasinglulu.endm 383*91f16700Schasinglulu 384*91f16700Schasinglulu/* 385*91f16700Schasinglulu * See `workaround_reset_start` for usage info. The _cve argument is kept here 386*91f16700Schasinglulu * so the same #define can be used as that macro. Additional arguments: 387*91f16700Schasinglulu * 388*91f16700Schasinglulu * _no_isb: 389*91f16700Schasinglulu * Optionally do not include the trailing isb. Please disable with the 390*91f16700Schasinglulu * NO_ISB macro 391*91f16700Schasinglulu */ 392*91f16700Schasinglulu.macro workaround_runtime_end _cpu:req, _cve:req, _id:req, _no_isb 393*91f16700Schasinglulu /* 394*91f16700Schasinglulu * Runtime errata do not have a reset function to call the isb for them 395*91f16700Schasinglulu * and missing the isb could be very problematic. It is also likely as 396*91f16700Schasinglulu * they tend to be scattered in generic code. 397*91f16700Schasinglulu */ 398*91f16700Schasinglulu .ifb \_no_isb 399*91f16700Schasinglulu isb 400*91f16700Schasinglulu .endif 401*91f16700Schasinglulu _workaround_end \_cpu, \_id 402*91f16700Schasinglulu.endm 403*91f16700Schasinglulu 404*91f16700Schasinglulu/******************************************************************************* 405*91f16700Schasinglulu * Errata workaround helpers 406*91f16700Schasinglulu ******************************************************************************/ 407*91f16700Schasinglulu/* 408*91f16700Schasinglulu * Set a bit in a system register. Can set multiple bits but is limited by the 409*91f16700Schasinglulu * way the ORR instruction encodes them. 410*91f16700Schasinglulu * 411*91f16700Schasinglulu * _reg: 412*91f16700Schasinglulu * Register to write to 413*91f16700Schasinglulu * 414*91f16700Schasinglulu * _bit: 415*91f16700Schasinglulu * Bit to set. Please use a descriptive #define 416*91f16700Schasinglulu * 417*91f16700Schasinglulu * _assert: 418*91f16700Schasinglulu * Optionally whether to read back and assert that the bit has been 419*91f16700Schasinglulu * written. Please disable with NO_ASSERT macro 420*91f16700Schasinglulu * 421*91f16700Schasinglulu * clobbers: x1 422*91f16700Schasinglulu */ 423*91f16700Schasinglulu.macro sysreg_bit_set _reg:req, _bit:req, _assert=1 424*91f16700Schasinglulu mrs x1, \_reg 425*91f16700Schasinglulu orr x1, x1, #\_bit 426*91f16700Schasinglulu msr \_reg, x1 427*91f16700Schasinglulu.endm 428*91f16700Schasinglulu 429*91f16700Schasinglulu/* 430*91f16700Schasinglulu * Clear a bit in a system register. Can clear multiple bits but is limited by 431*91f16700Schasinglulu * the way the BIC instrucion encodes them. 432*91f16700Schasinglulu * 433*91f16700Schasinglulu * see sysreg_bit_set for usage 434*91f16700Schasinglulu */ 435*91f16700Schasinglulu.macro sysreg_bit_clear _reg:req, _bit:req 436*91f16700Schasinglulu mrs x1, \_reg 437*91f16700Schasinglulu bic x1, x1, #\_bit 438*91f16700Schasinglulu msr \_reg, x1 439*91f16700Schasinglulu.endm 440*91f16700Schasinglulu 441*91f16700Schasinglulu.macro override_vector_table _table:req 442*91f16700Schasinglulu adr x1, \_table 443*91f16700Schasinglulu msr vbar_el3, x1 444*91f16700Schasinglulu.endm 445*91f16700Schasinglulu 446*91f16700Schasinglulu/* 447*91f16700Schasinglulu * BFI : Inserts bitfield into a system register. 448*91f16700Schasinglulu * 449*91f16700Schasinglulu * BFI{cond} Rd, Rn, #lsb, #width 450*91f16700Schasinglulu */ 451*91f16700Schasinglulu.macro sysreg_bitfield_insert _reg:req, _src:req, _lsb:req, _width:req 452*91f16700Schasinglulu /* Source value for BFI */ 453*91f16700Schasinglulu mov x1, #\_src 454*91f16700Schasinglulu mrs x0, \_reg 455*91f16700Schasinglulu bfi x0, x1, #\_lsb, #\_width 456*91f16700Schasinglulu msr \_reg, x0 457*91f16700Schasinglulu.endm 458*91f16700Schasinglulu 459*91f16700Schasinglulu/* 460*91f16700Schasinglulu * Apply erratum 461*91f16700Schasinglulu * 462*91f16700Schasinglulu * _cpu: 463*91f16700Schasinglulu * Name of cpu as given to declare_cpu_ops 464*91f16700Schasinglulu * 465*91f16700Schasinglulu * _cve: 466*91f16700Schasinglulu * Whether erratum is a CVE. CVE year if yes, 0 otherwise 467*91f16700Schasinglulu * 468*91f16700Schasinglulu * _id: 469*91f16700Schasinglulu * Erratum or CVE number. Please combine with previous field with ERRATUM 470*91f16700Schasinglulu * or CVE macros 471*91f16700Schasinglulu * 472*91f16700Schasinglulu * _chosen: 473*91f16700Schasinglulu * Compile time flag on whether the erratum is included 474*91f16700Schasinglulu * 475*91f16700Schasinglulu * _get_rev: 476*91f16700Schasinglulu * Optional parameter that determines whether to insert a call to the CPU revision fetching 477*91f16700Schasinglulu * procedure. Stores the result of this in the temporary register x10. 478*91f16700Schasinglulu * 479*91f16700Schasinglulu * clobbers: x0-x10 (PCS compliant) 480*91f16700Schasinglulu */ 481*91f16700Schasinglulu.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req, _get_rev=GET_CPU_REV 482*91f16700Schasinglulu .if (\_chosen & \_get_rev) 483*91f16700Schasinglulu mov x9, x30 484*91f16700Schasinglulu bl cpu_get_rev_var 485*91f16700Schasinglulu mov x10, x0 486*91f16700Schasinglulu .elseif (\_chosen) 487*91f16700Schasinglulu mov x9, x30 488*91f16700Schasinglulu mov x0, x10 489*91f16700Schasinglulu .endif 490*91f16700Schasinglulu 491*91f16700Schasinglulu .if \_chosen 492*91f16700Schasinglulu bl erratum_\_cpu\()_\_id\()_wa 493*91f16700Schasinglulu mov x30, x9 494*91f16700Schasinglulu .endif 495*91f16700Schasinglulu.endm 496*91f16700Schasinglulu 497*91f16700Schasinglulu/* 498*91f16700Schasinglulu * Helpers to select which revisions errata apply to. Don't leave a link 499*91f16700Schasinglulu * register as the cpu_rev_var_*** will call the ret and we can save on one. 500*91f16700Schasinglulu * 501*91f16700Schasinglulu * _cpu: 502*91f16700Schasinglulu * Name of cpu as given to declare_cpu_ops 503*91f16700Schasinglulu * 504*91f16700Schasinglulu * _cve: 505*91f16700Schasinglulu * Whether erratum is a CVE. CVE year if yes, 0 otherwise 506*91f16700Schasinglulu * 507*91f16700Schasinglulu * _id: 508*91f16700Schasinglulu * Erratum or CVE number. Please combine with previous field with ERRATUM 509*91f16700Schasinglulu * or CVE macros 510*91f16700Schasinglulu * 511*91f16700Schasinglulu * _rev_num: 512*91f16700Schasinglulu * Revision to apply to 513*91f16700Schasinglulu * 514*91f16700Schasinglulu * in body: 515*91f16700Schasinglulu * clobber: x0 to x4 516*91f16700Schasinglulu * argument: x0 - cpu_rev_var 517*91f16700Schasinglulu */ 518*91f16700Schasinglulu.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req 519*91f16700Schasinglulu func check_erratum_\_cpu\()_\_id 520*91f16700Schasinglulu mov x1, #\_rev_num 521*91f16700Schasinglulu b cpu_rev_var_ls 522*91f16700Schasinglulu endfunc check_erratum_\_cpu\()_\_id 523*91f16700Schasinglulu.endm 524*91f16700Schasinglulu 525*91f16700Schasinglulu.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req 526*91f16700Schasinglulu func check_erratum_\_cpu\()_\_id 527*91f16700Schasinglulu mov x1, #\_rev_num 528*91f16700Schasinglulu b cpu_rev_var_hs 529*91f16700Schasinglulu endfunc check_erratum_\_cpu\()_\_id 530*91f16700Schasinglulu.endm 531*91f16700Schasinglulu 532*91f16700Schasinglulu.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req 533*91f16700Schasinglulu func check_erratum_\_cpu\()_\_id 534*91f16700Schasinglulu mov x1, #\_rev_num_lo 535*91f16700Schasinglulu mov x2, #\_rev_num_hi 536*91f16700Schasinglulu b cpu_rev_var_range 537*91f16700Schasinglulu endfunc check_erratum_\_cpu\()_\_id 538*91f16700Schasinglulu.endm 539*91f16700Schasinglulu 540*91f16700Schasinglulu.macro check_erratum_chosen _cpu:req, _cve:req, _id:req, _chosen:req 541*91f16700Schasinglulu func check_erratum_\_cpu\()_\_id 542*91f16700Schasinglulu .if \_chosen 543*91f16700Schasinglulu mov x0, #ERRATA_APPLIES 544*91f16700Schasinglulu .else 545*91f16700Schasinglulu mov x0, #ERRATA_MISSING 546*91f16700Schasinglulu .endif 547*91f16700Schasinglulu ret 548*91f16700Schasinglulu endfunc check_erratum_\_cpu\()_\_id 549*91f16700Schasinglulu.endm 550*91f16700Schasinglulu 551*91f16700Schasinglulu/* provide a shorthand for the name format for annoying errata */ 552*91f16700Schasinglulu.macro check_erratum_custom_start _cpu:req, _cve:req, _id:req 553*91f16700Schasinglulu func check_erratum_\_cpu\()_\_id 554*91f16700Schasinglulu.endm 555*91f16700Schasinglulu 556*91f16700Schasinglulu.macro check_erratum_custom_end _cpu:req, _cve:req, _id:req 557*91f16700Schasinglulu endfunc check_erratum_\_cpu\()_\_id 558*91f16700Schasinglulu.endm 559*91f16700Schasinglulu 560*91f16700Schasinglulu 561*91f16700Schasinglulu/******************************************************************************* 562*91f16700Schasinglulu * CPU reset function wrapper 563*91f16700Schasinglulu ******************************************************************************/ 564*91f16700Schasinglulu 565*91f16700Schasinglulu/* 566*91f16700Schasinglulu * Wrapper to automatically apply all reset-time errata. Will end with an isb. 567*91f16700Schasinglulu * 568*91f16700Schasinglulu * _cpu: 569*91f16700Schasinglulu * Name of cpu as given to declare_cpu_ops 570*91f16700Schasinglulu * 571*91f16700Schasinglulu * in body: 572*91f16700Schasinglulu * clobber x8 to x14 573*91f16700Schasinglulu * argument x14 - cpu_rev_var 574*91f16700Schasinglulu */ 575*91f16700Schasinglulu.macro cpu_reset_func_start _cpu:req 576*91f16700Schasinglulu func \_cpu\()_reset_func 577*91f16700Schasinglulu mov x15, x30 578*91f16700Schasinglulu bl cpu_get_rev_var 579*91f16700Schasinglulu mov x14, x0 580*91f16700Schasinglulu 581*91f16700Schasinglulu /* short circuit the location to avoid searching the list */ 582*91f16700Schasinglulu adrp x12, \_cpu\()_errata_list_start 583*91f16700Schasinglulu add x12, x12, :lo12:\_cpu\()_errata_list_start 584*91f16700Schasinglulu adrp x13, \_cpu\()_errata_list_end 585*91f16700Schasinglulu add x13, x13, :lo12:\_cpu\()_errata_list_end 586*91f16700Schasinglulu 587*91f16700Schasinglulu errata_begin: 588*91f16700Schasinglulu /* if head catches up with end of list, exit */ 589*91f16700Schasinglulu cmp x12, x13 590*91f16700Schasinglulu b.eq errata_end 591*91f16700Schasinglulu 592*91f16700Schasinglulu ldr x10, [x12, #ERRATUM_WA_FUNC] 593*91f16700Schasinglulu /* TODO(errata ABI): check mitigated and checker function fields 594*91f16700Schasinglulu * for 0 */ 595*91f16700Schasinglulu ldrb w11, [x12, #ERRATUM_CHOSEN] 596*91f16700Schasinglulu 597*91f16700Schasinglulu /* skip if not chosen */ 598*91f16700Schasinglulu cbz x11, 1f 599*91f16700Schasinglulu /* skip if runtime erratum */ 600*91f16700Schasinglulu cbz x10, 1f 601*91f16700Schasinglulu 602*91f16700Schasinglulu /* put cpu revision in x0 and call workaround */ 603*91f16700Schasinglulu mov x0, x14 604*91f16700Schasinglulu blr x10 605*91f16700Schasinglulu 1: 606*91f16700Schasinglulu add x12, x12, #ERRATUM_ENTRY_SIZE 607*91f16700Schasinglulu b errata_begin 608*91f16700Schasinglulu errata_end: 609*91f16700Schasinglulu.endm 610*91f16700Schasinglulu 611*91f16700Schasinglulu.macro cpu_reset_func_end _cpu:req 612*91f16700Schasinglulu isb 613*91f16700Schasinglulu ret x15 614*91f16700Schasinglulu endfunc \_cpu\()_reset_func 615*91f16700Schasinglulu.endm 616*91f16700Schasinglulu 617*91f16700Schasinglulu/* 618*91f16700Schasinglulu * Maintain compatibility with the old scheme of each cpu has its own reporting. 619*91f16700Schasinglulu * TODO remove entirely once all cpus have been converted. This includes the 620*91f16700Schasinglulu * cpu_ops entry, as print_errata_status can call this directly for all cpus 621*91f16700Schasinglulu */ 622*91f16700Schasinglulu.macro errata_report_shim _cpu:req 623*91f16700Schasinglulu #if REPORT_ERRATA 624*91f16700Schasinglulu func \_cpu\()_errata_report 625*91f16700Schasinglulu /* normal stack frame for pretty debugging */ 626*91f16700Schasinglulu stp x29, x30, [sp, #-16]! 627*91f16700Schasinglulu mov x29, sp 628*91f16700Schasinglulu 629*91f16700Schasinglulu bl generic_errata_report 630*91f16700Schasinglulu 631*91f16700Schasinglulu ldp x29, x30, [sp], #16 632*91f16700Schasinglulu ret 633*91f16700Schasinglulu endfunc \_cpu\()_errata_report 634*91f16700Schasinglulu #endif 635*91f16700Schasinglulu.endm 636*91f16700Schasinglulu#endif /* CPU_MACROS_S */ 637