1add40351SSoby Mathew/* 2007433d8SBoyan Karatotev * Copyright (c) 2014-2023, ARM Limited and Contributors. All rights reserved. 3add40351SSoby Mathew * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5add40351SSoby Mathew */ 6c3cf06f1SAntonio Nino Diaz#ifndef CPU_MACROS_S 7c3cf06f1SAntonio Nino Diaz#define CPU_MACROS_S 8add40351SSoby Mathew 9ff6f62e1SAntonio Nino Diaz#include <assert_macros.S> 10007433d8SBoyan Karatotev#include <lib/cpus/cpu_ops.h> 116bb96fa6SBoyan Karatotev#include <lib/cpus/errata.h> 12add40351SSoby Mathew 13add40351SSoby Mathew /* 145dd9dbb5SJeenu Viswambharan * Write given expressions as quad words 155dd9dbb5SJeenu Viswambharan * 165dd9dbb5SJeenu Viswambharan * _count: 175dd9dbb5SJeenu Viswambharan * Write at least _count quad words. If the given number of 185dd9dbb5SJeenu Viswambharan * expressions is less than _count, repeat the last expression to 195dd9dbb5SJeenu Viswambharan * fill _count quad words in total 205dd9dbb5SJeenu Viswambharan * _rest: 215dd9dbb5SJeenu Viswambharan * Optional list of expressions. _this is for parameter extraction 225dd9dbb5SJeenu Viswambharan * only, and has no significance to the caller 235dd9dbb5SJeenu Viswambharan * 245dd9dbb5SJeenu Viswambharan * Invoked as: 255dd9dbb5SJeenu Viswambharan * fill_constants 2, foo, bar, blah, ... 26add40351SSoby Mathew */ 275dd9dbb5SJeenu Viswambharan .macro fill_constants _count:req, _this, _rest:vararg 285dd9dbb5SJeenu Viswambharan .ifgt \_count 295dd9dbb5SJeenu Viswambharan /* Write the current expression */ 305dd9dbb5SJeenu Viswambharan .ifb \_this 315dd9dbb5SJeenu Viswambharan .error "Nothing to fill" 325dd9dbb5SJeenu Viswambharan .endif 335dd9dbb5SJeenu Viswambharan .quad \_this 345dd9dbb5SJeenu Viswambharan 355dd9dbb5SJeenu Viswambharan /* Invoke recursively for remaining expressions */ 365dd9dbb5SJeenu Viswambharan .ifnb \_rest 375dd9dbb5SJeenu Viswambharan fill_constants \_count-1, \_rest 385dd9dbb5SJeenu Viswambharan .else 395dd9dbb5SJeenu Viswambharan fill_constants \_count-1, \_this 405dd9dbb5SJeenu Viswambharan .endif 415dd9dbb5SJeenu Viswambharan .endif 425dd9dbb5SJeenu Viswambharan .endm 435dd9dbb5SJeenu Viswambharan 445dd9dbb5SJeenu Viswambharan /* 455dd9dbb5SJeenu Viswambharan * Declare CPU operations 465dd9dbb5SJeenu Viswambharan * 475dd9dbb5SJeenu Viswambharan * _name: 485dd9dbb5SJeenu Viswambharan * Name of the CPU for which operations are being specified 495dd9dbb5SJeenu Viswambharan * _midr: 505dd9dbb5SJeenu Viswambharan * Numeric value expected to read from CPU's MIDR 515dd9dbb5SJeenu Viswambharan * _resetfunc: 525dd9dbb5SJeenu Viswambharan * Reset function for the CPU. If there's no CPU reset function, 535dd9dbb5SJeenu Viswambharan * specify CPU_NO_RESET_FUNC 54a205a56eSDimitris Papastamos * _extra1: 55a205a56eSDimitris Papastamos * This is a placeholder for future per CPU operations. Currently, 56a205a56eSDimitris Papastamos * some CPUs use this entry to set a test function to determine if 57a205a56eSDimitris Papastamos * the workaround for CVE-2017-5715 needs to be applied or not. 58fe007b2eSDimitris Papastamos * _extra2: 59fe007b2eSDimitris Papastamos * This is a placeholder for future per CPU operations. Currently 60fe007b2eSDimitris Papastamos * some CPUs use this entry to set a function to disable the 61fe007b2eSDimitris Papastamos * workaround for CVE-2018-3639. 629b2510b6SBipin Ravi * _extra3: 639b2510b6SBipin Ravi * This is a placeholder for future per CPU operations. Currently, 649b2510b6SBipin Ravi * some CPUs use this entry to set a test function to determine if 659b2510b6SBipin Ravi * the workaround for CVE-2022-23960 needs to be applied or not. 6680942622Slaurenw-arm * _e_handler: 6780942622Slaurenw-arm * This is a placeholder for future per CPU exception handlers. 685dd9dbb5SJeenu Viswambharan * _power_down_ops: 695dd9dbb5SJeenu Viswambharan * Comma-separated list of functions to perform power-down 705dd9dbb5SJeenu Viswambharan * operatios on the CPU. At least one, and up to 715dd9dbb5SJeenu Viswambharan * CPU_MAX_PWR_DWN_OPS number of functions may be specified. 725dd9dbb5SJeenu Viswambharan * Starting at power level 0, these functions shall handle power 735dd9dbb5SJeenu Viswambharan * down at subsequent power levels. If there aren't exactly 745dd9dbb5SJeenu Viswambharan * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be 755dd9dbb5SJeenu Viswambharan * used to handle power down at subsequent levels 765dd9dbb5SJeenu Viswambharan */ 77a205a56eSDimitris Papastamos .macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \ 789b2510b6SBipin Ravi _extra1:req, _extra2:req, _extra3:req, _e_handler:req, _power_down_ops:vararg 79da04341eSChris Kay .section .cpu_ops, "a" 805dd9dbb5SJeenu Viswambharan .align 3 81add40351SSoby Mathew .type cpu_ops_\_name, %object 82add40351SSoby Mathew .quad \_midr 83b1d27b48SRoberto Vargas#if defined(IMAGE_AT_EL3) 845dd9dbb5SJeenu Viswambharan .quad \_resetfunc 85add40351SSoby Mathew#endif 86a205a56eSDimitris Papastamos .quad \_extra1 87fe007b2eSDimitris Papastamos .quad \_extra2 889b2510b6SBipin Ravi .quad \_extra3 8980942622Slaurenw-arm .quad \_e_handler 903d8256b2SMasahiro Yamada#ifdef IMAGE_BL31 915dd9dbb5SJeenu Viswambharan /* Insert list of functions */ 925dd9dbb5SJeenu Viswambharan fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops 93add40351SSoby Mathew#endif 94*3f4c1e1eSBoyan Karatotev /* 95*3f4c1e1eSBoyan Karatotev * It is possible (although unlikely) that a cpu may have no errata in 96*3f4c1e1eSBoyan Karatotev * code. In that case the start label will not be defined. The list is 97*3f4c1e1eSBoyan Karatotev * intended to be used in a loop, so define it as zero-length for 98*3f4c1e1eSBoyan Karatotev * predictable behaviour. Since this macro is always called at the end 99*3f4c1e1eSBoyan Karatotev * of the cpu file (after all errata have been parsed) we can be sure 100*3f4c1e1eSBoyan Karatotev * that we are at the end of the list. Some cpus call declare_cpu_ops 101*3f4c1e1eSBoyan Karatotev * twice, so only do this once. 102*3f4c1e1eSBoyan Karatotev */ 103*3f4c1e1eSBoyan Karatotev .pushsection .rodata.errata_entries 104*3f4c1e1eSBoyan Karatotev .ifndef \_name\()_errata_list_start 105*3f4c1e1eSBoyan Karatotev \_name\()_errata_list_start: 106*3f4c1e1eSBoyan Karatotev .endif 107*3f4c1e1eSBoyan Karatotev .ifndef \_name\()_errata_list_end 108*3f4c1e1eSBoyan Karatotev \_name\()_errata_list_end: 109*3f4c1e1eSBoyan Karatotev .endif 110*3f4c1e1eSBoyan Karatotev .popsection 111*3f4c1e1eSBoyan Karatotev 112*3f4c1e1eSBoyan Karatotev /* and now put them in cpu_ops */ 113*3f4c1e1eSBoyan Karatotev .quad \_name\()_errata_list_start 114*3f4c1e1eSBoyan Karatotev .quad \_name\()_errata_list_end 11510bcd761SJeenu Viswambharan 11610bcd761SJeenu Viswambharan#if REPORT_ERRATA 11710bcd761SJeenu Viswambharan .ifndef \_name\()_cpu_str 11810bcd761SJeenu Viswambharan /* 11910bcd761SJeenu Viswambharan * Place errata reported flag, and the spinlock to arbitrate access to 12010bcd761SJeenu Viswambharan * it in the data section. 12110bcd761SJeenu Viswambharan */ 12210bcd761SJeenu Viswambharan .pushsection .data 12310bcd761SJeenu Viswambharan define_asm_spinlock \_name\()_errata_lock 12410bcd761SJeenu Viswambharan \_name\()_errata_reported: 12510bcd761SJeenu Viswambharan .word 0 12610bcd761SJeenu Viswambharan .popsection 12710bcd761SJeenu Viswambharan 12810bcd761SJeenu Viswambharan /* Place CPU string in rodata */ 12910bcd761SJeenu Viswambharan .pushsection .rodata 13010bcd761SJeenu Viswambharan \_name\()_cpu_str: 13110bcd761SJeenu Viswambharan .asciz "\_name" 13210bcd761SJeenu Viswambharan .popsection 13310bcd761SJeenu Viswambharan .endif 13410bcd761SJeenu Viswambharan 135*3f4c1e1eSBoyan Karatotev 13610bcd761SJeenu Viswambharan /* 13712af5ed4SSoby Mathew * Mandatory errata status printing function for CPUs of 13810bcd761SJeenu Viswambharan * this class. 13910bcd761SJeenu Viswambharan */ 14010bcd761SJeenu Viswambharan .quad \_name\()_errata_report 141*3f4c1e1eSBoyan Karatotev .quad \_name\()_cpu_str 14210bcd761SJeenu Viswambharan 14310bcd761SJeenu Viswambharan#ifdef IMAGE_BL31 14410bcd761SJeenu Viswambharan /* Pointers to errata lock and reported flag */ 14510bcd761SJeenu Viswambharan .quad \_name\()_errata_lock 14610bcd761SJeenu Viswambharan .quad \_name\()_errata_reported 147*3f4c1e1eSBoyan Karatotev#endif /* IMAGE_BL31 */ 148*3f4c1e1eSBoyan Karatotev#endif /* REPORT_ERRATA */ 14910bcd761SJeenu Viswambharan 1503d8256b2SMasahiro Yamada#if defined(IMAGE_BL31) && CRASH_REPORTING 151d3f70af6SSoby Mathew .quad \_name\()_cpu_reg_dump 152d3f70af6SSoby Mathew#endif 153add40351SSoby Mathew .endm 154e2bf57f8SDan Handley 155a205a56eSDimitris Papastamos .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ 156a205a56eSDimitris Papastamos _power_down_ops:vararg 1579b2510b6SBipin Ravi declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, \ 158a205a56eSDimitris Papastamos \_power_down_ops 159a205a56eSDimitris Papastamos .endm 160a205a56eSDimitris Papastamos 16180942622Slaurenw-arm .macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \ 16280942622Slaurenw-arm _e_handler:req, _power_down_ops:vararg 16380942622Slaurenw-arm declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 1649b2510b6SBipin Ravi 0, 0, 0, \_e_handler, \_power_down_ops 16580942622Slaurenw-arm .endm 16680942622Slaurenw-arm 167fe007b2eSDimitris Papastamos .macro declare_cpu_ops_wa _name:req, _midr:req, \ 168fe007b2eSDimitris Papastamos _resetfunc:req, _extra1:req, _extra2:req, \ 1699b2510b6SBipin Ravi _extra3:req, _power_down_ops:vararg 170a205a56eSDimitris Papastamos declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 1719b2510b6SBipin Ravi \_extra1, \_extra2, \_extra3, 0, \_power_down_ops 172a205a56eSDimitris Papastamos .endm 173a205a56eSDimitris Papastamos 174*3f4c1e1eSBoyan Karatotev/* TODO can be deleted once all CPUs have been converted */ 17510bcd761SJeenu Viswambharan#if REPORT_ERRATA 17610bcd761SJeenu Viswambharan /* 17710bcd761SJeenu Viswambharan * Print status of a CPU errata 17810bcd761SJeenu Viswambharan * 17910bcd761SJeenu Viswambharan * _chosen: 18010bcd761SJeenu Viswambharan * Identifier indicating whether or not a CPU errata has been 18110bcd761SJeenu Viswambharan * compiled in. 18210bcd761SJeenu Viswambharan * _cpu: 18310bcd761SJeenu Viswambharan * Name of the CPU 18410bcd761SJeenu Viswambharan * _id: 18510bcd761SJeenu Viswambharan * Errata identifier 18610bcd761SJeenu Viswambharan * _rev_var: 18710bcd761SJeenu Viswambharan * Register containing the combined value CPU revision and variant 18810bcd761SJeenu Viswambharan * - typically the return value of cpu_get_rev_var 18910bcd761SJeenu Viswambharan */ 19010bcd761SJeenu Viswambharan .macro report_errata _chosen, _cpu, _id, _rev_var=x8 19110bcd761SJeenu Viswambharan /* Stash a string with errata ID */ 19210bcd761SJeenu Viswambharan .pushsection .rodata 19310bcd761SJeenu Viswambharan \_cpu\()_errata_\_id\()_str: 19410bcd761SJeenu Viswambharan .asciz "\_id" 19510bcd761SJeenu Viswambharan .popsection 19610bcd761SJeenu Viswambharan 19710bcd761SJeenu Viswambharan /* Check whether errata applies */ 19810bcd761SJeenu Viswambharan mov x0, \_rev_var 1999ec3921cSJonathan Wright /* Shall clobber: x0-x7 */ 20010bcd761SJeenu Viswambharan bl check_errata_\_id 20110bcd761SJeenu Viswambharan 20210bcd761SJeenu Viswambharan .ifeq \_chosen 20310bcd761SJeenu Viswambharan /* 20410bcd761SJeenu Viswambharan * Errata workaround has not been compiled in. If the errata would have 20510bcd761SJeenu Viswambharan * applied had it been compiled in, print its status as missing. 20610bcd761SJeenu Viswambharan */ 20710bcd761SJeenu Viswambharan cbz x0, 900f 20810bcd761SJeenu Viswambharan mov x0, #ERRATA_MISSING 20910bcd761SJeenu Viswambharan .endif 21010bcd761SJeenu Viswambharan900: 21110bcd761SJeenu Viswambharan adr x1, \_cpu\()_cpu_str 21210bcd761SJeenu Viswambharan adr x2, \_cpu\()_errata_\_id\()_str 21310bcd761SJeenu Viswambharan bl errata_print_msg 21410bcd761SJeenu Viswambharan .endm 21510bcd761SJeenu Viswambharan#endif 21610bcd761SJeenu Viswambharan 2173991a6a4SDimitris Papastamos /* 2183991a6a4SDimitris Papastamos * This macro is used on some CPUs to detect if they are vulnerable 2193991a6a4SDimitris Papastamos * to CVE-2017-5715. 2203991a6a4SDimitris Papastamos */ 2213991a6a4SDimitris Papastamos .macro cpu_check_csv2 _reg _label 2223991a6a4SDimitris Papastamos mrs \_reg, id_aa64pfr0_el1 2233991a6a4SDimitris Papastamos ubfx \_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH 2243991a6a4SDimitris Papastamos /* 225ff6f62e1SAntonio Nino Diaz * If the field equals 1, branch targets trained in one context cannot 226ff6f62e1SAntonio Nino Diaz * affect speculative execution in a different context. 227ff6f62e1SAntonio Nino Diaz * 228ff6f62e1SAntonio Nino Diaz * If the field equals 2, it means that the system is also aware of 229ff6f62e1SAntonio Nino Diaz * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we 230ff6f62e1SAntonio Nino Diaz * expect users of the registers to do the right thing. 231ff6f62e1SAntonio Nino Diaz * 232ff6f62e1SAntonio Nino Diaz * Only apply mitigations if the value of this field is 0. 2333991a6a4SDimitris Papastamos */ 234ff6f62e1SAntonio Nino Diaz#if ENABLE_ASSERTIONS 235ff6f62e1SAntonio Nino Diaz cmp \_reg, #3 /* Only values 0 to 2 are expected */ 236ff6f62e1SAntonio Nino Diaz ASM_ASSERT(lo) 237ff6f62e1SAntonio Nino Diaz#endif 238ff6f62e1SAntonio Nino Diaz 239ff6f62e1SAntonio Nino Diaz cmp \_reg, #0 240ff6f62e1SAntonio Nino Diaz bne \_label 2413991a6a4SDimitris Papastamos .endm 242da3b038fSDeepak Pandey 243da3b038fSDeepak Pandey /* 244da3b038fSDeepak Pandey * Helper macro that reads the part number of the current 245da3b038fSDeepak Pandey * CPU and jumps to the given label if it matches the CPU 246da3b038fSDeepak Pandey * MIDR provided. 247da3b038fSDeepak Pandey * 248da3b038fSDeepak Pandey * Clobbers x0. 249da3b038fSDeepak Pandey */ 250da3b038fSDeepak Pandey .macro jump_if_cpu_midr _cpu_midr, _label 251da3b038fSDeepak Pandey mrs x0, midr_el1 252da3b038fSDeepak Pandey ubfx x0, x0, MIDR_PN_SHIFT, #12 253da3b038fSDeepak Pandey cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 254da3b038fSDeepak Pandey b.eq \_label 255da3b038fSDeepak Pandey .endm 256c3cf06f1SAntonio Nino Diaz 257*3f4c1e1eSBoyan Karatotev 258*3f4c1e1eSBoyan Karatotev/* 259*3f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata 260*3f4c1e1eSBoyan Karatotev * will be applied automatically 261*3f4c1e1eSBoyan Karatotev * 262*3f4c1e1eSBoyan Karatotev * _cpu: 263*3f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 264*3f4c1e1eSBoyan Karatotev * 265*3f4c1e1eSBoyan Karatotev * _cve: 266*3f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 267*3f4c1e1eSBoyan Karatotev * 268*3f4c1e1eSBoyan Karatotev * _id: 269*3f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 270*3f4c1e1eSBoyan Karatotev * or CVE macros 271*3f4c1e1eSBoyan Karatotev * 272*3f4c1e1eSBoyan Karatotev * _chosen: 273*3f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 274*3f4c1e1eSBoyan Karatotev * 275*3f4c1e1eSBoyan Karatotev * _apply_at_reset: 276*3f4c1e1eSBoyan Karatotev * Whether the erratum should be automatically applied at reset 277*3f4c1e1eSBoyan Karatotev */ 278*3f4c1e1eSBoyan Karatotev.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req 279*3f4c1e1eSBoyan Karatotev .pushsection .rodata.errata_entries 280*3f4c1e1eSBoyan Karatotev .align 3 281*3f4c1e1eSBoyan Karatotev .ifndef \_cpu\()_errata_list_start 282*3f4c1e1eSBoyan Karatotev \_cpu\()_errata_list_start: 283*3f4c1e1eSBoyan Karatotev .endif 284*3f4c1e1eSBoyan Karatotev 285*3f4c1e1eSBoyan Karatotev /* check if unused and compile out if no references */ 286*3f4c1e1eSBoyan Karatotev .if \_apply_at_reset && \_chosen 287*3f4c1e1eSBoyan Karatotev .quad erratum_\_cpu\()_\_id\()_wa 288*3f4c1e1eSBoyan Karatotev .else 289*3f4c1e1eSBoyan Karatotev .quad 0 290*3f4c1e1eSBoyan Karatotev .endif 291*3f4c1e1eSBoyan Karatotev /* TODO(errata ABI): this prevents all checker functions from 292*3f4c1e1eSBoyan Karatotev * being optimised away. Can be done away with unless the ABI 293*3f4c1e1eSBoyan Karatotev * needs them */ 294*3f4c1e1eSBoyan Karatotev .quad check_erratum_\_cpu\()_\_id 295*3f4c1e1eSBoyan Karatotev /* Will fit CVEs with up to 10 character in the ID field */ 296*3f4c1e1eSBoyan Karatotev .word \_id 297*3f4c1e1eSBoyan Karatotev .hword \_cve 298*3f4c1e1eSBoyan Karatotev .byte \_chosen 299*3f4c1e1eSBoyan Karatotev /* TODO(errata ABI): mitigated field for known but unmitigated 300*3f4c1e1eSBoyan Karatotev * errata */ 301*3f4c1e1eSBoyan Karatotev .byte 0x1 302*3f4c1e1eSBoyan Karatotev .popsection 303*3f4c1e1eSBoyan Karatotev.endm 304*3f4c1e1eSBoyan Karatotev 305*3f4c1e1eSBoyan Karatotev.macro _workaround_start _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req 306*3f4c1e1eSBoyan Karatotev add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_apply_at_reset 307*3f4c1e1eSBoyan Karatotev 308*3f4c1e1eSBoyan Karatotev func erratum_\_cpu\()_\_id\()_wa 309*3f4c1e1eSBoyan Karatotev mov x8, x30 310*3f4c1e1eSBoyan Karatotev 311*3f4c1e1eSBoyan Karatotev /* save rev_var for workarounds that might need it but don't 312*3f4c1e1eSBoyan Karatotev * restore to x0 because few will care */ 313*3f4c1e1eSBoyan Karatotev mov x7, x0 314*3f4c1e1eSBoyan Karatotev bl check_erratum_\_cpu\()_\_id 315*3f4c1e1eSBoyan Karatotev cbz x0, erratum_\_cpu\()_\_id\()_skip 316*3f4c1e1eSBoyan Karatotev.endm 317*3f4c1e1eSBoyan Karatotev 318*3f4c1e1eSBoyan Karatotev.macro _workaround_end _cpu:req, _id:req 319*3f4c1e1eSBoyan Karatotev erratum_\_cpu\()_\_id\()_skip: 320*3f4c1e1eSBoyan Karatotev ret x8 321*3f4c1e1eSBoyan Karatotev endfunc erratum_\_cpu\()_\_id\()_wa 322*3f4c1e1eSBoyan Karatotev.endm 323*3f4c1e1eSBoyan Karatotev 324*3f4c1e1eSBoyan Karatotev/******************************************************************************* 325*3f4c1e1eSBoyan Karatotev * Errata workaround wrappers 326*3f4c1e1eSBoyan Karatotev ******************************************************************************/ 327*3f4c1e1eSBoyan Karatotev/* 328*3f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata 329*3f4c1e1eSBoyan Karatotev * will be applied automatically 330*3f4c1e1eSBoyan Karatotev * 331*3f4c1e1eSBoyan Karatotev * _cpu: 332*3f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 333*3f4c1e1eSBoyan Karatotev * 334*3f4c1e1eSBoyan Karatotev * _cve: 335*3f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 336*3f4c1e1eSBoyan Karatotev * 337*3f4c1e1eSBoyan Karatotev * _id: 338*3f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 339*3f4c1e1eSBoyan Karatotev * or CVE macros 340*3f4c1e1eSBoyan Karatotev * 341*3f4c1e1eSBoyan Karatotev * _chosen: 342*3f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 343*3f4c1e1eSBoyan Karatotev * 344*3f4c1e1eSBoyan Karatotev * in body: 345*3f4c1e1eSBoyan Karatotev * clobber x0 to x7 (please only use those) 346*3f4c1e1eSBoyan Karatotev * argument x7 - cpu_rev_var 347*3f4c1e1eSBoyan Karatotev * 348*3f4c1e1eSBoyan Karatotev * _wa clobbers: x0-x8 (PCS compliant) 349*3f4c1e1eSBoyan Karatotev */ 350*3f4c1e1eSBoyan Karatotev.macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req 351*3f4c1e1eSBoyan Karatotev _workaround_start \_cpu, \_cve, \_id, \_chosen, 1 352*3f4c1e1eSBoyan Karatotev.endm 353*3f4c1e1eSBoyan Karatotev 354*3f4c1e1eSBoyan Karatotev/* 355*3f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. Additional arguments: 356*3f4c1e1eSBoyan Karatotev * 357*3f4c1e1eSBoyan Karatotev * _midr: 358*3f4c1e1eSBoyan Karatotev * Check if CPU's MIDR matches the CPU it's meant for. Must be specified 359*3f4c1e1eSBoyan Karatotev * for errata applied in generic code 360*3f4c1e1eSBoyan Karatotev */ 361*3f4c1e1eSBoyan Karatotev.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr 362*3f4c1e1eSBoyan Karatotev /* 363*3f4c1e1eSBoyan Karatotev * Let errata specify if they need MIDR checking. Sadly, storing the 364*3f4c1e1eSBoyan Karatotev * MIDR in an .equ to retrieve automatically blows up as it stores some 365*3f4c1e1eSBoyan Karatotev * brackets in the symbol 366*3f4c1e1eSBoyan Karatotev */ 367*3f4c1e1eSBoyan Karatotev .ifnb \_midr 368*3f4c1e1eSBoyan Karatotev jump_if_cpu_midr \_midr, 1f 369*3f4c1e1eSBoyan Karatotev b erratum_\_cpu\()_\_id\()_skip 370*3f4c1e1eSBoyan Karatotev 371*3f4c1e1eSBoyan Karatotev 1: 372*3f4c1e1eSBoyan Karatotev .endif 373*3f4c1e1eSBoyan Karatotev _workaround_start \_cpu, \_cve, \_id, \_chosen, 0 374*3f4c1e1eSBoyan Karatotev.endm 375*3f4c1e1eSBoyan Karatotev 376*3f4c1e1eSBoyan Karatotev/* 377*3f4c1e1eSBoyan Karatotev * Usage and arguments identical to `workaround_reset_start`. The _cve argument 378*3f4c1e1eSBoyan Karatotev * is kept here so the same #define can be used as that macro 379*3f4c1e1eSBoyan Karatotev */ 380*3f4c1e1eSBoyan Karatotev.macro workaround_reset_end _cpu:req, _cve:req, _id:req 381*3f4c1e1eSBoyan Karatotev _workaround_end \_cpu, \_id 382*3f4c1e1eSBoyan Karatotev.endm 383*3f4c1e1eSBoyan Karatotev 384*3f4c1e1eSBoyan Karatotev/* 385*3f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. The _cve argument is kept here 386*3f4c1e1eSBoyan Karatotev * so the same #define can be used as that macro. Additional arguments: 387*3f4c1e1eSBoyan Karatotev * 388*3f4c1e1eSBoyan Karatotev * _no_isb: 389*3f4c1e1eSBoyan Karatotev * Optionally do not include the trailing isb. Please disable with the 390*3f4c1e1eSBoyan Karatotev * NO_ISB macro 391*3f4c1e1eSBoyan Karatotev */ 392*3f4c1e1eSBoyan Karatotev.macro workaround_runtime_end _cpu:req, _cve:req, _id:req, _no_isb 393*3f4c1e1eSBoyan Karatotev /* 394*3f4c1e1eSBoyan Karatotev * Runtime errata do not have a reset function to call the isb for them 395*3f4c1e1eSBoyan Karatotev * and missing the isb could be very problematic. It is also likely as 396*3f4c1e1eSBoyan Karatotev * they tend to be scattered in generic code. 397*3f4c1e1eSBoyan Karatotev */ 398*3f4c1e1eSBoyan Karatotev .ifb \_no_isb 399*3f4c1e1eSBoyan Karatotev isb 400*3f4c1e1eSBoyan Karatotev .endif 401*3f4c1e1eSBoyan Karatotev _workaround_end \_cpu, \_id 402*3f4c1e1eSBoyan Karatotev.endm 403*3f4c1e1eSBoyan Karatotev 404*3f4c1e1eSBoyan Karatotev/******************************************************************************* 405*3f4c1e1eSBoyan Karatotev * Errata workaround helpers 406*3f4c1e1eSBoyan Karatotev ******************************************************************************/ 407*3f4c1e1eSBoyan Karatotev/* 408*3f4c1e1eSBoyan Karatotev * Set a bit in a system register. Can set multiple bits but is limited by the 409*3f4c1e1eSBoyan Karatotev * way the ORR instruction encodes them. 410*3f4c1e1eSBoyan Karatotev * 411*3f4c1e1eSBoyan Karatotev * _reg: 412*3f4c1e1eSBoyan Karatotev * Register to write to 413*3f4c1e1eSBoyan Karatotev * 414*3f4c1e1eSBoyan Karatotev * _bit: 415*3f4c1e1eSBoyan Karatotev * Bit to set. Please use a descriptive #define 416*3f4c1e1eSBoyan Karatotev * 417*3f4c1e1eSBoyan Karatotev * _assert: 418*3f4c1e1eSBoyan Karatotev * Optionally whether to read back and assert that the bit has been 419*3f4c1e1eSBoyan Karatotev * written. Please disable with NO_ASSERT macro 420*3f4c1e1eSBoyan Karatotev * 421*3f4c1e1eSBoyan Karatotev * clobbers: x1 422*3f4c1e1eSBoyan Karatotev */ 423*3f4c1e1eSBoyan Karatotev.macro sysreg_bit_set _reg:req, _bit:req, _assert=1 424*3f4c1e1eSBoyan Karatotev mrs x1, \_reg 425*3f4c1e1eSBoyan Karatotev orr x1, x1, #\_bit 426*3f4c1e1eSBoyan Karatotev msr \_reg, x1 427*3f4c1e1eSBoyan Karatotev.endm 428*3f4c1e1eSBoyan Karatotev 429*3f4c1e1eSBoyan Karatotev/* 430*3f4c1e1eSBoyan Karatotev * Apply erratum 431*3f4c1e1eSBoyan Karatotev * 432*3f4c1e1eSBoyan Karatotev * _cpu: 433*3f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 434*3f4c1e1eSBoyan Karatotev * 435*3f4c1e1eSBoyan Karatotev * _cve: 436*3f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 437*3f4c1e1eSBoyan Karatotev * 438*3f4c1e1eSBoyan Karatotev * _id: 439*3f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 440*3f4c1e1eSBoyan Karatotev * or CVE macros 441*3f4c1e1eSBoyan Karatotev * 442*3f4c1e1eSBoyan Karatotev * _chosen: 443*3f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 444*3f4c1e1eSBoyan Karatotev * 445*3f4c1e1eSBoyan Karatotev * clobbers: x0-x9 (PCS compliant) 446*3f4c1e1eSBoyan Karatotev */ 447*3f4c1e1eSBoyan Karatotev.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req 448*3f4c1e1eSBoyan Karatotev .if \_chosen 449*3f4c1e1eSBoyan Karatotev mov x9, x30 450*3f4c1e1eSBoyan Karatotev bl cpu_get_rev_var 451*3f4c1e1eSBoyan Karatotev bl erratum_\_cpu\()_\_id\()_wa 452*3f4c1e1eSBoyan Karatotev mov x30, x9 453*3f4c1e1eSBoyan Karatotev 454*3f4c1e1eSBoyan Karatotev .endif 455*3f4c1e1eSBoyan Karatotev.endm 456*3f4c1e1eSBoyan Karatotev 457*3f4c1e1eSBoyan Karatotev/* 458*3f4c1e1eSBoyan Karatotev * Helpers to select which revisions errata apply to. Don't leave a link 459*3f4c1e1eSBoyan Karatotev * register as the cpu_rev_var_*** will call the ret and we can save on one. 460*3f4c1e1eSBoyan Karatotev * 461*3f4c1e1eSBoyan Karatotev * _cpu: 462*3f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 463*3f4c1e1eSBoyan Karatotev * 464*3f4c1e1eSBoyan Karatotev * _cve: 465*3f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 466*3f4c1e1eSBoyan Karatotev * 467*3f4c1e1eSBoyan Karatotev * _id: 468*3f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 469*3f4c1e1eSBoyan Karatotev * or CVE macros 470*3f4c1e1eSBoyan Karatotev * 471*3f4c1e1eSBoyan Karatotev * _rev_num: 472*3f4c1e1eSBoyan Karatotev * Revision to apply to 473*3f4c1e1eSBoyan Karatotev * 474*3f4c1e1eSBoyan Karatotev * in body: 475*3f4c1e1eSBoyan Karatotev * clobber: x0 to x4 476*3f4c1e1eSBoyan Karatotev * argument: x0 - cpu_rev_var 477*3f4c1e1eSBoyan Karatotev */ 478*3f4c1e1eSBoyan Karatotev.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req 479*3f4c1e1eSBoyan Karatotev func check_erratum_\_cpu\()_\_id 480*3f4c1e1eSBoyan Karatotev mov x1, #\_rev_num 481*3f4c1e1eSBoyan Karatotev b cpu_rev_var_ls 482*3f4c1e1eSBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 483*3f4c1e1eSBoyan Karatotev.endm 484*3f4c1e1eSBoyan Karatotev 485*3f4c1e1eSBoyan Karatotev.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req 486*3f4c1e1eSBoyan Karatotev func check_erratum_\_cpu\()_\_id 487*3f4c1e1eSBoyan Karatotev mov x1, #\_rev_num 488*3f4c1e1eSBoyan Karatotev b cpu_rev_var_hs 489*3f4c1e1eSBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 490*3f4c1e1eSBoyan Karatotev.endm 491*3f4c1e1eSBoyan Karatotev 492*3f4c1e1eSBoyan Karatotev.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req 493*3f4c1e1eSBoyan Karatotev func check_erratum_\_cpu\()_\_id 494*3f4c1e1eSBoyan Karatotev mov x1, #\_rev_num_lo 495*3f4c1e1eSBoyan Karatotev mov x2, #\_rev_num_hi 496*3f4c1e1eSBoyan Karatotev b cpu_rev_var_range 497*3f4c1e1eSBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 498*3f4c1e1eSBoyan Karatotev.endm 499*3f4c1e1eSBoyan Karatotev 500*3f4c1e1eSBoyan Karatotev/******************************************************************************* 501*3f4c1e1eSBoyan Karatotev * CPU reset function wrapper 502*3f4c1e1eSBoyan Karatotev ******************************************************************************/ 503*3f4c1e1eSBoyan Karatotev 504*3f4c1e1eSBoyan Karatotev/* 505*3f4c1e1eSBoyan Karatotev * Wrapper to automatically apply all reset-time errata. Will end with an isb. 506*3f4c1e1eSBoyan Karatotev * 507*3f4c1e1eSBoyan Karatotev * _cpu: 508*3f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 509*3f4c1e1eSBoyan Karatotev * 510*3f4c1e1eSBoyan Karatotev * in body: 511*3f4c1e1eSBoyan Karatotev * clobber x8 to x14 512*3f4c1e1eSBoyan Karatotev * argument x14 - cpu_rev_var 513*3f4c1e1eSBoyan Karatotev */ 514*3f4c1e1eSBoyan Karatotev.macro cpu_reset_func_start _cpu:req 515*3f4c1e1eSBoyan Karatotev func \_cpu\()_reset_func 516*3f4c1e1eSBoyan Karatotev mov x15, x30 517*3f4c1e1eSBoyan Karatotev bl cpu_get_rev_var 518*3f4c1e1eSBoyan Karatotev mov x14, x0 519*3f4c1e1eSBoyan Karatotev 520*3f4c1e1eSBoyan Karatotev /* short circuit the location to avoid searching the list */ 521*3f4c1e1eSBoyan Karatotev adrp x12, \_cpu\()_errata_list_start 522*3f4c1e1eSBoyan Karatotev add x12, x12, :lo12:\_cpu\()_errata_list_start 523*3f4c1e1eSBoyan Karatotev adrp x13, \_cpu\()_errata_list_end 524*3f4c1e1eSBoyan Karatotev add x13, x13, :lo12:\_cpu\()_errata_list_end 525*3f4c1e1eSBoyan Karatotev 526*3f4c1e1eSBoyan Karatotev errata_begin: 527*3f4c1e1eSBoyan Karatotev /* if head catches up with end of list, exit */ 528*3f4c1e1eSBoyan Karatotev cmp x12, x13 529*3f4c1e1eSBoyan Karatotev b.eq errata_end 530*3f4c1e1eSBoyan Karatotev 531*3f4c1e1eSBoyan Karatotev ldr x10, [x12, #ERRATUM_WA_FUNC] 532*3f4c1e1eSBoyan Karatotev /* TODO(errata ABI): check mitigated and checker function fields 533*3f4c1e1eSBoyan Karatotev * for 0 */ 534*3f4c1e1eSBoyan Karatotev ldrb w11, [x12, #ERRATUM_CHOSEN] 535*3f4c1e1eSBoyan Karatotev 536*3f4c1e1eSBoyan Karatotev /* skip if not chosen */ 537*3f4c1e1eSBoyan Karatotev cbz x11, 1f 538*3f4c1e1eSBoyan Karatotev /* skip if runtime erratum */ 539*3f4c1e1eSBoyan Karatotev cbz x10, 1f 540*3f4c1e1eSBoyan Karatotev 541*3f4c1e1eSBoyan Karatotev /* put cpu revision in x0 and call workaround */ 542*3f4c1e1eSBoyan Karatotev mov x0, x14 543*3f4c1e1eSBoyan Karatotev blr x10 544*3f4c1e1eSBoyan Karatotev 1: 545*3f4c1e1eSBoyan Karatotev add x12, x12, #ERRATUM_ENTRY_SIZE 546*3f4c1e1eSBoyan Karatotev b errata_begin 547*3f4c1e1eSBoyan Karatotev errata_end: 548*3f4c1e1eSBoyan Karatotev.endm 549*3f4c1e1eSBoyan Karatotev 550*3f4c1e1eSBoyan Karatotev.macro cpu_reset_func_end _cpu:req 551*3f4c1e1eSBoyan Karatotev isb 552*3f4c1e1eSBoyan Karatotev ret x15 553*3f4c1e1eSBoyan Karatotev endfunc \_cpu\()_reset_func 554*3f4c1e1eSBoyan Karatotev.endm 555c3cf06f1SAntonio Nino Diaz#endif /* CPU_MACROS_S */ 556