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: 52*0d020822SBoyan Karatotev * Reset function for the CPU. 53a205a56eSDimitris Papastamos * _extra1: 54a205a56eSDimitris Papastamos * This is a placeholder for future per CPU operations. Currently, 55a205a56eSDimitris Papastamos * some CPUs use this entry to set a test function to determine if 56a205a56eSDimitris Papastamos * the workaround for CVE-2017-5715 needs to be applied or not. 57fe007b2eSDimitris Papastamos * _extra2: 58fe007b2eSDimitris Papastamos * This is a placeholder for future per CPU operations. Currently 59fe007b2eSDimitris Papastamos * some CPUs use this entry to set a function to disable the 60fe007b2eSDimitris Papastamos * workaround for CVE-2018-3639. 619b2510b6SBipin Ravi * _extra3: 629b2510b6SBipin Ravi * This is a placeholder for future per CPU operations. Currently, 639b2510b6SBipin Ravi * some CPUs use this entry to set a test function to determine if 649b2510b6SBipin Ravi * the workaround for CVE-2022-23960 needs to be applied or not. 654caef42aSArvind Ram Prakash * _extra4: 664caef42aSArvind Ram Prakash * This is a placeholder for future per CPU operations. Currently, 674caef42aSArvind Ram Prakash * some CPUs use this entry to set a test function to determine if 684caef42aSArvind Ram Prakash * the workaround for CVE-2024-7881 needs to be applied or not. 6980942622Slaurenw-arm * _e_handler: 7080942622Slaurenw-arm * This is a placeholder for future per CPU exception handlers. 715dd9dbb5SJeenu Viswambharan * _power_down_ops: 725dd9dbb5SJeenu Viswambharan * Comma-separated list of functions to perform power-down 735dd9dbb5SJeenu Viswambharan * operatios on the CPU. At least one, and up to 745dd9dbb5SJeenu Viswambharan * CPU_MAX_PWR_DWN_OPS number of functions may be specified. 755dd9dbb5SJeenu Viswambharan * Starting at power level 0, these functions shall handle power 765dd9dbb5SJeenu Viswambharan * down at subsequent power levels. If there aren't exactly 775dd9dbb5SJeenu Viswambharan * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be 785dd9dbb5SJeenu Viswambharan * used to handle power down at subsequent levels 795dd9dbb5SJeenu Viswambharan */ 80a205a56eSDimitris Papastamos .macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \ 814caef42aSArvind Ram Prakash _extra1:req, _extra2:req, _extra3:req, _extra4:req, \ 824caef42aSArvind Ram Prakash _e_handler:req, _power_down_ops:vararg 83da04341eSChris Kay .section .cpu_ops, "a" 845dd9dbb5SJeenu Viswambharan .align 3 85add40351SSoby Mathew .type cpu_ops_\_name, %object 86add40351SSoby Mathew .quad \_midr 87b1d27b48SRoberto Vargas#if defined(IMAGE_AT_EL3) 885dd9dbb5SJeenu Viswambharan .quad \_resetfunc 89add40351SSoby Mathew#endif 90a205a56eSDimitris Papastamos .quad \_extra1 91fe007b2eSDimitris Papastamos .quad \_extra2 929b2510b6SBipin Ravi .quad \_extra3 934caef42aSArvind Ram Prakash .quad \_extra4 9480942622Slaurenw-arm .quad \_e_handler 953d8256b2SMasahiro Yamada#ifdef IMAGE_BL31 965dd9dbb5SJeenu Viswambharan /* Insert list of functions */ 975dd9dbb5SJeenu Viswambharan fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops 98add40351SSoby Mathew#endif 993f4c1e1eSBoyan Karatotev /* 1003f4c1e1eSBoyan Karatotev * It is possible (although unlikely) that a cpu may have no errata in 1013f4c1e1eSBoyan Karatotev * code. In that case the start label will not be defined. The list is 1023f4c1e1eSBoyan Karatotev * intended to be used in a loop, so define it as zero-length for 1033f4c1e1eSBoyan Karatotev * predictable behaviour. Since this macro is always called at the end 1043f4c1e1eSBoyan Karatotev * of the cpu file (after all errata have been parsed) we can be sure 1053f4c1e1eSBoyan Karatotev * that we are at the end of the list. Some cpus call declare_cpu_ops 1063f4c1e1eSBoyan Karatotev * twice, so only do this once. 1073f4c1e1eSBoyan Karatotev */ 1083f4c1e1eSBoyan Karatotev .pushsection .rodata.errata_entries 1093f4c1e1eSBoyan Karatotev .ifndef \_name\()_errata_list_start 1103f4c1e1eSBoyan Karatotev \_name\()_errata_list_start: 1113f4c1e1eSBoyan Karatotev .endif 1123f4c1e1eSBoyan Karatotev .ifndef \_name\()_errata_list_end 1133f4c1e1eSBoyan Karatotev \_name\()_errata_list_end: 1143f4c1e1eSBoyan Karatotev .endif 1153f4c1e1eSBoyan Karatotev .popsection 1163f4c1e1eSBoyan Karatotev 1173f4c1e1eSBoyan Karatotev /* and now put them in cpu_ops */ 1183f4c1e1eSBoyan Karatotev .quad \_name\()_errata_list_start 1193f4c1e1eSBoyan Karatotev .quad \_name\()_errata_list_end 12010bcd761SJeenu Viswambharan 12110bcd761SJeenu Viswambharan#if REPORT_ERRATA 12210bcd761SJeenu Viswambharan .ifndef \_name\()_cpu_str 12310bcd761SJeenu Viswambharan /* 12410bcd761SJeenu Viswambharan * Place errata reported flag, and the spinlock to arbitrate access to 12510bcd761SJeenu Viswambharan * it in the data section. 12610bcd761SJeenu Viswambharan */ 12710bcd761SJeenu Viswambharan .pushsection .data 12810bcd761SJeenu Viswambharan define_asm_spinlock \_name\()_errata_lock 12910bcd761SJeenu Viswambharan \_name\()_errata_reported: 13010bcd761SJeenu Viswambharan .word 0 13110bcd761SJeenu Viswambharan .popsection 13210bcd761SJeenu Viswambharan 13310bcd761SJeenu Viswambharan /* Place CPU string in rodata */ 13410bcd761SJeenu Viswambharan .pushsection .rodata 13510bcd761SJeenu Viswambharan \_name\()_cpu_str: 13610bcd761SJeenu Viswambharan .asciz "\_name" 13710bcd761SJeenu Viswambharan .popsection 13810bcd761SJeenu Viswambharan .endif 13910bcd761SJeenu Viswambharan 1403f4c1e1eSBoyan Karatotev .quad \_name\()_cpu_str 14110bcd761SJeenu Viswambharan 14210bcd761SJeenu Viswambharan#ifdef IMAGE_BL31 14310bcd761SJeenu Viswambharan /* Pointers to errata lock and reported flag */ 14410bcd761SJeenu Viswambharan .quad \_name\()_errata_lock 14510bcd761SJeenu Viswambharan .quad \_name\()_errata_reported 1463f4c1e1eSBoyan Karatotev#endif /* IMAGE_BL31 */ 1473f4c1e1eSBoyan Karatotev#endif /* REPORT_ERRATA */ 14810bcd761SJeenu Viswambharan 1493d8256b2SMasahiro Yamada#if defined(IMAGE_BL31) && CRASH_REPORTING 150d3f70af6SSoby Mathew .quad \_name\()_cpu_reg_dump 151d3f70af6SSoby Mathew#endif 152add40351SSoby Mathew .endm 153e2bf57f8SDan Handley 154a205a56eSDimitris Papastamos .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ 155a205a56eSDimitris Papastamos _power_down_ops:vararg 1564caef42aSArvind Ram Prakash declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, 0, \ 157a205a56eSDimitris Papastamos \_power_down_ops 158a205a56eSDimitris Papastamos .endm 159a205a56eSDimitris Papastamos 16080942622Slaurenw-arm .macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \ 16180942622Slaurenw-arm _e_handler:req, _power_down_ops:vararg 16280942622Slaurenw-arm declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 1634caef42aSArvind Ram Prakash 0, 0, 0, 0, \_e_handler, \_power_down_ops 16480942622Slaurenw-arm .endm 16580942622Slaurenw-arm 166fe007b2eSDimitris Papastamos .macro declare_cpu_ops_wa _name:req, _midr:req, \ 167fe007b2eSDimitris Papastamos _resetfunc:req, _extra1:req, _extra2:req, \ 1689b2510b6SBipin Ravi _extra3:req, _power_down_ops:vararg 169a205a56eSDimitris Papastamos declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 1704caef42aSArvind Ram Prakash \_extra1, \_extra2, \_extra3, 0, 0, \_power_down_ops 1714caef42aSArvind Ram Prakash .endm 1724caef42aSArvind Ram Prakash 1734caef42aSArvind Ram Prakash .macro declare_cpu_ops_wa_4 _name:req, _midr:req, \ 1744caef42aSArvind Ram Prakash _resetfunc:req, _extra1:req, _extra2:req, \ 1754caef42aSArvind Ram Prakash _extra3:req, _extra4:req, _power_down_ops:vararg 1764caef42aSArvind Ram Prakash declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ 1774caef42aSArvind Ram Prakash \_extra1, \_extra2, \_extra3, \_extra4, 0, \_power_down_ops 178a205a56eSDimitris Papastamos .endm 179a205a56eSDimitris Papastamos 1803991a6a4SDimitris Papastamos /* 1813991a6a4SDimitris Papastamos * This macro is used on some CPUs to detect if they are vulnerable 1823991a6a4SDimitris Papastamos * to CVE-2017-5715. 1833991a6a4SDimitris Papastamos */ 1843991a6a4SDimitris Papastamos .macro cpu_check_csv2 _reg _label 1853991a6a4SDimitris Papastamos mrs \_reg, id_aa64pfr0_el1 1863991a6a4SDimitris Papastamos ubfx \_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH 1873991a6a4SDimitris Papastamos /* 188ff6f62e1SAntonio Nino Diaz * If the field equals 1, branch targets trained in one context cannot 189ff6f62e1SAntonio Nino Diaz * affect speculative execution in a different context. 190ff6f62e1SAntonio Nino Diaz * 191ff6f62e1SAntonio Nino Diaz * If the field equals 2, it means that the system is also aware of 192ff6f62e1SAntonio Nino Diaz * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we 193ff6f62e1SAntonio Nino Diaz * expect users of the registers to do the right thing. 194ff6f62e1SAntonio Nino Diaz * 195ff6f62e1SAntonio Nino Diaz * Only apply mitigations if the value of this field is 0. 1963991a6a4SDimitris Papastamos */ 197ff6f62e1SAntonio Nino Diaz#if ENABLE_ASSERTIONS 198ff6f62e1SAntonio Nino Diaz cmp \_reg, #3 /* Only values 0 to 2 are expected */ 199ff6f62e1SAntonio Nino Diaz ASM_ASSERT(lo) 200ff6f62e1SAntonio Nino Diaz#endif 201ff6f62e1SAntonio Nino Diaz 202ff6f62e1SAntonio Nino Diaz cmp \_reg, #0 203ff6f62e1SAntonio Nino Diaz bne \_label 2043991a6a4SDimitris Papastamos .endm 205da3b038fSDeepak Pandey 206da3b038fSDeepak Pandey /* 207da3b038fSDeepak Pandey * Helper macro that reads the part number of the current 208da3b038fSDeepak Pandey * CPU and jumps to the given label if it matches the CPU 209da3b038fSDeepak Pandey * MIDR provided. 210da3b038fSDeepak Pandey * 211da3b038fSDeepak Pandey * Clobbers x0. 212da3b038fSDeepak Pandey */ 213da3b038fSDeepak Pandey .macro jump_if_cpu_midr _cpu_midr, _label 214da3b038fSDeepak Pandey mrs x0, midr_el1 215da3b038fSDeepak Pandey ubfx x0, x0, MIDR_PN_SHIFT, #12 216da3b038fSDeepak Pandey cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 217da3b038fSDeepak Pandey b.eq \_label 218da3b038fSDeepak Pandey .endm 219c3cf06f1SAntonio Nino Diaz 2203f4c1e1eSBoyan Karatotev 2213f4c1e1eSBoyan Karatotev/* 2223f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata 2233f4c1e1eSBoyan Karatotev * will be applied automatically 2243f4c1e1eSBoyan Karatotev * 2253f4c1e1eSBoyan Karatotev * _cpu: 2263f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 2273f4c1e1eSBoyan Karatotev * 2283f4c1e1eSBoyan Karatotev * _cve: 2293f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 2303f4c1e1eSBoyan Karatotev * 2313f4c1e1eSBoyan Karatotev * _id: 2323f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 2333f4c1e1eSBoyan Karatotev * or CVE macros 2343f4c1e1eSBoyan Karatotev * 2353f4c1e1eSBoyan Karatotev * _chosen: 2363f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 2373f4c1e1eSBoyan Karatotev * 2383f4c1e1eSBoyan Karatotev * _apply_at_reset: 2393f4c1e1eSBoyan Karatotev * Whether the erratum should be automatically applied at reset 2403f4c1e1eSBoyan Karatotev */ 2413f4c1e1eSBoyan Karatotev.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req 2423f4c1e1eSBoyan Karatotev .pushsection .rodata.errata_entries 2433f4c1e1eSBoyan Karatotev .align 3 2443f4c1e1eSBoyan Karatotev .ifndef \_cpu\()_errata_list_start 2453f4c1e1eSBoyan Karatotev \_cpu\()_errata_list_start: 2463f4c1e1eSBoyan Karatotev .endif 2473f4c1e1eSBoyan Karatotev 2483f4c1e1eSBoyan Karatotev /* check if unused and compile out if no references */ 2493f4c1e1eSBoyan Karatotev .if \_apply_at_reset && \_chosen 2503f4c1e1eSBoyan Karatotev .quad erratum_\_cpu\()_\_id\()_wa 2513f4c1e1eSBoyan Karatotev .else 2523f4c1e1eSBoyan Karatotev .quad 0 2533f4c1e1eSBoyan Karatotev .endif 2543f4c1e1eSBoyan Karatotev /* TODO(errata ABI): this prevents all checker functions from 2553f4c1e1eSBoyan Karatotev * being optimised away. Can be done away with unless the ABI 2563f4c1e1eSBoyan Karatotev * needs them */ 2573f4c1e1eSBoyan Karatotev .quad check_erratum_\_cpu\()_\_id 2583f4c1e1eSBoyan Karatotev /* Will fit CVEs with up to 10 character in the ID field */ 2593f4c1e1eSBoyan Karatotev .word \_id 2603f4c1e1eSBoyan Karatotev .hword \_cve 2613f4c1e1eSBoyan Karatotev .byte \_chosen 2623f4c1e1eSBoyan Karatotev /* TODO(errata ABI): mitigated field for known but unmitigated 2633f4c1e1eSBoyan Karatotev * errata */ 2643f4c1e1eSBoyan Karatotev .byte 0x1 2653f4c1e1eSBoyan Karatotev .popsection 2663f4c1e1eSBoyan Karatotev.endm 2673f4c1e1eSBoyan Karatotev 2683f4c1e1eSBoyan Karatotev.macro _workaround_start _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req 2693f4c1e1eSBoyan Karatotev add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_apply_at_reset 2703f4c1e1eSBoyan Karatotev 2713f4c1e1eSBoyan Karatotev func erratum_\_cpu\()_\_id\()_wa 2723f4c1e1eSBoyan Karatotev mov x8, x30 2733f4c1e1eSBoyan Karatotev 2743f4c1e1eSBoyan Karatotev /* save rev_var for workarounds that might need it but don't 2753f4c1e1eSBoyan Karatotev * restore to x0 because few will care */ 2763f4c1e1eSBoyan Karatotev mov x7, x0 2773f4c1e1eSBoyan Karatotev bl check_erratum_\_cpu\()_\_id 2783f4c1e1eSBoyan Karatotev cbz x0, erratum_\_cpu\()_\_id\()_skip 2793f4c1e1eSBoyan Karatotev.endm 2803f4c1e1eSBoyan Karatotev 2813f4c1e1eSBoyan Karatotev.macro _workaround_end _cpu:req, _id:req 2823f4c1e1eSBoyan Karatotev erratum_\_cpu\()_\_id\()_skip: 2833f4c1e1eSBoyan Karatotev ret x8 2843f4c1e1eSBoyan Karatotev endfunc erratum_\_cpu\()_\_id\()_wa 2853f4c1e1eSBoyan Karatotev.endm 2863f4c1e1eSBoyan Karatotev 2873f4c1e1eSBoyan Karatotev/******************************************************************************* 2883f4c1e1eSBoyan Karatotev * Errata workaround wrappers 2893f4c1e1eSBoyan Karatotev ******************************************************************************/ 2903f4c1e1eSBoyan Karatotev/* 2913f4c1e1eSBoyan Karatotev * Workaround wrappers for errata that apply at reset or runtime. Reset errata 2923f4c1e1eSBoyan Karatotev * will be applied automatically 2933f4c1e1eSBoyan Karatotev * 2943f4c1e1eSBoyan Karatotev * _cpu: 2953f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 2963f4c1e1eSBoyan Karatotev * 2973f4c1e1eSBoyan Karatotev * _cve: 2983f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 2993f4c1e1eSBoyan Karatotev * 3003f4c1e1eSBoyan Karatotev * _id: 3013f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 3023f4c1e1eSBoyan Karatotev * or CVE macros 3033f4c1e1eSBoyan Karatotev * 3043f4c1e1eSBoyan Karatotev * _chosen: 3053f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 3063f4c1e1eSBoyan Karatotev * 3073f4c1e1eSBoyan Karatotev * in body: 3083f4c1e1eSBoyan Karatotev * clobber x0 to x7 (please only use those) 3093f4c1e1eSBoyan Karatotev * argument x7 - cpu_rev_var 3103f4c1e1eSBoyan Karatotev * 3113f4c1e1eSBoyan Karatotev * _wa clobbers: x0-x8 (PCS compliant) 3123f4c1e1eSBoyan Karatotev */ 3133f4c1e1eSBoyan Karatotev.macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req 3143f4c1e1eSBoyan Karatotev _workaround_start \_cpu, \_cve, \_id, \_chosen, 1 3153f4c1e1eSBoyan Karatotev.endm 3163f4c1e1eSBoyan Karatotev 3173f4c1e1eSBoyan Karatotev/* 3183f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. Additional arguments: 3193f4c1e1eSBoyan Karatotev * 3203f4c1e1eSBoyan Karatotev * _midr: 3213f4c1e1eSBoyan Karatotev * Check if CPU's MIDR matches the CPU it's meant for. Must be specified 3223f4c1e1eSBoyan Karatotev * for errata applied in generic code 3233f4c1e1eSBoyan Karatotev */ 3243f4c1e1eSBoyan Karatotev.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr 3253f4c1e1eSBoyan Karatotev /* 3263f4c1e1eSBoyan Karatotev * Let errata specify if they need MIDR checking. Sadly, storing the 3273f4c1e1eSBoyan Karatotev * MIDR in an .equ to retrieve automatically blows up as it stores some 3283f4c1e1eSBoyan Karatotev * brackets in the symbol 3293f4c1e1eSBoyan Karatotev */ 3303f4c1e1eSBoyan Karatotev .ifnb \_midr 3313f4c1e1eSBoyan Karatotev jump_if_cpu_midr \_midr, 1f 3323f4c1e1eSBoyan Karatotev b erratum_\_cpu\()_\_id\()_skip 3333f4c1e1eSBoyan Karatotev 3343f4c1e1eSBoyan Karatotev 1: 3353f4c1e1eSBoyan Karatotev .endif 3363f4c1e1eSBoyan Karatotev _workaround_start \_cpu, \_cve, \_id, \_chosen, 0 3373f4c1e1eSBoyan Karatotev.endm 3383f4c1e1eSBoyan Karatotev 3393f4c1e1eSBoyan Karatotev/* 3403f4c1e1eSBoyan Karatotev * Usage and arguments identical to `workaround_reset_start`. The _cve argument 3413f4c1e1eSBoyan Karatotev * is kept here so the same #define can be used as that macro 3423f4c1e1eSBoyan Karatotev */ 3433f4c1e1eSBoyan Karatotev.macro workaround_reset_end _cpu:req, _cve:req, _id:req 3443f4c1e1eSBoyan Karatotev _workaround_end \_cpu, \_id 3453f4c1e1eSBoyan Karatotev.endm 3463f4c1e1eSBoyan Karatotev 3473f4c1e1eSBoyan Karatotev/* 3483f4c1e1eSBoyan Karatotev * See `workaround_reset_start` for usage info. The _cve argument is kept here 3493f4c1e1eSBoyan Karatotev * so the same #define can be used as that macro. Additional arguments: 3503f4c1e1eSBoyan Karatotev * 3513f4c1e1eSBoyan Karatotev * _no_isb: 3523f4c1e1eSBoyan Karatotev * Optionally do not include the trailing isb. Please disable with the 3533f4c1e1eSBoyan Karatotev * NO_ISB macro 3543f4c1e1eSBoyan Karatotev */ 3553f4c1e1eSBoyan Karatotev.macro workaround_runtime_end _cpu:req, _cve:req, _id:req, _no_isb 3563f4c1e1eSBoyan Karatotev /* 3573f4c1e1eSBoyan Karatotev * Runtime errata do not have a reset function to call the isb for them 3583f4c1e1eSBoyan Karatotev * and missing the isb could be very problematic. It is also likely as 3593f4c1e1eSBoyan Karatotev * they tend to be scattered in generic code. 3603f4c1e1eSBoyan Karatotev */ 3613f4c1e1eSBoyan Karatotev .ifb \_no_isb 3623f4c1e1eSBoyan Karatotev isb 3633f4c1e1eSBoyan Karatotev .endif 3643f4c1e1eSBoyan Karatotev _workaround_end \_cpu, \_id 3653f4c1e1eSBoyan Karatotev.endm 3663f4c1e1eSBoyan Karatotev 3673f4c1e1eSBoyan Karatotev/******************************************************************************* 3683f4c1e1eSBoyan Karatotev * Errata workaround helpers 3693f4c1e1eSBoyan Karatotev ******************************************************************************/ 3703f4c1e1eSBoyan Karatotev/* 3713f4c1e1eSBoyan Karatotev * Set a bit in a system register. Can set multiple bits but is limited by the 3723f4c1e1eSBoyan Karatotev * way the ORR instruction encodes them. 3733f4c1e1eSBoyan Karatotev * 3743f4c1e1eSBoyan Karatotev * _reg: 3753f4c1e1eSBoyan Karatotev * Register to write to 3763f4c1e1eSBoyan Karatotev * 3773f4c1e1eSBoyan Karatotev * _bit: 3783f4c1e1eSBoyan Karatotev * Bit to set. Please use a descriptive #define 3793f4c1e1eSBoyan Karatotev * 3803f4c1e1eSBoyan Karatotev * _assert: 3813f4c1e1eSBoyan Karatotev * Optionally whether to read back and assert that the bit has been 3823f4c1e1eSBoyan Karatotev * written. Please disable with NO_ASSERT macro 3833f4c1e1eSBoyan Karatotev * 3843f4c1e1eSBoyan Karatotev * clobbers: x1 3853f4c1e1eSBoyan Karatotev */ 3863f4c1e1eSBoyan Karatotev.macro sysreg_bit_set _reg:req, _bit:req, _assert=1 3873f4c1e1eSBoyan Karatotev mrs x1, \_reg 3883f4c1e1eSBoyan Karatotev orr x1, x1, #\_bit 3893f4c1e1eSBoyan Karatotev msr \_reg, x1 3903f4c1e1eSBoyan Karatotev.endm 3913f4c1e1eSBoyan Karatotev 3923f4c1e1eSBoyan Karatotev/* 39394a75ad4SBoyan Karatotev * Clear a bit in a system register. Can clear multiple bits but is limited by 39494a75ad4SBoyan Karatotev * the way the BIC instrucion encodes them. 39594a75ad4SBoyan Karatotev * 39694a75ad4SBoyan Karatotev * see sysreg_bit_set for usage 39794a75ad4SBoyan Karatotev */ 39894a75ad4SBoyan Karatotev.macro sysreg_bit_clear _reg:req, _bit:req 39994a75ad4SBoyan Karatotev mrs x1, \_reg 40094a75ad4SBoyan Karatotev bic x1, x1, #\_bit 40194a75ad4SBoyan Karatotev msr \_reg, x1 40294a75ad4SBoyan Karatotev.endm 40394a75ad4SBoyan Karatotev 404bb801857SBoyan Karatotev/* 405bb801857SBoyan Karatotev * Toggle a bit in a system register. Can toggle multiple bits but is limited by 406bb801857SBoyan Karatotev * the way the EOR instrucion encodes them. 407bb801857SBoyan Karatotev * 408bb801857SBoyan Karatotev * see sysreg_bit_set for usage 409bb801857SBoyan Karatotev */ 410bb801857SBoyan Karatotev.macro sysreg_bit_toggle _reg:req, _bit:req, _assert=1 411bb801857SBoyan Karatotev mrs x1, \_reg 412bb801857SBoyan Karatotev eor x1, x1, #\_bit 413bb801857SBoyan Karatotev msr \_reg, x1 414bb801857SBoyan Karatotev.endm 415bb801857SBoyan Karatotev 41694a75ad4SBoyan Karatotev.macro override_vector_table _table:req 41794a75ad4SBoyan Karatotev adr x1, \_table 41894a75ad4SBoyan Karatotev msr vbar_el3, x1 41994a75ad4SBoyan Karatotev.endm 42094a75ad4SBoyan Karatotev 42194a75ad4SBoyan Karatotev/* 422445f7b51SJayanth Dodderi Chidanand * BFI : Inserts bitfield into a system register. 423445f7b51SJayanth Dodderi Chidanand * 424445f7b51SJayanth Dodderi Chidanand * BFI{cond} Rd, Rn, #lsb, #width 425445f7b51SJayanth Dodderi Chidanand */ 426445f7b51SJayanth Dodderi Chidanand.macro sysreg_bitfield_insert _reg:req, _src:req, _lsb:req, _width:req 427445f7b51SJayanth Dodderi Chidanand /* Source value for BFI */ 428445f7b51SJayanth Dodderi Chidanand mov x1, #\_src 429445f7b51SJayanth Dodderi Chidanand mrs x0, \_reg 430445f7b51SJayanth Dodderi Chidanand bfi x0, x1, #\_lsb, #\_width 431445f7b51SJayanth Dodderi Chidanand msr \_reg, x0 432445f7b51SJayanth Dodderi Chidanand.endm 433445f7b51SJayanth Dodderi Chidanand 434ad8b5141SJagdish Gediya.macro sysreg_bitfield_insert_from_gpr _reg:req, _gpr:req, _lsb:req, _width:req 435ad8b5141SJagdish Gediya /* Source value in register for BFI */ 436ad8b5141SJagdish Gediya mov x1, \_gpr 437ad8b5141SJagdish Gediya mrs x0, \_reg 438ad8b5141SJagdish Gediya bfi x0, x1, #\_lsb, #\_width 439ad8b5141SJagdish Gediya msr \_reg, x0 440ad8b5141SJagdish Gediya.endm 441ad8b5141SJagdish Gediya 442445f7b51SJayanth Dodderi Chidanand/* 44336eeb59fSBoyan Karatotev * Extract CPU revision and variant, and combine them into a single numeric for 44436eeb59fSBoyan Karatotev * easier comparison. 44536eeb59fSBoyan Karatotev * 44636eeb59fSBoyan Karatotev * _res: 44736eeb59fSBoyan Karatotev * register where the result will be placed 44836eeb59fSBoyan Karatotev * _tmp: 44936eeb59fSBoyan Karatotev * register to clobber for temporaries 45036eeb59fSBoyan Karatotev */ 45136eeb59fSBoyan Karatotev.macro get_rev_var _res:req, _tmp:req 45236eeb59fSBoyan Karatotev mrs \_tmp, midr_el1 45336eeb59fSBoyan Karatotev 45436eeb59fSBoyan Karatotev /* 45536eeb59fSBoyan Karatotev * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them 45636eeb59fSBoyan Karatotev * as variant[7:4] and revision[3:0] of x0. 45736eeb59fSBoyan Karatotev * 45836eeb59fSBoyan Karatotev * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then 45936eeb59fSBoyan Karatotev * extract x1[3:0] into x0[3:0] retaining other bits. 46036eeb59fSBoyan Karatotev */ 46136eeb59fSBoyan Karatotev ubfx \_res, \_tmp, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) 46236eeb59fSBoyan Karatotev bfxil \_res, \_tmp, #MIDR_REV_SHIFT, #MIDR_REV_BITS 46336eeb59fSBoyan Karatotev.endm 46436eeb59fSBoyan Karatotev 46536eeb59fSBoyan Karatotev/* 4663f4c1e1eSBoyan Karatotev * Apply erratum 4673f4c1e1eSBoyan Karatotev * 4683f4c1e1eSBoyan Karatotev * _cpu: 4693f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 4703f4c1e1eSBoyan Karatotev * 4713f4c1e1eSBoyan Karatotev * _cve: 4723f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 4733f4c1e1eSBoyan Karatotev * 4743f4c1e1eSBoyan Karatotev * _id: 4753f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 4763f4c1e1eSBoyan Karatotev * or CVE macros 4773f4c1e1eSBoyan Karatotev * 4783f4c1e1eSBoyan Karatotev * _chosen: 4793f4c1e1eSBoyan Karatotev * Compile time flag on whether the erratum is included 4803f4c1e1eSBoyan Karatotev * 4814d22b0e5SHarrison Mutai * _get_rev: 4824d22b0e5SHarrison Mutai * Optional parameter that determines whether to insert a call to the CPU revision fetching 483db9ee834SBoyan Karatotev * procedure. Stores the result of this in the temporary register x10 to allow for chaining 4844d22b0e5SHarrison Mutai * 4854d22b0e5SHarrison Mutai * clobbers: x0-x10 (PCS compliant) 4863f4c1e1eSBoyan Karatotev */ 4874d22b0e5SHarrison Mutai.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req, _get_rev=GET_CPU_REV 488cc94e71bSBoyan Karatotev .if (\_chosen && \_get_rev) 4893f4c1e1eSBoyan Karatotev mov x9, x30 4903f4c1e1eSBoyan Karatotev bl cpu_get_rev_var 4914d22b0e5SHarrison Mutai mov x10, x0 4924d22b0e5SHarrison Mutai .elseif (\_chosen) 4934d22b0e5SHarrison Mutai mov x9, x30 4944d22b0e5SHarrison Mutai mov x0, x10 4954d22b0e5SHarrison Mutai .endif 4964d22b0e5SHarrison Mutai 4974d22b0e5SHarrison Mutai .if \_chosen 4983f4c1e1eSBoyan Karatotev bl erratum_\_cpu\()_\_id\()_wa 4993f4c1e1eSBoyan Karatotev mov x30, x9 5003f4c1e1eSBoyan Karatotev .endif 5013f4c1e1eSBoyan Karatotev.endm 5023f4c1e1eSBoyan Karatotev 5033f4c1e1eSBoyan Karatotev/* 5047791ce21SBoyan Karatotev * Helpers to report if an erratum applies. Compares the given revision variant 5057791ce21SBoyan Karatotev * to the given value. Return ERRATA_APPLIES or ERRATA_NOT_APPLIES accordingly. 5067791ce21SBoyan Karatotev * 5077791ce21SBoyan Karatotev * _rev_num: the given revision variant. Or 5087791ce21SBoyan Karatotev * _rev_num_lo,_rev_num_hi: the lower and upper bounds of the revision variant 5097791ce21SBoyan Karatotev * 5107791ce21SBoyan Karatotev * in body: 5117791ce21SBoyan Karatotev * clobber: x0 5127791ce21SBoyan Karatotev * argument: x0 - cpu_rev_var 5137791ce21SBoyan Karatotev */ 5147791ce21SBoyan Karatotev.macro cpu_rev_var_ls _rev_num:req 5157791ce21SBoyan Karatotev cmp x0, #\_rev_num 5167791ce21SBoyan Karatotev cset x0, ls 5177791ce21SBoyan Karatotev.endm 5187791ce21SBoyan Karatotev 5197791ce21SBoyan Karatotev.macro cpu_rev_var_hs _rev_num:req 5207791ce21SBoyan Karatotev cmp x0, #\_rev_num 5217791ce21SBoyan Karatotev cset x0, hs 5227791ce21SBoyan Karatotev.endm 5237791ce21SBoyan Karatotev 5247791ce21SBoyan Karatotev.macro cpu_rev_var_range _rev_num_lo:req, _rev_num_hi:req 5257791ce21SBoyan Karatotev cmp x0, #\_rev_num_lo 5267791ce21SBoyan Karatotev mov x1, #\_rev_num_hi 5277791ce21SBoyan Karatotev ccmp x0, x1, #2, hs 5287791ce21SBoyan Karatotev cset x0, ls 5297791ce21SBoyan Karatotev.endm 5307791ce21SBoyan Karatotev 5317791ce21SBoyan Karatotev/* 5327791ce21SBoyan Karatotev * Helpers to select which revisions errata apply to. 5333f4c1e1eSBoyan Karatotev * 5343f4c1e1eSBoyan Karatotev * _cpu: 5353f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 5363f4c1e1eSBoyan Karatotev * 5373f4c1e1eSBoyan Karatotev * _cve: 5383f4c1e1eSBoyan Karatotev * Whether erratum is a CVE. CVE year if yes, 0 otherwise 5393f4c1e1eSBoyan Karatotev * 5403f4c1e1eSBoyan Karatotev * _id: 5413f4c1e1eSBoyan Karatotev * Erratum or CVE number. Please combine with previous field with ERRATUM 5423f4c1e1eSBoyan Karatotev * or CVE macros 5433f4c1e1eSBoyan Karatotev * 5443f4c1e1eSBoyan Karatotev * _rev_num: 5453f4c1e1eSBoyan Karatotev * Revision to apply to 5463f4c1e1eSBoyan Karatotev * 5473f4c1e1eSBoyan Karatotev * in body: 5487791ce21SBoyan Karatotev * clobber: x0 to x1 5493f4c1e1eSBoyan Karatotev * argument: x0 - cpu_rev_var 5503f4c1e1eSBoyan Karatotev */ 5513f4c1e1eSBoyan Karatotev.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req 5523f4c1e1eSBoyan Karatotev func check_erratum_\_cpu\()_\_id 5537791ce21SBoyan Karatotev cpu_rev_var_ls \_rev_num 5547791ce21SBoyan Karatotev ret 5553f4c1e1eSBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 5563f4c1e1eSBoyan Karatotev.endm 5573f4c1e1eSBoyan Karatotev 5583f4c1e1eSBoyan Karatotev.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req 5593f4c1e1eSBoyan Karatotev func check_erratum_\_cpu\()_\_id 5607791ce21SBoyan Karatotev cpu_rev_var_hs \_rev_num 5617791ce21SBoyan Karatotev ret 5623f4c1e1eSBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 5633f4c1e1eSBoyan Karatotev.endm 5643f4c1e1eSBoyan Karatotev 5653f4c1e1eSBoyan Karatotev.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req 5663f4c1e1eSBoyan Karatotev func check_erratum_\_cpu\()_\_id 5677791ce21SBoyan Karatotev cpu_rev_var_range \_rev_num_lo, \_rev_num_hi 5687791ce21SBoyan Karatotev ret 5693f4c1e1eSBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 5703f4c1e1eSBoyan Karatotev.endm 5713f4c1e1eSBoyan Karatotev 57294a75ad4SBoyan Karatotev.macro check_erratum_chosen _cpu:req, _cve:req, _id:req, _chosen:req 57394a75ad4SBoyan Karatotev func check_erratum_\_cpu\()_\_id 57494a75ad4SBoyan Karatotev .if \_chosen 57594a75ad4SBoyan Karatotev mov x0, #ERRATA_APPLIES 57694a75ad4SBoyan Karatotev .else 57794a75ad4SBoyan Karatotev mov x0, #ERRATA_MISSING 57894a75ad4SBoyan Karatotev .endif 57994a75ad4SBoyan Karatotev ret 58094a75ad4SBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 58194a75ad4SBoyan Karatotev.endm 58294a75ad4SBoyan Karatotev 5837791ce21SBoyan Karatotev/* 5847791ce21SBoyan Karatotev * provide a shorthand for the name format for annoying errata 58536eeb59fSBoyan Karatotev * body: clobber x0 to x4 5867791ce21SBoyan Karatotev */ 58794a75ad4SBoyan Karatotev.macro check_erratum_custom_start _cpu:req, _cve:req, _id:req 58894a75ad4SBoyan Karatotev func check_erratum_\_cpu\()_\_id 58994a75ad4SBoyan Karatotev.endm 59094a75ad4SBoyan Karatotev 59194a75ad4SBoyan Karatotev.macro check_erratum_custom_end _cpu:req, _cve:req, _id:req 59294a75ad4SBoyan Karatotev endfunc check_erratum_\_cpu\()_\_id 59394a75ad4SBoyan Karatotev.endm 59494a75ad4SBoyan Karatotev 59594a75ad4SBoyan Karatotev 5963f4c1e1eSBoyan Karatotev/******************************************************************************* 5973f4c1e1eSBoyan Karatotev * CPU reset function wrapper 5983f4c1e1eSBoyan Karatotev ******************************************************************************/ 5993f4c1e1eSBoyan Karatotev 6003f4c1e1eSBoyan Karatotev/* 6013f4c1e1eSBoyan Karatotev * Wrapper to automatically apply all reset-time errata. Will end with an isb. 6023f4c1e1eSBoyan Karatotev * 6033f4c1e1eSBoyan Karatotev * _cpu: 6043f4c1e1eSBoyan Karatotev * Name of cpu as given to declare_cpu_ops 6053f4c1e1eSBoyan Karatotev * 6063f4c1e1eSBoyan Karatotev * in body: 6073f4c1e1eSBoyan Karatotev * clobber x8 to x14 6083f4c1e1eSBoyan Karatotev * argument x14 - cpu_rev_var 6093f4c1e1eSBoyan Karatotev */ 6103f4c1e1eSBoyan Karatotev.macro cpu_reset_func_start _cpu:req 6113f4c1e1eSBoyan Karatotev func \_cpu\()_reset_func 6123f4c1e1eSBoyan Karatotev mov x15, x30 61336eeb59fSBoyan Karatotev get_rev_var x14, x0 6143f4c1e1eSBoyan Karatotev 6153f4c1e1eSBoyan Karatotev /* short circuit the location to avoid searching the list */ 6163f4c1e1eSBoyan Karatotev adrp x12, \_cpu\()_errata_list_start 6173f4c1e1eSBoyan Karatotev add x12, x12, :lo12:\_cpu\()_errata_list_start 6183f4c1e1eSBoyan Karatotev adrp x13, \_cpu\()_errata_list_end 6193f4c1e1eSBoyan Karatotev add x13, x13, :lo12:\_cpu\()_errata_list_end 6203f4c1e1eSBoyan Karatotev 6213f4c1e1eSBoyan Karatotev errata_begin: 6223f4c1e1eSBoyan Karatotev /* if head catches up with end of list, exit */ 6233f4c1e1eSBoyan Karatotev cmp x12, x13 6243f4c1e1eSBoyan Karatotev b.eq errata_end 6253f4c1e1eSBoyan Karatotev 6263f4c1e1eSBoyan Karatotev ldr x10, [x12, #ERRATUM_WA_FUNC] 6273f4c1e1eSBoyan Karatotev /* TODO(errata ABI): check mitigated and checker function fields 6283f4c1e1eSBoyan Karatotev * for 0 */ 6293f4c1e1eSBoyan Karatotev ldrb w11, [x12, #ERRATUM_CHOSEN] 6303f4c1e1eSBoyan Karatotev 6313f4c1e1eSBoyan Karatotev /* skip if not chosen */ 6323f4c1e1eSBoyan Karatotev cbz x11, 1f 6333f4c1e1eSBoyan Karatotev /* skip if runtime erratum */ 6343f4c1e1eSBoyan Karatotev cbz x10, 1f 6353f4c1e1eSBoyan Karatotev 6363f4c1e1eSBoyan Karatotev /* put cpu revision in x0 and call workaround */ 6373f4c1e1eSBoyan Karatotev mov x0, x14 6383f4c1e1eSBoyan Karatotev blr x10 6393f4c1e1eSBoyan Karatotev 1: 6403f4c1e1eSBoyan Karatotev add x12, x12, #ERRATUM_ENTRY_SIZE 6413f4c1e1eSBoyan Karatotev b errata_begin 6423f4c1e1eSBoyan Karatotev errata_end: 6433f4c1e1eSBoyan Karatotev.endm 6443f4c1e1eSBoyan Karatotev 6453f4c1e1eSBoyan Karatotev.macro cpu_reset_func_end _cpu:req 6463f4c1e1eSBoyan Karatotev isb 6473f4c1e1eSBoyan Karatotev ret x15 6483f4c1e1eSBoyan Karatotev endfunc \_cpu\()_reset_func 6493f4c1e1eSBoyan Karatotev.endm 6504f748cc4SBoyan Karatotev 651c3cf06f1SAntonio Nino Diaz#endif /* CPU_MACROS_S */ 652