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