blob: 4c131a31d9c411daf33e2c402447747ac1f48396 [file] [log] [blame]
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +00001/*
Yann Gautier322e60a2021-10-06 17:34:12 +02002 * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +00003 *
dp-arm82cb2c12017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +00005 */
6
7/* Runtime firmware routines to report errata status for the current CPU. */
8
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +00009#include <assert.h>
Antonio Nino Diaz43534992018-10-25 17:11:02 +010010#include <stdbool.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000011
12#include <arch_helpers.h>
13#include <common/debug.h>
Boyan Karatotev30abae02023-01-25 18:50:10 +000014#include <lib/cpus/cpu_ops.h>
Boyan Karatotevf8b21662023-01-27 09:37:07 +000015#include <lib/cpus/errata.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000016#include <lib/el3_runtime/cpu_data.h>
17#include <lib/spinlock.h>
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000018
19#ifdef IMAGE_BL1
20# define BL_STRING "BL1"
Julius Werner402b3cf2019-07-09 14:02:43 -070021#elif defined(__aarch64__) && defined(IMAGE_BL31)
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000022# define BL_STRING "BL31"
Yann Gautier322e60a2021-10-06 17:34:12 +020023#elif !defined(__aarch64__) && defined(IMAGE_BL32)
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000024# define BL_STRING "BL32"
Roberto Vargasb1d27b42017-10-30 14:43:43 +000025#elif defined(IMAGE_BL2) && BL2_AT_EL3
26# define BL_STRING "BL2"
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000027#else
28# error This image should not be printing errata status
29#endif
30
31/* Errata format: BL stage, CPU, errata ID, message */
Dimitris Papastamosc0ca14d2018-01-16 10:42:20 +000032#define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n"
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000033
Boyan Karatotev30abae02023-01-25 18:50:10 +000034#if !REPORT_ERRATA
35void print_errata_status(void) {}
36#else /* !REPORT_ERRATA */
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000037/*
38 * Returns whether errata needs to be reported. Passed arguments are private to
39 * a CPU type.
40 */
Boyan Karatotev30abae02023-01-25 18:50:10 +000041static __unused int errata_needs_reporting(spinlock_t *lock, uint32_t *reported)
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000042{
Antonio Nino Diaz43534992018-10-25 17:11:02 +010043 bool report_now;
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000044
45 /* If already reported, return false. */
Antonio Nino Diaz43534992018-10-25 17:11:02 +010046 if (*reported != 0U)
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000047 return 0;
48
49 /*
50 * Acquire lock. Determine whether status needs reporting, and then mark
51 * report status to true.
52 */
53 spin_lock(lock);
Antonio Nino Diaz43534992018-10-25 17:11:02 +010054 report_now = (*reported == 0U);
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000055 if (report_now)
56 *reported = 1;
57 spin_unlock(lock);
58
59 return report_now;
60}
61
62/*
Boyan Karatotev30abae02023-01-25 18:50:10 +000063 * Function to print errata status for the calling CPU (and others of the same
64 * type). Must be called only:
65 * - when MMU and data caches are enabled;
66 * - after cpu_ops have been initialized in per-CPU data.
67 */
68void print_errata_status(void)
69{
70 struct cpu_ops *cpu_ops;
71#ifdef IMAGE_BL1
72 /*
73 * BL1 doesn't have per-CPU data. So retrieve the CPU operations
74 * directly.
75 */
76 cpu_ops = get_cpu_ops_ptr();
77
78 if (cpu_ops->errata_func != NULL) {
79 cpu_ops->errata_func();
80 }
81#else /* IMAGE_BL1 */
82 cpu_ops = (void *) get_cpu_data(cpu_ops_ptr);
83
84 assert(cpu_ops != NULL);
85
86 if (cpu_ops->errata_func == NULL) {
87 return;
88 }
89
90 if (errata_needs_reporting(cpu_ops->errata_lock, cpu_ops->errata_reported)) {
91 cpu_ops->errata_func();
92 }
93#endif /* IMAGE_BL1 */
94}
95
96/*
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +000097 * Print errata status message.
98 *
99 * Unknown: WARN
100 * Missing: WARN
101 * Applied: INFO
102 * Not applied: VERBOSE
103 */
Varun Wadekar6311f632017-06-07 09:57:42 -0700104void errata_print_msg(unsigned int status, const char *cpu, const char *id)
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +0000105{
106 /* Errata status strings */
107 static const char *const errata_status_str[] = {
108 [ERRATA_NOT_APPLIES] = "not applied",
109 [ERRATA_APPLIES] = "applied",
110 [ERRATA_MISSING] = "missing!"
111 };
112 static const char *const __unused bl_str = BL_STRING;
113 const char *msg __unused;
114
115
David Cunado0dd41952017-06-21 16:52:45 +0100116 assert(status < ARRAY_SIZE(errata_status_str));
Antonio Nino Diaz43534992018-10-25 17:11:02 +0100117 assert(cpu != NULL);
118 assert(id != NULL);
Jeenu Viswambharan10bcd762017-01-03 11:01:51 +0000119
120 msg = errata_status_str[status];
121
122 switch (status) {
123 case ERRATA_NOT_APPLIES:
124 VERBOSE(ERRATA_FORMAT, bl_str, cpu, id, msg);
125 break;
126
127 case ERRATA_APPLIES:
128 INFO(ERRATA_FORMAT, bl_str, cpu, id, msg);
129 break;
130
131 case ERRATA_MISSING:
132 WARN(ERRATA_FORMAT, bl_str, cpu, id, msg);
133 break;
134
135 default:
136 WARN(ERRATA_FORMAT, bl_str, cpu, id, "unknown");
137 break;
138 }
139}
Boyan Karatotev30abae02023-01-25 18:50:10 +0000140#endif /* !REPORT_ERRATA */