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
231 * Compare the CPU's revision-variant (x0) with a given range (x1 - x2), for errata
232 * application purposes. If the revision-variant is between or includes the given
233 * values, this indicates that errata applies; otherwise not.
235 * Shall clobber: x0-x4
237 .globl cpu_rev_var_range
238 func cpu_rev_var_range
239 mov x3, #ERRATA_APPLIES
240 mov x4, #ERRATA_NOT_APPLIES
249 endfunc cpu_rev_var_range
253 * void print_errata_status(void);
255 * Function to print errata status for CPUs of its class. Must be called only:
257 * - with MMU and data caches are enabled;
258 * - after cpu_ops have been initialized in per-CPU data.
260 .globl print_errata_status
261 func print_errata_status
264 * BL1 doesn't have per-CPU data. So retrieve the CPU operations
267 stp xzr, x30, [sp, #-16]!
269 ldp xzr, x30, [sp], #16
270 ldr x1, [x0, #CPU_ERRATA_FUNC]
274 * Retrieve pointer to cpu_ops from per-CPU data, and further, the
275 * errata printing function. If it's non-NULL, jump to the function in
279 ldr x1, [x0, #CPU_DATA_CPU_OPS_PTR]
280 ldr x0, [x1, #CPU_ERRATA_FUNC]
284 * Printing errata status requires atomically testing the printed flag.
286 stp x19, x30, [sp, #-16]!
290 * Load pointers to errata lock and printed flag. Call
291 * errata_needs_reporting to check whether this CPU needs to report
292 * errata status pertaining to its class.
294 ldr x0, [x1, #CPU_ERRATA_LOCK]
295 ldr x1, [x1, #CPU_ERRATA_PRINTED]
296 bl errata_needs_reporting
298 ldp x19, x30, [sp], #16
304 /* Jump to errata reporting function for this CPU */
306 endfunc print_errata_status
310 * int check_wa_cve_2017_5715(void);
312 * This function returns:
313 * - ERRATA_APPLIES when firmware mitigation is required.
314 * - ERRATA_NOT_APPLIES when firmware mitigation is _not_ required.
315 * - ERRATA_MISSING when firmware mitigation would be required but
316 * is not compiled in.
318 * NOTE: Must be called only after cpu_ops have been initialized
321 .globl check_wa_cve_2017_5715
322 func check_wa_cve_2017_5715
324 #if ENABLE_ASSERTIONS
328 ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR]
329 ldr x0, [x0, #CPU_EXTRA1_FUNC]
331 * If the reserved function pointer is NULL, this CPU
332 * is unaffected by CVE-2017-5715 so bail out.
338 mov x0, #ERRATA_NOT_APPLIES
340 endfunc check_wa_cve_2017_5715
343 * void *wa_cve_2018_3639_get_disable_ptr(void);
345 * Returns a function pointer which is used to disable mitigation
347 * The function pointer is only returned on cores that employ
348 * dynamic mitigation. If the core uses static mitigation or is
349 * unaffected by CVE-2018-3639 this function returns NULL.
351 * NOTE: Must be called only after cpu_ops have been initialized
354 .globl wa_cve_2018_3639_get_disable_ptr
355 func wa_cve_2018_3639_get_disable_ptr
357 #if ENABLE_ASSERTIONS
361 ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR]
362 ldr x0, [x0, #CPU_EXTRA2_FUNC]
364 endfunc wa_cve_2018_3639_get_disable_ptr