2 * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
8 #include <asm_macros.S>
9 #include <assert_macros.S>
10 #include <common/bl_common.h>
11 #include <common/debug.h>
12 #include <cpu_macros.S>
13 #include <lib/cpus/errata_report.h>
14 #include <lib/el3_runtime/cpu_data.h>
16 /* Reset fn is needed in BL at reset vector */
17 #if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
19 * The reset handler common to all platforms. After a matching
20 * cpu_ops structure entry is found, the correponding reset_handler
21 * in the cpu_ops is invoked.
22 * Clobbers: x0 - x19, x30
28 /* The plat_reset_handler can clobber x0 - x18, x30 */
31 /* Get the matching cpu_ops pointer */
38 /* Get the cpu_ops reset handler */
39 ldr x2, [x0, #CPU_RESET_FUNC]
43 /* The cpu_ops reset handler can clobber x0 - x19, x30 */
51 #ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */
53 * void prepare_cpu_pwr_dwn(unsigned int power_level)
55 * Prepare CPU power down function for all platforms. The function takes
56 * a domain level to be powered down as its parameter. After the cpu_ops
57 * pointer is retrieved from cpu_data, the handler for requested power
60 .globl prepare_cpu_pwr_dwn
61 func prepare_cpu_pwr_dwn
63 * If the given power level exceeds CPU_MAX_PWR_DWN_OPS, we call the
64 * power down handler for the last power level
66 mov_imm x2, (CPU_MAX_PWR_DWN_OPS - 1)
71 ldr x0, [x1, #CPU_DATA_CPU_OPS_PTR]
77 /* Get the appropriate power down handler */
78 mov x1, #CPU_PWR_DWN_OPS
79 add x1, x1, x2, lsl #3
82 endfunc prepare_cpu_pwr_dwn
86 * Initializes the cpu_ops_ptr if not already initialized
87 * in cpu_data. This can be called without a runtime stack, but may
88 * only be called after the MMU is enabled.
89 * clobbers: x0 - x6, x10
94 ldr x0, [x6, #CPU_DATA_CPU_OPS_PTR]
102 str x0, [x6, #CPU_DATA_CPU_OPS_PTR]!
107 #endif /* IMAGE_BL31 */
109 #if defined(IMAGE_BL31) && CRASH_REPORTING
111 * The cpu specific registers which need to be reported in a crash
112 * are reported via cpu_ops cpu_reg_dump function. After a matching
113 * cpu_ops structure entry is found, the correponding cpu_reg_dump
114 * in the cpu_ops is invoked.
116 .globl do_cpu_reg_dump
120 /* Get the matching cpu_ops pointer */
124 /* Get the cpu_ops cpu_reg_dump */
125 ldr x2, [x0, #CPU_REG_DUMP]
131 endfunc do_cpu_reg_dump
135 * The below function returns the cpu_ops structure matching the
136 * midr of the core. It reads the MIDR_EL1 and finds the matching
137 * entry in cpu_ops entries. Only the implementation and part number
138 * are used to match the entries.
140 * x0 - The matching cpu_ops pointer on Success
144 .globl get_cpu_ops_ptr
146 /* Get the cpu_ops start and end locations */
147 adr x4, (__CPU_OPS_START__ + CPU_MIDR)
148 adr x5, (__CPU_OPS_END__ + CPU_MIDR)
150 /* Initialize the return parameter */
153 /* Read the MIDR_EL1 */
155 mov_imm x3, CPU_IMPL_PN_MASK
157 /* Retain only the implementation and part number using mask */
160 /* Check if we have reached end of list */
164 /* load the midr from the cpu_ops */
165 ldr x1, [x4], #CPU_OPS_SIZE
168 /* Check if midr matches to midr of this core */
172 /* Subtract the increment and offset to get the cpu-ops pointer */
173 sub x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
176 endfunc get_cpu_ops_ptr
179 * Extract CPU revision and variant, and combine them into a single numeric for
182 .globl cpu_get_rev_var
187 * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them
188 * as variant[7:4] and revision[3:0] of x0.
190 * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then
191 * extract x1[3:0] into x0[3:0] retaining other bits.
193 ubfx x0, x1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
194 bfxil x0, x1, #MIDR_REV_SHIFT, #MIDR_REV_BITS
196 endfunc cpu_get_rev_var
199 * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
200 * application purposes. If the revision-variant is less than or same as a given
201 * value, indicates that errata applies; otherwise not.
203 * Shall clobber: x0-x3
205 .globl cpu_rev_var_ls
207 mov x2, #ERRATA_APPLIES
208 mov x3, #ERRATA_NOT_APPLIES
212 endfunc cpu_rev_var_ls
215 * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
216 * application purposes. If the revision-variant is higher than or same as a
217 * given value, indicates that errata applies; otherwise not.
219 * Shall clobber: x0-x3
221 .globl cpu_rev_var_hs
223 mov x2, #ERRATA_APPLIES
224 mov x3, #ERRATA_NOT_APPLIES
228 endfunc cpu_rev_var_hs
232 * void print_errata_status(void);
234 * Function to print errata status for CPUs of its class. Must be called only:
236 * - with MMU and data caches are enabled;
237 * - after cpu_ops have been initialized in per-CPU data.
239 .globl print_errata_status
240 func print_errata_status
243 * BL1 doesn't have per-CPU data. So retrieve the CPU operations
246 stp xzr, x30, [sp, #-16]!
248 ldp xzr, x30, [sp], #16
249 ldr x1, [x0, #CPU_ERRATA_FUNC]
253 * Retrieve pointer to cpu_ops from per-CPU data, and further, the
254 * errata printing function. If it's non-NULL, jump to the function in
258 ldr x1, [x0, #CPU_DATA_CPU_OPS_PTR]
259 ldr x0, [x1, #CPU_ERRATA_FUNC]
263 * Printing errata status requires atomically testing the printed flag.
265 stp x19, x30, [sp, #-16]!
269 * Load pointers to errata lock and printed flag. Call
270 * errata_needs_reporting to check whether this CPU needs to report
271 * errata status pertaining to its class.
273 ldr x0, [x1, #CPU_ERRATA_LOCK]
274 ldr x1, [x1, #CPU_ERRATA_PRINTED]
275 bl errata_needs_reporting
277 ldp x19, x30, [sp], #16
283 /* Jump to errata reporting function for this CPU */
285 endfunc print_errata_status
289 * int check_wa_cve_2017_5715(void);
291 * This function returns:
292 * - ERRATA_APPLIES when firmware mitigation is required.
293 * - ERRATA_NOT_APPLIES when firmware mitigation is _not_ required.
294 * - ERRATA_MISSING when firmware mitigation would be required but
295 * is not compiled in.
297 * NOTE: Must be called only after cpu_ops have been initialized
300 .globl check_wa_cve_2017_5715
301 func check_wa_cve_2017_5715
303 #if ENABLE_ASSERTIONS
307 ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR]
308 ldr x0, [x0, #CPU_EXTRA1_FUNC]
310 * If the reserved function pointer is NULL, this CPU
311 * is unaffected by CVE-2017-5715 so bail out.
317 mov x0, #ERRATA_NOT_APPLIES
319 endfunc check_wa_cve_2017_5715
322 * void *wa_cve_2018_3639_get_disable_ptr(void);
324 * Returns a function pointer which is used to disable mitigation
326 * The function pointer is only returned on cores that employ
327 * dynamic mitigation. If the core uses static mitigation or is
328 * unaffected by CVE-2018-3639 this function returns NULL.
330 * NOTE: Must be called only after cpu_ops have been initialized
333 .globl wa_cve_2018_3639_get_disable_ptr
334 func wa_cve_2018_3639_get_disable_ptr
336 #if ENABLE_ASSERTIONS
340 ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR]
341 ldr x0, [x0, #CPU_EXTRA2_FUNC]
343 endfunc wa_cve_2018_3639_get_disable_ptr