Browse Source

refactor(cpus): convert print_errata_status to C

The function is called in a fully initialised C environment and calls
into other C functions. The Aarch differences are minimal and are hidden
by the pre-existing headers. Converting it results into cleaner code
that is the same across both Aarch64 and Aarch32.

To avoid having to do very ugly pointer arithmetic, define a C struct
for the cpu_ops for both Aarch64 and Aarch32.

Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: Idc07c4064e03143c88a4a0e2d10ceda70ba19a50
(cherry picked from commit dd9fae1ce0e7b985c9fe8f8f8ae358b8c166c6a9)
Boyan Karatotev 1 year ago
parent
commit
30abae00bc

+ 1 - 2
bl2/bl2.mk

@@ -35,8 +35,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

+ 37 - 0
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 */

+ 1 - 12
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__ */
 

+ 1 - 60
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) || (defined(IMAGE_BL2) && BL2_AT_EL3)
@@ -204,62 +204,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

+ 0 - 66
lib/cpus/aarch64/cpu_helpers.S

@@ -279,72 +279,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);
  *

+ 40 - 1
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 */

+ 1 - 0
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	\