1add40351SSoby Mathew/* 2bb801857SBoyan Karatotev * Copyright (c) 2014-2025, 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: 520d020822SBoyan Karatotev * Reset function for the CPU. 5380942622Slaurenw-arm * _e_handler: 5480942622Slaurenw-arm * This is a placeholder for future per CPU exception handlers. 555dd9dbb5SJeenu Viswambharan * _power_down_ops: 565dd9dbb5SJeenu Viswambharan * Comma-separated list of functions to perform power-down 575dd9dbb5SJeenu Viswambharan * operatios on the CPU. At least one, and up to 585dd9dbb5SJeenu Viswambharan * CPU_MAX_PWR_DWN_OPS number of functions may be specified. 595dd9dbb5SJeenu Viswambharan * Starting at power level 0, these functions shall handle power 605dd9dbb5SJeenu Viswambharan * down at subsequent power levels. If there aren't exactly 615dd9dbb5SJeenu Viswambharan * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be 625dd9dbb5SJeenu Viswambharan * used to handle power down at subsequent levels 635dd9dbb5SJeenu Viswambharan */ 64a205a56eSDimitris Papastamos .macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \ 654caef42aSArvind Ram Prakash _e_handler:req, _power_down_ops:vararg 66da04341eSChris Kay .section .cpu_ops, "a" 675dd9dbb5SJeenu Viswambharan .align 3 68add40351SSoby Mathew .type cpu_ops_\_name, %object 69add40351SSoby Mathew .quad \_midr 70b1d27b48SRoberto Vargas#if defined(IMAGE_AT_EL3) 715dd9dbb5SJeenu Viswambharan .quad \_resetfunc 72add40351SSoby Mathew#endif 7380942622Slaurenw-arm .quad \_e_handler 743d8256b2SMasahiro Yamada#ifdef IMAGE_BL31 755dd9dbb5SJeenu Viswambharan /* Insert list of functions */ 765dd9dbb5SJeenu Viswambharan fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops 77add40351SSoby Mathew#endif 783f4c1e1eSBoyan Karatotev /* 793f4c1e1eSBoyan Karatotev * It is possible (although unlikely) that a cpu may have no errata in 803f4c1e1eSBoyan Karatotev * code. In that case the start label will not be defined. The list is 813f4c1e1eSBoyan Karatotev * intended to be used in a loop, so define it as zero-length for 823f4c1e1eSBoyan Karatotev * predictable behaviour. Since this macro is always called at the end 833f4c1e1eSBoyan Karatotev * of the cpu file (after all errata have been parsed) we can be sure 843f4c1e1eSBoyan Karatotev * that we are at the end of the list. Some cpus call declare_cpu_ops 853f4c1e1eSBoyan Karatotev * twice, so only do this once. 863f4c1e1eSBoyan Karatotev */ 873f4c1e1eSBoyan Karatotev .pushsection .rodata.errata_entries 883f4c1e1eSBoyan Karatotev .ifndef \_name\()_errata_list_start 893f4c1e1eSBoyan Karatotev \_name\()_errata_list_start: 903f4c1e1eSBoyan Karatotev .endif 913f4c1e1eSBoyan Karatotev .ifndef \_name\()_errata_list_end 923f4c1e1eSBoyan Karatotev \_name\()_errata_list_end: 933f4c1e1eSBoyan Karatotev .endif 943f4c1e1eSBoyan Karatotev .popsection 953f4c1e1eSBoyan Karatotev 963f4c1e1eSBoyan Karatotev /* and now put them in cpu_ops */ 973f4c1e1eSBoyan Karatotev .quad \_name\()_errata_list_start 983f4c1e1eSBoyan Karatotev .quad \_name\()_errata_list_end 9910bcd761SJeenu Viswambharan 10010bcd761SJeenu Viswambharan#if REPORT_ERRATA 10110bcd761SJeenu Viswambharan .ifndef \_name\()_cpu_str 10210bcd761SJeenu Viswambharan /* 10310bcd761SJeenu Viswambharan * Place errata reported flag, and the spinlock to arbitrate access to 10410bcd761SJeenu Viswambharan * it in the data section. 10510bcd761SJeenu Viswambharan */ 10610bcd761SJeenu Viswambharan .pushsection .data 10710bcd761SJeenu Viswambharan define_asm_spinlock \_name\()_errata_lock 10810bcd761SJeenu Viswambharan \_name\()_errata_reported: 10910bcd761SJeenu Viswambharan .word 0 11010bcd761SJeenu Viswambharan .popsection 11110bcd761SJeenu Viswambharan 11210bcd761SJeenu Viswambharan /* Place CPU string in rodata */ 11310bcd761SJeenu Viswambharan .pushsection .rodata 11410bcd761SJeenu Viswambharan \_name\()_cpu_str: 11510bcd761SJeenu Viswambharan .asciz "\_name" 11610bcd761SJeenu Viswambharan .popsection 11710bcd761SJeenu Viswambharan .endif 11810bcd761SJeenu Viswambharan 1193f4c1e1eSBoyan Karatotev .quad \_name\()_cpu_str 12010bcd761SJeenu Viswambharan 12110bcd761SJeenu Viswambharan#ifdef IMAGE_BL31 12210bcd761SJeenu Viswambharan /* Pointers to errata lock and reported flag */ 12310bcd761SJeenu Viswambharan .quad \_name\()_errata_lock 12410bcd761SJeenu Viswambharan .quad \_name\()_errata_reported 1253f4c1e1eSBoyan Karatotev#endif /* IMAGE_BL31 */ 1263f4c1e1eSBoyan Karatotev#endif /* REPORT_ERRATA */ 12710bcd761SJeenu Viswambharan 1283d8256b2SMasahiro Yamada#if defined(IMAGE_BL31) && CRASH_REPORTING 129d3f70af6SSoby Mathew .quad \_name\()_cpu_reg_dump 130d3f70af6SSoby Mathew#endif 131add40351SSoby Mathew .endm 132e2bf57f8SDan Handley 133a205a56eSDimitris Papastamos .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ 134a205a56eSDimitris Papastamos _power_down_ops:vararg 135fd04156eSArvind Ram Prakash declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, \_power_down_ops 136a205a56eSDimitris Papastamos .endm 137a205a56eSDimitris Papastamos 13880942622Slaurenw-arm .macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \ 13980942622Slaurenw-arm _e_handler:req, _power_down_ops:vararg 14080942622Slaurenw-arm declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 141fd04156eSArvind Ram Prakash \_e_handler, \_power_down_ops 142a205a56eSDimitris Papastamos .endm 143a205a56eSDimitris Papastamos 1443991a6a4SDimitris Papastamos /* 1453991a6a4SDimitris Papastamos * This macro is used on some CPUs to detect if they are vulnerable 1463991a6a4SDimitris Papastamos * to CVE-2017-5715. 1473991a6a4SDimitris Papastamos */ 1483991a6a4SDimitris Papastamos .macro cpu_check_csv2 _reg _label 1493991a6a4SDimitris Papastamos mrs \_reg, id_aa64pfr0_el1 1503991a6a4SDimitris Papastamos ubfx \_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH 1513991a6a4SDimitris Papastamos /* 152ff6f62e1SAntonio Nino Diaz * If the field equals 1, branch targets trained in one context cannot 153ff6f62e1SAntonio Nino Diaz * affect speculative execution in a different context. 154ff6f62e1SAntonio Nino Diaz * 1552b432165SArvind Ram Prakash * If the field equals 2 or 3, it means that the system is also aware of 156ff6f62e1SAntonio Nino Diaz * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we 157ff6f62e1SAntonio Nino Diaz * expect users of the registers to do the right thing. 158ff6f62e1SAntonio Nino Diaz * 159ff6f62e1SAntonio Nino Diaz * Only apply mitigations if the value of this field is 0. 1603991a6a4SDimitris Papastamos */ 161ff6f62e1SAntonio Nino Diaz#if ENABLE_ASSERTIONS 1622b432165SArvind Ram Prakash cmp \_reg, #4 /* Only values 0 to 3 are expected */ 163ff6f62e1SAntonio Nino Diaz ASM_ASSERT(lo) 164ff6f62e1SAntonio Nino Diaz#endif 165ff6f62e1SAntonio Nino Diaz 166ff6f62e1SAntonio Nino Diaz cmp \_reg, #0 167ff6f62e1SAntonio Nino Diaz bne \_label 1683991a6a4SDimitris Papastamos .endm 169da3b038fSDeepak Pandey 170da3b038fSDeepak Pandey /* 171da3b038fSDeepak Pandey * Helper macro that reads the part number of the current 172da3b038fSDeepak Pandey * CPU and jumps to the given label if it matches the CPU 173da3b038fSDeepak Pandey * MIDR provided. 174da3b038fSDeepak Pandey * 175da3b038fSDeepak Pandey * Clobbers x0. 176da3b038fSDeepak Pandey */ 177da3b038fSDeepak Pandey .macro jump_if_cpu_midr _cpu_midr, _label 178da3b038fSDeepak Pandey mrs x0, midr_el1 179da3b038fSDeepak Pandey ubfx x0, x0, MIDR_PN_SHIFT, #12 180da3b038fSDeepak Pandey cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 181da3b038fSDeepak Pandey b.eq \_label 182da3b038fSDeepak Pandey .endm 183c3cf06f1SAntonio Nino Diaz 1843f4c1e1eSBoyan Karatotev 1853f4c1e1eSBoyan Karatotev/* 1863f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata 1873f4c1e1eSBoyan Karatotev * will be applied automatically 1883f4c1e1eSBoyan Karatotev * 1893f4c1e1eSBoyan Karatotev * _cpu: 1903f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 1913f4c1e1eSBoyan Karatotev * 1923f4c1e1eSBoyan Karatotev * _cve: 1933f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 1943f4c1e1eSBoyan Karatotev * 1953f4c1e1eSBoyan Karatotev * _id: 1963f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 1973f4c1e1eSBoyan Karatotev * or CVE macros 1983f4c1e1eSBoyan Karatotev * 1993f4c1e1eSBoyan Karatotev * _chosen: 2003f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 2013f4c1e1eSBoyan Karatotev * 202bbff267bSArvind Ram Prakash * _split_wa: 203bbff267bSArvind Ram Prakash * Flag that indicates whether an erratum has split workaround or not. 204bbff267bSArvind Ram Prakash * Default value is 0. 2053f4c1e1eSBoyan Karatotev */ 206bbff267bSArvind Ram Prakash.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _split_wa=0 207fd04156eSArvind Ram Prakash#if INCLUDE_ERRATA_LIST 2083f4c1e1eSBoyan Karatotev .pushsection .rodata.errata_entries 2093f4c1e1eSBoyan Karatotev .align 3 2103f4c1e1eSBoyan Karatotev .ifndef \_cpu\()_errata_list_start 2113f4c1e1eSBoyan Karatotev \_cpu\()_errata_list_start: 2123f4c1e1eSBoyan Karatotev .endif 2133f4c1e1eSBoyan Karatotev 2143f4c1e1eSBoyan Karatotev .quad check_erratum_\_cpu\()_\_id 2153f4c1e1eSBoyan Karatotev /* Will fit CVEs with up to 10 character in the ID field */ 2163f4c1e1eSBoyan Karatotev .word \_id 2173f4c1e1eSBoyan Karatotev .hword \_cve 218bbff267bSArvind Ram Prakash /* bit magic that appends chosen field based on _split_wa */ 219bbff267bSArvind Ram Prakash .byte ((\_chosen * 0b11) & ((\_split_wa << 1) | \_chosen)) 22089dba82dSBoyan Karatotev .byte 0x0 /* alignment */ 2213f4c1e1eSBoyan Karatotev .popsection 22289dba82dSBoyan Karatotev#endif 2233f4c1e1eSBoyan Karatotev.endm 2243f4c1e1eSBoyan Karatotev 2253f4c1e1eSBoyan Karatotev/******************************************************************************* 2263f4c1e1eSBoyan Karatotev * Errata workaround wrappers 2273f4c1e1eSBoyan Karatotev ******************************************************************************/ 2283f4c1e1eSBoyan Karatotev/* 2293f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata 2303f4c1e1eSBoyan Karatotev * will be applied automatically 2313f4c1e1eSBoyan Karatotev * 2323f4c1e1eSBoyan Karatotev * _cpu: 2333f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 2343f4c1e1eSBoyan Karatotev * 2353f4c1e1eSBoyan Karatotev * _cve: 2363f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 2373f4c1e1eSBoyan Karatotev * 2383f4c1e1eSBoyan Karatotev * _id: 2393f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 2403f4c1e1eSBoyan Karatotev * or CVE macros 2413f4c1e1eSBoyan Karatotev * 2423f4c1e1eSBoyan Karatotev * _chosen: 2433f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 2443f4c1e1eSBoyan Karatotev * 245bbff267bSArvind Ram Prakash * _split_wa: 246bbff267bSArvind Ram Prakash * Flag that indicates whether an erratum has split workaround or not. 247bbff267bSArvind Ram Prakash * Default value is 0. 248bbff267bSArvind Ram Prakash * 2493f4c1e1eSBoyan Karatotev * in body: 2503f4c1e1eSBoyan Karatotev * clobber x0 to x7 (please only use those) 2513f4c1e1eSBoyan Karatotev * argument x7 - cpu_rev_var 2523f4c1e1eSBoyan Karatotev * 2533f4c1e1eSBoyan Karatotev * _wa clobbers: x0-x8 (PCS compliant) 2543f4c1e1eSBoyan Karatotev */ 255bbff267bSArvind Ram Prakash.macro workaround_reset_start _cpu:req, _cve:req, _id:req, \ 256bbff267bSArvind Ram Prakash _chosen:req, _split_wa=0 257bbff267bSArvind Ram Prakash 258bbff267bSArvind Ram Prakash add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_split_wa 25989dba82dSBoyan Karatotev 26089dba82dSBoyan Karatotev .if \_chosen 26189dba82dSBoyan Karatotev /* put errata directly into the reset function */ 26289dba82dSBoyan Karatotev .pushsection .text.asm.\_cpu\()_reset_func, "ax" 26389dba82dSBoyan Karatotev .else 26489dba82dSBoyan Karatotev /* or something else that will get garbage collected by the 26589dba82dSBoyan Karatotev * linker */ 26689dba82dSBoyan Karatotev .pushsection .text.asm.erratum_\_cpu\()_\_id\()_wa, "ax" 26789dba82dSBoyan Karatotev .endif 26889dba82dSBoyan Karatotev /* revision is stored in x14, get it */ 26989dba82dSBoyan Karatotev mov x0, x14 27089dba82dSBoyan Karatotev bl check_erratum_\_cpu\()_\_id 27189dba82dSBoyan Karatotev /* save rev_var for workarounds that might need it */ 27289dba82dSBoyan Karatotev mov x7, x14 27389dba82dSBoyan Karatotev cbz x0, erratum_\_cpu\()_\_id\()_skip_reset 2743f4c1e1eSBoyan Karatotev.endm 2753f4c1e1eSBoyan Karatotev 2763f4c1e1eSBoyan Karatotev/* 2773f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. Additional arguments: 2783f4c1e1eSBoyan Karatotev * 2793f4c1e1eSBoyan Karatotev * _midr: 2803f4c1e1eSBoyan Karatotev * Check if CPU's MIDR matches the CPU it's meant for. Must be specified 2813f4c1e1eSBoyan Karatotev * for errata applied in generic code 2823f4c1e1eSBoyan Karatotev */ 2833f4c1e1eSBoyan Karatotev.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr 28489dba82dSBoyan Karatotev add_erratum_entry \_cpu, \_cve, \_id, \_chosen 28589dba82dSBoyan Karatotev 28689dba82dSBoyan Karatotev func erratum_\_cpu\()_\_id\()_wa 28789dba82dSBoyan Karatotev mov x8, x30 2883f4c1e1eSBoyan Karatotev /* 2893f4c1e1eSBoyan Karatotev * Let errata specify if they need MIDR checking. Sadly, storing the 2903f4c1e1eSBoyan Karatotev * MIDR in an .equ to retrieve automatically blows up as it stores some 2913f4c1e1eSBoyan Karatotev * brackets in the symbol 2923f4c1e1eSBoyan Karatotev */ 2933f4c1e1eSBoyan Karatotev .ifnb \_midr 2943f4c1e1eSBoyan Karatotev jump_if_cpu_midr \_midr, 1f 29589dba82dSBoyan Karatotev b erratum_\_cpu\()_\_id\()_skip_runtime 2963f4c1e1eSBoyan Karatotev 2973f4c1e1eSBoyan Karatotev 1: 2983f4c1e1eSBoyan Karatotev .endif 29989dba82dSBoyan Karatotev /* save rev_var for workarounds that might need it but don't 30089dba82dSBoyan Karatotev * restore to x0 because few will care */ 30189dba82dSBoyan Karatotev mov x7, x0 30289dba82dSBoyan Karatotev bl check_erratum_\_cpu\()_\_id 30389dba82dSBoyan Karatotev cbz x0, erratum_\_cpu\()_\_id\()_skip_runtime 3043f4c1e1eSBoyan Karatotev.endm 3053f4c1e1eSBoyan Karatotev 3063f4c1e1eSBoyan Karatotev/* 3073f4c1e1eSBoyan Karatotev * Usage and arguments identical to `workaround_reset_start`. The _cve argument 3083f4c1e1eSBoyan Karatotev * is kept here so the same #define can be used as that macro 3093f4c1e1eSBoyan Karatotev */ 3103f4c1e1eSBoyan Karatotev.macro workaround_reset_end _cpu:req, _cve:req, _id:req 31189dba82dSBoyan Karatotev erratum_\_cpu\()_\_id\()_skip_reset: 31289dba82dSBoyan Karatotev .popsection 3133f4c1e1eSBoyan Karatotev.endm 3143f4c1e1eSBoyan Karatotev 3153f4c1e1eSBoyan Karatotev/* 3163f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. The _cve argument is kept here 3173f4c1e1eSBoyan Karatotev * so the same #define can be used as that macro. Additional arguments: 3183f4c1e1eSBoyan Karatotev * 3193f4c1e1eSBoyan Karatotev * _no_isb: 3203f4c1e1eSBoyan Karatotev * Optionally do not include the trailing isb. Please disable with the 3213f4c1e1eSBoyan Karatotev * NO_ISB macro 3223f4c1e1eSBoyan Karatotev */ 3233f4c1e1eSBoyan Karatotev.macro workaround_runtime_end _cpu:req, _cve:req, _id:req, _no_isb 3243f4c1e1eSBoyan Karatotev /* 3253f4c1e1eSBoyan Karatotev * Runtime errata do not have a reset function to call the isb for them 3263f4c1e1eSBoyan Karatotev * and missing the isb could be very problematic. It is also likely as 3273f4c1e1eSBoyan Karatotev * they tend to be scattered in generic code. 3283f4c1e1eSBoyan Karatotev */ 3293f4c1e1eSBoyan Karatotev .ifb \_no_isb 3303f4c1e1eSBoyan Karatotev isb 3313f4c1e1eSBoyan Karatotev .endif 33289dba82dSBoyan Karatotev erratum_\_cpu\()_\_id\()_skip_runtime: 33389dba82dSBoyan Karatotev ret x8 33489dba82dSBoyan Karatotev endfunc erratum_\_cpu\()_\_id\()_wa 3353f4c1e1eSBoyan Karatotev.endm 3363f4c1e1eSBoyan Karatotev 3373f4c1e1eSBoyan Karatotev/******************************************************************************* 3383f4c1e1eSBoyan Karatotev * Errata workaround helpers 3393f4c1e1eSBoyan Karatotev ******************************************************************************/ 3403f4c1e1eSBoyan Karatotev/* 3413f4c1e1eSBoyan Karatotev * Set a bit in a system register. Can set multiple bits but is limited by the 3423f4c1e1eSBoyan Karatotev * way the ORR instruction encodes them. 3433f4c1e1eSBoyan Karatotev * 3443f4c1e1eSBoyan Karatotev * _reg: 3453f4c1e1eSBoyan Karatotev * Register to write to 3463f4c1e1eSBoyan Karatotev * 3473f4c1e1eSBoyan Karatotev * _bit: 3483f4c1e1eSBoyan Karatotev * Bit to set. Please use a descriptive #define 3493f4c1e1eSBoyan Karatotev * 3503f4c1e1eSBoyan Karatotev * _assert: 3513f4c1e1eSBoyan Karatotev * Optionally whether to read back and assert that the bit has been 3523f4c1e1eSBoyan Karatotev * written. Please disable with NO_ASSERT macro 3533f4c1e1eSBoyan Karatotev * 3543f4c1e1eSBoyan Karatotev * clobbers: x1 3553f4c1e1eSBoyan Karatotev */ 3563f4c1e1eSBoyan Karatotev.macro sysreg_bit_set _reg:req, _bit:req, _assert=1 3573f4c1e1eSBoyan Karatotev mrs x1, \_reg 3583f4c1e1eSBoyan Karatotev orr x1, x1, #\_bit 3593f4c1e1eSBoyan Karatotev msr \_reg, x1 3603f4c1e1eSBoyan Karatotev.endm 3613f4c1e1eSBoyan Karatotev 3623f4c1e1eSBoyan Karatotev/* 36394a75ad4SBoyan Karatotev * Clear a bit in a system register. Can clear multiple bits but is limited by 36494a75ad4SBoyan Karatotev * the way the BIC instrucion encodes them. 36594a75ad4SBoyan Karatotev * 36694a75ad4SBoyan Karatotev * see sysreg_bit_set for usage 36794a75ad4SBoyan Karatotev */ 36894a75ad4SBoyan Karatotev.macro sysreg_bit_clear _reg:req, _bit:req 36994a75ad4SBoyan Karatotev mrs x1, \_reg 37094a75ad4SBoyan Karatotev bic x1, x1, #\_bit 37194a75ad4SBoyan Karatotev msr \_reg, x1 37294a75ad4SBoyan Karatotev.endm 37394a75ad4SBoyan Karatotev 374bb801857SBoyan Karatotev/* 375bb801857SBoyan Karatotev * Toggle a bit in a system register. Can toggle multiple bits but is limited by 376bb801857SBoyan Karatotev * the way the EOR instrucion encodes them. 377bb801857SBoyan Karatotev * 378bb801857SBoyan Karatotev * see sysreg_bit_set for usage 379bb801857SBoyan Karatotev */ 380bb801857SBoyan Karatotev.macro sysreg_bit_toggle _reg:req, _bit:req, _assert=1 381bb801857SBoyan Karatotev mrs x1, \_reg 382bb801857SBoyan Karatotev eor x1, x1, #\_bit 383bb801857SBoyan Karatotev msr \_reg, x1 384bb801857SBoyan Karatotev.endm 385bb801857SBoyan Karatotev 38694a75ad4SBoyan Karatotev.macro override_vector_table _table:req 38794a75ad4SBoyan Karatotev adr x1, \_table 38894a75ad4SBoyan Karatotev msr vbar_el3, x1 38994a75ad4SBoyan Karatotev.endm 39094a75ad4SBoyan Karatotev 39194a75ad4SBoyan Karatotev/* 392445f7b51SJayanth Dodderi Chidanand * BFI : Inserts bitfield into a system register. 393445f7b51SJayanth Dodderi Chidanand * 394445f7b51SJayanth Dodderi Chidanand * BFI{cond} Rd, Rn, #lsb, #width 395445f7b51SJayanth Dodderi Chidanand */ 396445f7b51SJayanth Dodderi Chidanand.macro sysreg_bitfield_insert _reg:req, _src:req, _lsb:req, _width:req 397445f7b51SJayanth Dodderi Chidanand /* Source value for BFI */ 398445f7b51SJayanth Dodderi Chidanand mov x1, #\_src 399445f7b51SJayanth Dodderi Chidanand mrs x0, \_reg 400445f7b51SJayanth Dodderi Chidanand bfi x0, x1, #\_lsb, #\_width 401445f7b51SJayanth Dodderi Chidanand msr \_reg, x0 402445f7b51SJayanth Dodderi Chidanand.endm 403445f7b51SJayanth Dodderi Chidanand 404ad8b5141SJagdish Gediya.macro sysreg_bitfield_insert_from_gpr _reg:req, _gpr:req, _lsb:req, _width:req 405ad8b5141SJagdish Gediya /* Source value in register for BFI */ 406ad8b5141SJagdish Gediya mov x1, \_gpr 407ad8b5141SJagdish Gediya mrs x0, \_reg 408ad8b5141SJagdish Gediya bfi x0, x1, #\_lsb, #\_width 409ad8b5141SJagdish Gediya msr \_reg, x0 410ad8b5141SJagdish Gediya.endm 411ad8b5141SJagdish Gediya 412445f7b51SJayanth Dodderi Chidanand/* 41336eeb59fSBoyan Karatotev * Extract CPU revision and variant, and combine them into a single numeric for 41436eeb59fSBoyan Karatotev * easier comparison. 41536eeb59fSBoyan Karatotev * 41636eeb59fSBoyan Karatotev * _res: 41736eeb59fSBoyan Karatotev * register where the result will be placed 41836eeb59fSBoyan Karatotev * _tmp: 41936eeb59fSBoyan Karatotev * register to clobber for temporaries 42036eeb59fSBoyan Karatotev */ 42136eeb59fSBoyan Karatotev.macro get_rev_var _res:req, _tmp:req 42236eeb59fSBoyan Karatotev mrs \_tmp, midr_el1 42336eeb59fSBoyan Karatotev 42436eeb59fSBoyan Karatotev /* 42536eeb59fSBoyan Karatotev * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them 42636eeb59fSBoyan Karatotev * as variant[7:4] and revision[3:0] of x0. 42736eeb59fSBoyan Karatotev * 42836eeb59fSBoyan Karatotev * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then 42936eeb59fSBoyan Karatotev * extract x1[3:0] into x0[3:0] retaining other bits. 43036eeb59fSBoyan Karatotev */ 43136eeb59fSBoyan Karatotev ubfx \_res, \_tmp, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) 43236eeb59fSBoyan Karatotev bfxil \_res, \_tmp, #MIDR_REV_SHIFT, #MIDR_REV_BITS 43336eeb59fSBoyan Karatotev.endm 43436eeb59fSBoyan Karatotev 43536eeb59fSBoyan Karatotev/* 4363f4c1e1eSBoyan Karatotev * Apply erratum 4373f4c1e1eSBoyan Karatotev * 4383f4c1e1eSBoyan Karatotev * _cpu: 4393f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 4403f4c1e1eSBoyan Karatotev * 4413f4c1e1eSBoyan Karatotev * _cve: 4423f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 4433f4c1e1eSBoyan Karatotev * 4443f4c1e1eSBoyan Karatotev * _id: 4453f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 4463f4c1e1eSBoyan Karatotev * or CVE macros 4473f4c1e1eSBoyan Karatotev * 4483f4c1e1eSBoyan Karatotev * _chosen: 4493f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 4503f4c1e1eSBoyan Karatotev * 4514d22b0e5SHarrison Mutai * _get_rev: 4524d22b0e5SHarrison Mutai * Optional parameter that determines whether to insert a call to the CPU revision fetching 453db9ee834SBoyan Karatotev * procedure. Stores the result of this in the temporary register x10 to allow for chaining 4544d22b0e5SHarrison Mutai * 4554d22b0e5SHarrison Mutai * clobbers: x0-x10 (PCS compliant) 4563f4c1e1eSBoyan Karatotev */ 4574d22b0e5SHarrison Mutai.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req, _get_rev=GET_CPU_REV 458cc94e71bSBoyan Karatotev .if (\_chosen && \_get_rev) 4593f4c1e1eSBoyan Karatotev mov x9, x30 4603f4c1e1eSBoyan Karatotev bl cpu_get_rev_var 4614d22b0e5SHarrison Mutai mov x10, x0 4624d22b0e5SHarrison Mutai .elseif (\_chosen) 4634d22b0e5SHarrison Mutai mov x9, x30 4644d22b0e5SHarrison Mutai mov x0, x10 4654d22b0e5SHarrison Mutai .endif 4664d22b0e5SHarrison Mutai 4674d22b0e5SHarrison Mutai .if \_chosen 4683f4c1e1eSBoyan Karatotev bl erratum_\_cpu\()_\_id\()_wa 4693f4c1e1eSBoyan Karatotev mov x30, x9 4703f4c1e1eSBoyan Karatotev .endif 4713f4c1e1eSBoyan Karatotev.endm 4723f4c1e1eSBoyan Karatotev 4733f4c1e1eSBoyan Karatotev/* 4747791ce21SBoyan Karatotev * Helpers to report if an erratum applies. Compares the given revision variant 4757791ce21SBoyan Karatotev * to the given value. Return ERRATA_APPLIES or ERRATA_NOT_APPLIES accordingly. 4767791ce21SBoyan Karatotev * 4777791ce21SBoyan Karatotev * _rev_num: the given revision variant. Or 4787791ce21SBoyan Karatotev * _rev_num_lo,_rev_num_hi: the lower and upper bounds of the revision variant 4797791ce21SBoyan Karatotev * 4807791ce21SBoyan Karatotev * in body: 4817791ce21SBoyan Karatotev * clobber: x0 4827791ce21SBoyan Karatotev * argument: x0 - cpu_rev_var 4837791ce21SBoyan Karatotev */ 4847791ce21SBoyan Karatotev.macro cpu_rev_var_ls _rev_num:req 4857791ce21SBoyan Karatotev cmp x0, #\_rev_num 4867791ce21SBoyan Karatotev cset x0, ls 4877791ce21SBoyan Karatotev.endm 4887791ce21SBoyan Karatotev 4897791ce21SBoyan Karatotev.macro cpu_rev_var_hs _rev_num:req 4907791ce21SBoyan Karatotev cmp x0, #\_rev_num 4917791ce21SBoyan Karatotev cset x0, hs 4927791ce21SBoyan Karatotev.endm 4937791ce21SBoyan Karatotev 4947791ce21SBoyan Karatotev.macro cpu_rev_var_range _rev_num_lo:req, _rev_num_hi:req 4957791ce21SBoyan Karatotev cmp x0, #\_rev_num_lo 4967791ce21SBoyan Karatotev mov x1, #\_rev_num_hi 4977791ce21SBoyan Karatotev ccmp x0, x1, #2, hs 4987791ce21SBoyan Karatotev cset x0, ls 4997791ce21SBoyan Karatotev.endm 5007791ce21SBoyan Karatotev 501bdaf0d9bSGovindraj Raja 502bdaf0d9bSGovindraj Raja#if __clang_major__ < 17 503bdaf0d9bSGovindraj Raja/* 504bdaf0d9bSGovindraj Raja * A problem with clang version < 17 can cause resolving nested 505bdaf0d9bSGovindraj Raja * 'cfi_startproc' to fail compilation. 506bdaf0d9bSGovindraj Raja * So add a compatibility variant for start and endfunc expansions 507bdaf0d9bSGovindraj Raja * to ignore `cfi_startproc` and `cfi_endproc`, this to be used only with 508bdaf0d9bSGovindraj Raja * check_errata/reset macros if we build TF-A with clang version < 17 509bdaf0d9bSGovindraj Raja */ 510bdaf0d9bSGovindraj Raja 511bdaf0d9bSGovindraj Raja.macro func_compat _name, _align=2 512bdaf0d9bSGovindraj Raja .section .text.asm.\_name, "ax" 513bdaf0d9bSGovindraj Raja .type \_name, %function 514bdaf0d9bSGovindraj Raja .align \_align 515bdaf0d9bSGovindraj Raja \_name: 516bdaf0d9bSGovindraj Raja#if ENABLE_BTI 517bdac600bSAndre Przywara BTI jc 518bdaf0d9bSGovindraj Raja#endif 519bdaf0d9bSGovindraj Raja.endm 520bdaf0d9bSGovindraj Raja 521bdaf0d9bSGovindraj Raja/* 522bdaf0d9bSGovindraj Raja * This macro is used to mark the end of a function. 523bdaf0d9bSGovindraj Raja */ 524bdaf0d9bSGovindraj Raja.macro endfunc_compat _name 525bdaf0d9bSGovindraj Raja .size \_name, . - \_name 526bdaf0d9bSGovindraj Raja.endm 527bdaf0d9bSGovindraj Raja 528bdaf0d9bSGovindraj Raja#else 529bdaf0d9bSGovindraj Raja 530bdaf0d9bSGovindraj Raja#define func_compat func 531bdaf0d9bSGovindraj Raja#define endfunc_compat endfunc 532bdaf0d9bSGovindraj Raja 533bdaf0d9bSGovindraj Raja#endif /* __clang_version__ < 17 */ 534bdaf0d9bSGovindraj Raja 5357791ce21SBoyan Karatotev/* 5367791ce21SBoyan Karatotev * Helpers to select which revisions errata apply to. 5373f4c1e1eSBoyan Karatotev * 5383f4c1e1eSBoyan Karatotev * _cpu: 5393f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 5403f4c1e1eSBoyan Karatotev * 5413f4c1e1eSBoyan Karatotev * _cve: 5423f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 5433f4c1e1eSBoyan Karatotev * 5443f4c1e1eSBoyan Karatotev * _id: 5453f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 5463f4c1e1eSBoyan Karatotev * or CVE macros 5473f4c1e1eSBoyan Karatotev * 5483f4c1e1eSBoyan Karatotev * _rev_num: 5493f4c1e1eSBoyan Karatotev * Revision to apply to 5503f4c1e1eSBoyan Karatotev * 5513f4c1e1eSBoyan Karatotev * in body: 5527791ce21SBoyan Karatotev * clobber: x0 to x1 5533f4c1e1eSBoyan Karatotev * argument: x0 - cpu_rev_var 5543f4c1e1eSBoyan Karatotev */ 5553f4c1e1eSBoyan Karatotev.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req 556bdaf0d9bSGovindraj Raja func_compat check_erratum_\_cpu\()_\_id 5577791ce21SBoyan Karatotev cpu_rev_var_ls \_rev_num 5587791ce21SBoyan Karatotev ret 559bdaf0d9bSGovindraj Raja endfunc_compat check_erratum_\_cpu\()_\_id 5603f4c1e1eSBoyan Karatotev.endm 5613f4c1e1eSBoyan Karatotev 5623f4c1e1eSBoyan Karatotev.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req 563bdaf0d9bSGovindraj Raja func_compat check_erratum_\_cpu\()_\_id 5647791ce21SBoyan Karatotev cpu_rev_var_hs \_rev_num 5657791ce21SBoyan Karatotev ret 566bdaf0d9bSGovindraj Raja endfunc_compat check_erratum_\_cpu\()_\_id 5673f4c1e1eSBoyan Karatotev.endm 5683f4c1e1eSBoyan Karatotev 5693f4c1e1eSBoyan Karatotev.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req 570bdaf0d9bSGovindraj Raja func_compat check_erratum_\_cpu\()_\_id 5717791ce21SBoyan Karatotev cpu_rev_var_range \_rev_num_lo, \_rev_num_hi 5727791ce21SBoyan Karatotev ret 573bdaf0d9bSGovindraj Raja endfunc_compat check_erratum_\_cpu\()_\_id 5743f4c1e1eSBoyan Karatotev.endm 5753f4c1e1eSBoyan Karatotev 57694a75ad4SBoyan Karatotev.macro check_erratum_chosen _cpu:req, _cve:req, _id:req, _chosen:req 577bdaf0d9bSGovindraj Raja func_compat check_erratum_\_cpu\()_\_id 57894a75ad4SBoyan Karatotev .if \_chosen 57994a75ad4SBoyan Karatotev mov x0, #ERRATA_APPLIES 58094a75ad4SBoyan Karatotev .else 58194a75ad4SBoyan Karatotev mov x0, #ERRATA_MISSING 58294a75ad4SBoyan Karatotev .endif 58394a75ad4SBoyan Karatotev ret 584bdaf0d9bSGovindraj Raja endfunc_compat check_erratum_\_cpu\()_\_id 58594a75ad4SBoyan Karatotev.endm 58694a75ad4SBoyan Karatotev 5877791ce21SBoyan Karatotev/* 5887791ce21SBoyan Karatotev * provide a shorthand for the name format for annoying errata 58936eeb59fSBoyan Karatotev * body: clobber x0 to x4 5907791ce21SBoyan Karatotev */ 59194a75ad4SBoyan Karatotev.macro check_erratum_custom_start _cpu:req, _cve:req, _id:req 592bdaf0d9bSGovindraj Raja func_compat check_erratum_\_cpu\()_\_id 59394a75ad4SBoyan Karatotev.endm 59494a75ad4SBoyan Karatotev 59594a75ad4SBoyan Karatotev.macro check_erratum_custom_end _cpu:req, _cve:req, _id:req 596bdaf0d9bSGovindraj Raja endfunc_compat check_erratum_\_cpu\()_\_id 59794a75ad4SBoyan Karatotev.endm 59894a75ad4SBoyan Karatotev 5993f4c1e1eSBoyan Karatotev/******************************************************************************* 6003f4c1e1eSBoyan Karatotev * CPU reset function wrapper 6013f4c1e1eSBoyan Karatotev ******************************************************************************/ 6023f4c1e1eSBoyan Karatotev 6033f4c1e1eSBoyan Karatotev/* 60489dba82dSBoyan Karatotev * Helper to register a cpu with the errata framework. Begins the definition of 60589dba82dSBoyan Karatotev * the reset function. 60689dba82dSBoyan Karatotev * 60789dba82dSBoyan Karatotev * _cpu: 60889dba82dSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 60989dba82dSBoyan Karatotev */ 61089dba82dSBoyan Karatotev.macro cpu_reset_prologue _cpu:req 611bdaf0d9bSGovindraj Raja func_compat \_cpu\()_reset_func 61289dba82dSBoyan Karatotev mov x15, x30 61389dba82dSBoyan Karatotev get_rev_var x14, x0 61489dba82dSBoyan Karatotev.endm 61589dba82dSBoyan Karatotev 61689dba82dSBoyan Karatotev/* 61789dba82dSBoyan Karatotev * Wrapper of the reset function to automatically apply all reset-time errata. 61889dba82dSBoyan Karatotev * Will end with an isb. 6193f4c1e1eSBoyan Karatotev * 6203f4c1e1eSBoyan Karatotev * _cpu: 6213f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 6223f4c1e1eSBoyan Karatotev * 6233f4c1e1eSBoyan Karatotev * in body: 6243f4c1e1eSBoyan Karatotev * clobber x8 to x14 6253f4c1e1eSBoyan Karatotev * argument x14 - cpu_rev_var 6263f4c1e1eSBoyan Karatotev */ 6273f4c1e1eSBoyan Karatotev.macro cpu_reset_func_start _cpu:req 62889dba82dSBoyan Karatotev /* the func/endfunc macros will change sections. So change the section 62989dba82dSBoyan Karatotev * back to the reset function's */ 63089dba82dSBoyan Karatotev .section .text.asm.\_cpu\()_reset_func, "ax" 6313f4c1e1eSBoyan Karatotev.endm 6323f4c1e1eSBoyan Karatotev 6333f4c1e1eSBoyan Karatotev.macro cpu_reset_func_end _cpu:req 6343f4c1e1eSBoyan Karatotev isb 6353f4c1e1eSBoyan Karatotev ret x15 636bdaf0d9bSGovindraj Raja endfunc_compat \_cpu\()_reset_func 6373f4c1e1eSBoyan Karatotev.endm 6384f748cc4SBoyan Karatotev 6392590e819SBoyan Karatotev/* 6402590e819SBoyan Karatotev * Helper macro that enables Maximum Power Mitigation Mechanism (MPMM) on 6412590e819SBoyan Karatotev * compatible Arm cores. 6422590e819SBoyan Karatotev * 6432590e819SBoyan Karatotev * Clobbers x0. 6442590e819SBoyan Karatotev */ 6452590e819SBoyan Karatotev.macro enable_mpmm 6462590e819SBoyan Karatotev#if ENABLE_MPMM 6472590e819SBoyan Karatotev mrs x0, CPUPPMCR_EL3 6482590e819SBoyan Karatotev /* if CPUPPMCR_EL3.MPMMPINCTL != 0, skip enabling MPMM */ 6492590e819SBoyan Karatotev ands x0, x0, CPUPPMCR_EL3_MPMMPINCTL_BIT 6502590e819SBoyan Karatotev b.ne 1f 6512590e819SBoyan Karatotev sysreg_bit_set CPUPPMCR_EL3, CPUMPMMCR_EL3_MPMM_EN_BIT 6522590e819SBoyan Karatotev 1: 6532590e819SBoyan Karatotev#endif 6542590e819SBoyan Karatotev.endm 6552590e819SBoyan Karatotev 656*461b62b5SBoyan Karatotev/* 657*461b62b5SBoyan Karatotev * Call this just before a return to indicate support for pabandon. Only 658*461b62b5SBoyan Karatotev * necessary on an abandon call, but harmless on a powerdown call. 659*461b62b5SBoyan Karatotev * 660*461b62b5SBoyan Karatotev * PSCI wants us to tell it we handled a pabandon by returning 0. This is the 661*461b62b5SBoyan Karatotev * only way support for it is indicated. 662*461b62b5SBoyan Karatotev */ 663*461b62b5SBoyan Karatotev.macro signal_pabandon_handled 664*461b62b5SBoyan Karatotev mov_imm x0, PABANDON_ACK 665*461b62b5SBoyan Karatotev.endm 666*461b62b5SBoyan Karatotev 667c3cf06f1SAntonio Nino Diaz#endif /* CPU_MACROS_S */ 668