1 /*
2 * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /* Runtime firmware routines to report errata status for the current CPU. */
8
9 #include <assert.h>
10 #include <stdbool.h>
11
12 #include <arch_helpers.h>
13 #include <common/debug.h>
14 #include <lib/cpus/errata_report.h>
15 #include <lib/el3_runtime/cpu_data.h>
16 #include <lib/spinlock.h>
17
18 #ifdef IMAGE_BL1
19 # define BL_STRING "BL1"
20 #elif defined(__aarch64__) && defined(IMAGE_BL31)
21 # define BL_STRING "BL31"
22 #elif !defined(__aarch64__) && defined(IMAGE_BL32)
23 # define BL_STRING "BL32"
24 #elif defined(IMAGE_BL2) && BL2_AT_EL3
25 # define BL_STRING "BL2"
26 #else
27 # error This image should not be printing errata status
28 #endif
29
30 /* Errata format: BL stage, CPU, errata ID, message */
31 #define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n"
32
33 /*
34 * Returns whether errata needs to be reported. Passed arguments are private to
35 * a CPU type.
36 */
errata_needs_reporting(spinlock_t * lock,uint32_t * reported)37 int errata_needs_reporting(spinlock_t *lock, uint32_t *reported)
38 {
39 bool report_now;
40
41 /* If already reported, return false. */
42 if (*reported != 0U)
43 return 0;
44
45 /*
46 * Acquire lock. Determine whether status needs reporting, and then mark
47 * report status to true.
48 */
49 spin_lock(lock);
50 report_now = (*reported == 0U);
51 if (report_now)
52 *reported = 1;
53 spin_unlock(lock);
54
55 return report_now;
56 }
57
58 /*
59 * Print errata status message.
60 *
61 * Unknown: WARN
62 * Missing: WARN
63 * Applied: INFO
64 * Not applied: VERBOSE
65 */
errata_print_msg(unsigned int status,const char * cpu,const char * id)66 void errata_print_msg(unsigned int status, const char *cpu, const char *id)
67 {
68 /* Errata status strings */
69 static const char *const errata_status_str[] = {
70 [ERRATA_NOT_APPLIES] = "not applied",
71 [ERRATA_APPLIES] = "applied",
72 [ERRATA_MISSING] = "missing!"
73 };
74 static const char *const __unused bl_str = BL_STRING;
75 const char *msg __unused;
76
77
78 assert(status < ARRAY_SIZE(errata_status_str));
79 assert(cpu != NULL);
80 assert(id != NULL);
81
82 msg = errata_status_str[status];
83
84 switch (status) {
85 case ERRATA_NOT_APPLIES:
86 VERBOSE(ERRATA_FORMAT, bl_str, cpu, id, msg);
87 break;
88
89 case ERRATA_APPLIES:
90 INFO(ERRATA_FORMAT, bl_str, cpu, id, msg);
91 break;
92
93 case ERRATA_MISSING:
94 WARN(ERRATA_FORMAT, bl_str, cpu, id, msg);
95 break;
96
97 default:
98 WARN(ERRATA_FORMAT, bl_str, cpu, id, "unknown");
99 break;
100 }
101 }
102