diff --git a/bl2/bl2.mk b/bl2/bl2.mk index 41bcd127b4ac8da56257e20dbe33dbe783bd37e6..19b955f17e5c34c6f851775b2afaf24c0f173eba 100644 --- a/bl2/bl2.mk +++ b/bl2/bl2.mk @@ -41,8 +41,7 @@ else BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ bl2/${ARCH}/bl2_el3_exceptions.S \ bl2/${ARCH}/bl2_run_next_image.S \ - lib/cpus/${ARCH}/cpu_helpers.S \ - lib/cpus/errata_report.c + lib/cpus/${ARCH}/cpu_helpers.S ifeq (${DISABLE_MTPMU},1) BL2_SOURCES += lib/extensions/mtpmu/${ARCH}/mtpmu.S diff --git a/include/lib/cpus/cpu_ops.h b/include/lib/cpus/cpu_ops.h index 0854fec0052bcd420a606062620806b276e6319d..475ba91d95bc3da4e2504ce1736223cf575d774d 100644 --- a/include/lib/cpus/cpu_ops.h +++ b/include/lib/cpus/cpu_ops.h @@ -102,4 +102,41 @@ #define CPU_OPS_SIZE CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE #endif /* __aarch64__ */ +#ifndef __ASSEMBLER__ +#include <lib/cassert.h> +#include <lib/spinlock.h> + +struct cpu_ops { + unsigned long midr; +#ifdef IMAGE_AT_EL3 + void (*reset_func)(void); +#endif /* IMAGE_AT_EL3 */ +#if __aarch64__ + void (*extra1_func)(void); + void (*extra2_func)(void); + void (*extra3_func)(void); + void (*e_handler_func)(long es); +#endif /* __aarch64__ */ +#if (defined(IMAGE_BL31) || defined(IMAGE_BL32)) && CPU_MAX_PWR_DWN_OPS + void (*pwr_dwn_ops[CPU_MAX_PWR_DWN_OPS])(void); +#endif /* (defined(IMAGE_BL31) || defined(IMAGE_BL32)) && CPU_MAX_PWR_DWN_OPS */ +#if REPORT_ERRATA + void (*errata_func)(void); +#if defined(IMAGE_BL31) || defined(IMAGE_BL32) + spinlock_t *errata_lock; + unsigned int *errata_reported; +#endif /* defined(IMAGE_BL31) || defined(IMAGE_BL32) */ +#endif /* REPORT_ERRATA */ +#if defined(IMAGE_BL31) && CRASH_REPORTING + void (*reg_dump)(void); +#endif /* defined(IMAGE_BL31) && CRASH_REPORTING */ +} __packed; + +CASSERT(sizeof(struct cpu_ops) == CPU_OPS_SIZE, + assert_cpu_ops_asm_c_different_sizes); + +long cpu_get_rev_var(void); +void *get_cpu_ops_ptr(void); + +#endif /* __ASSEMBLER__ */ #endif /* CPU_OPS_H */ diff --git a/include/lib/cpus/errata.h b/include/lib/cpus/errata.h index efdedf0aaad3544923425dbb5a30d325a5346226..f9ab520fc467f89458572650d68e87d7493c62d7 100644 --- a/include/lib/cpus/errata.h +++ b/include/lib/cpus/errata.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,19 +9,8 @@ #ifndef __ASSEMBLER__ -#include <arch.h> -#include <arch_helpers.h> -#include <lib/spinlock.h> -#include <lib/utils_def.h> - -#if DEBUG void print_errata_status(void); -#else -static inline void print_errata_status(void) {} -#endif - void errata_print_msg(unsigned int status, const char *cpu, const char *id); -int errata_needs_reporting(spinlock_t *lock, uint32_t *reported); #endif /* __ASSEMBLER__ */ diff --git a/lib/cpus/aarch32/cpu_helpers.S b/lib/cpus/aarch32/cpu_helpers.S index 25b6308dd7e2d67a07bfe95b7fe0248f462dad59..05bc5d93d7c028ecdbac2c671227b59067081c42 100644 --- a/lib/cpus/aarch32/cpu_helpers.S +++ b/lib/cpus/aarch32/cpu_helpers.S @@ -7,9 +7,9 @@ #include <arch.h> #include <asm_macros.S> #include <assert_macros.S> -#include <lib/cpus/cpu_ops.h> #include <cpu_macros.S> #include <common/bl_common.h> +#include <lib/cpus/cpu_ops.h> #include <lib/el3_runtime/cpu_data.h> #if defined(IMAGE_BL1) || defined(IMAGE_BL32) || \ @@ -205,62 +205,3 @@ func cpu_rev_var_hs movlt r0, #ERRATA_NOT_APPLIES bx lr endfunc cpu_rev_var_hs - -#if REPORT_ERRATA -/* - * void print_errata_status(void); - * - * Function to print errata status for CPUs of its class. Must be called only: - * - * - with MMU and data caches are enabled; - * - after cpu_ops have been initialized in per-CPU data. - */ - .globl print_errata_status -func print_errata_status - /* r12 is pushed only for the sake of 8-byte stack alignment */ - push {r4, r5, r12, lr} -#ifdef IMAGE_BL1 - /* - * BL1 doesn't have per-CPU data. So retrieve the CPU operations - * directly. - */ - bl get_cpu_ops_ptr - ldr r0, [r0, #CPU_ERRATA_FUNC] - cmp r0, #0 - blxne r0 -#else - /* - * Retrieve pointer to cpu_ops, and further, the errata printing - * function. If it's non-NULL, jump to the function in turn. - */ - bl _cpu_data -#if ENABLE_ASSERTIONS - cmp r0, #0 - ASM_ASSERT(ne) -#endif - ldr r1, [r0, #CPU_DATA_CPU_OPS_PTR] -#if ENABLE_ASSERTIONS - cmp r1, #0 - ASM_ASSERT(ne) -#endif - ldr r0, [r1, #CPU_ERRATA_FUNC] - cmp r0, #0 - beq 1f - - mov r4, r0 - - /* - * Load pointers to errata lock and printed flag. Call - * errata_needs_reporting to check whether this CPU needs to report - * errata status pertaining to its class. - */ - ldr r0, [r1, #CPU_ERRATA_LOCK] - ldr r1, [r1, #CPU_ERRATA_PRINTED] - bl errata_needs_reporting - cmp r0, #0 - blxne r4 -1: -#endif - pop {r4, r5, r12, pc} -endfunc print_errata_status -#endif diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S index f92eeebae38176df6a433805b6fbf6991be5e041..a4285eda5708e4640928506b35ec61391df6226c 100644 --- a/lib/cpus/aarch64/cpu_helpers.S +++ b/lib/cpus/aarch64/cpu_helpers.S @@ -280,72 +280,6 @@ func cpu_rev_var_range ret endfunc cpu_rev_var_range -#if REPORT_ERRATA -/* - * void print_errata_status(void); - * - * Function to print errata status for CPUs of its class. Must be called only: - * - * - with MMU and data caches are enabled; - * - after cpu_ops have been initialized in per-CPU data. - */ - .globl print_errata_status -func print_errata_status -#ifdef IMAGE_BL1 - /* - * BL1 doesn't have per-CPU data. So retrieve the CPU operations - * directly. - */ - stp xzr, x30, [sp, #-16]! - bl get_cpu_ops_ptr - ldp xzr, x30, [sp], #16 - ldr x1, [x0, #CPU_ERRATA_FUNC] - cbnz x1, .Lprint -#else - /* - * Retrieve pointer to cpu_ops from per-CPU data, and further, the - * errata printing function. If it's non-NULL, jump to the function in - * turn. - */ - mrs x0, tpidr_el3 -#if ENABLE_ASSERTIONS - cmp x0, #0 - ASM_ASSERT(ne) -#endif - ldr x1, [x0, #CPU_DATA_CPU_OPS_PTR] -#if ENABLE_ASSERTIONS - cmp x1, #0 - ASM_ASSERT(ne) -#endif - ldr x0, [x1, #CPU_ERRATA_FUNC] - cbz x0, .Lnoprint - - /* - * Printing errata status requires atomically testing the printed flag. - */ - stp x19, x30, [sp, #-16]! - mov x19, x0 - - /* - * Load pointers to errata lock and printed flag. Call - * errata_needs_reporting to check whether this CPU needs to report - * errata status pertaining to its class. - */ - ldr x0, [x1, #CPU_ERRATA_LOCK] - ldr x1, [x1, #CPU_ERRATA_PRINTED] - bl errata_needs_reporting - mov x1, x19 - ldp x19, x30, [sp], #16 - cbnz x0, .Lprint -#endif -.Lnoprint: - ret -.Lprint: - /* Jump to errata reporting function for this CPU */ - br x1 -endfunc print_errata_status -#endif - /* * int check_wa_cve_2017_5715(void); * diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c index f289302137867bd7fea050d9689ca2680bea6b5d..8c043285afb16cf6bf43d011bd07849d92c744af 100644 --- a/lib/cpus/errata_report.c +++ b/lib/cpus/errata_report.c @@ -11,6 +11,7 @@ #include <arch_helpers.h> #include <common/debug.h> +#include <lib/cpus/cpu_ops.h> #include <lib/cpus/errata.h> #include <lib/el3_runtime/cpu_data.h> #include <lib/spinlock.h> @@ -30,11 +31,14 @@ /* Errata format: BL stage, CPU, errata ID, message */ #define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n" +#if !REPORT_ERRATA +void print_errata_status(void) {} +#else /* !REPORT_ERRATA */ /* * Returns whether errata needs to be reported. Passed arguments are private to * a CPU type. */ -int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) +static __unused int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) { bool report_now; @@ -55,6 +59,40 @@ int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) return report_now; } +/* + * Function to print errata status for the calling CPU (and others of the same + * type). Must be called only: + * - when MMU and data caches are enabled; + * - after cpu_ops have been initialized in per-CPU data. + */ +void print_errata_status(void) +{ + struct cpu_ops *cpu_ops; +#ifdef IMAGE_BL1 + /* + * BL1 doesn't have per-CPU data. So retrieve the CPU operations + * directly. + */ + cpu_ops = get_cpu_ops_ptr(); + + if (cpu_ops->errata_func != NULL) { + cpu_ops->errata_func(); + } +#else /* IMAGE_BL1 */ + cpu_ops = (void *) get_cpu_data(cpu_ops_ptr); + + assert(cpu_ops != NULL); + + if (cpu_ops->errata_func == NULL) { + return; + } + + if (errata_needs_reporting(cpu_ops->errata_lock, cpu_ops->errata_reported)) { + cpu_ops->errata_func(); + } +#endif /* IMAGE_BL1 */ +} + /* * Print errata status message. * @@ -99,3 +137,4 @@ void errata_print_msg(unsigned int status, const char *cpu, const char *id) break; } } +#endif /* !REPORT_ERRATA */ diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk index 5dd28b95d87606c36a9915f68034f30b643b4ffc..f14ea544b5677dbd1205874df1890f6b17ea45d6 100644 --- a/plat/arm/board/fvp_r/platform.mk +++ b/plat/arm/board/fvp_r/platform.mk @@ -83,6 +83,7 @@ override BL1_SOURCES := drivers/arm/sp805/sp805.c \ drivers/io/io_storage.c \ drivers/io/io_semihosting.c \ lib/cpus/aarch64/cpu_helpers.S \ + lib/cpus/errata_report.c \ lib/fconf/fconf_dyn_cfg_getter.c \ lib/semihosting/semihosting.c \ lib/semihosting/${ARCH}/semihosting_call.S \