blob: e0a9076e041870a1b4f71e40328438a5b386f8ec [file] [log] [blame]
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +00001/*
Sona Mathewd7a54c82024-07-18 21:53:09 -05002 * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +00003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +00005 */
6
7/* Runtime firmware routines to report errata status for the current CPU. */
8
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +00009#include <assert.h>
Antonio Nino Diaz9fe40fd2018-10-25 17:11:02 +010010#include <stdbool.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
12#include <arch_helpers.h>
13#include <common/debug.h>
Boyan Karatotev06236c92023-01-25 18:50:10 +000014#include <lib/cpus/cpu_ops.h>
Boyan Karatotev5d38cb32023-01-27 09:37:07 +000015#include <lib/cpus/errata.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016#include <lib/el3_runtime/cpu_data.h>
17#include <lib/spinlock.h>
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +000018
19#ifdef IMAGE_BL1
20# define BL_STRING "BL1"
Julius Werner8e0ef0f2019-07-09 14:02:43 -070021#elif defined(__aarch64__) && defined(IMAGE_BL31)
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +000022# define BL_STRING "BL31"
Yann Gautier9335ff52021-10-06 17:34:12 +020023#elif !defined(__aarch64__) && defined(IMAGE_BL32)
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +000024# define BL_STRING "BL32"
Arvind Ram Prakash11b9b492022-11-22 14:41:00 -060025#elif defined(IMAGE_BL2) && RESET_TO_BL2
Roberto Vargase0e99462017-10-30 14:43:43 +000026# define BL_STRING "BL2"
Jeenu Viswambharand5ec3672017-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 Papastamos84e02dc2018-01-16 10:42:20 +000032#define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n"
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +000033
Boyan Karatotev29fa56d2023-01-27 09:38:15 +000034#define CVE_FORMAT "%s: %s: CPU workaround for CVE %u_%u was %s\n"
35#define ERRATUM_FORMAT "%s: %s: CPU workaround for erratum %u was %s\n"
36
Boyan Karatotev29fa56d2023-01-27 09:38:15 +000037
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010038static __unused void print_status(int status, char *cpu_str, uint16_t cve, uint32_t id)
39{
40 if (status == ERRATA_MISSING) {
41 if (cve) {
42 WARN(CVE_FORMAT, BL_STRING, cpu_str, cve, id, "missing!");
43 } else {
44 WARN(ERRATUM_FORMAT, BL_STRING, cpu_str, id, "missing!");
45 }
46 } else if (status == ERRATA_APPLIES) {
47 if (cve) {
48 INFO(CVE_FORMAT, BL_STRING, cpu_str, cve, id, "applied");
49 } else {
50 INFO(ERRATUM_FORMAT, BL_STRING, cpu_str, id, "applied");
51 }
52 } else {
53 if (cve) {
Sona Mathewd7a54c82024-07-18 21:53:09 -050054 VERBOSE(CVE_FORMAT, BL_STRING, cpu_str, cve, id, "not applicable");
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010055 } else {
Sona Mathewd7a54c82024-07-18 21:53:09 -050056 VERBOSE(ERRATUM_FORMAT, BL_STRING, cpu_str, id, "not applicable");
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010057 }
58 }
59}
Boyan Karatotev29fa56d2023-01-27 09:38:15 +000060
Boyan Karatotev06236c92023-01-25 18:50:10 +000061#if !REPORT_ERRATA
62void print_errata_status(void) {}
63#else /* !REPORT_ERRATA */
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010064/*
65 * New errata status message printer
66 * The order checking function is hidden behind the FEATURE_DETECTION flag to
67 * save space. This functionality is only useful on development and platform
68 * bringup builds, when FEATURE_DETECTION should be used anyway
69 */
Ryan Everettd34d7fd2024-05-10 14:56:02 +010070void generic_errata_report(void)
Boyan Karatotev29fa56d2023-01-27 09:38:15 +000071{
72 struct cpu_ops *cpu_ops = get_cpu_ops_ptr();
73 struct erratum_entry *entry = cpu_ops->errata_list_start;
74 struct erratum_entry *end = cpu_ops->errata_list_end;
75 long rev_var = cpu_get_rev_var();
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010076#if FEATURE_DETECTION
Boyan Karatotev29fa56d2023-01-27 09:38:15 +000077 uint32_t last_erratum_id = 0;
78 uint16_t last_cve_yr = 0;
79 bool check_cve = false;
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010080 bool failed = false;
81#endif /* FEATURE_DETECTION */
Boyan Karatotev29fa56d2023-01-27 09:38:15 +000082
83 for (; entry != end; entry += 1) {
84 uint64_t status = entry->check_func(rev_var);
85
86 assert(entry->id != 0);
87
88 /*
89 * Errata workaround has not been compiled in. If the errata
90 * would have applied had it been compiled in, print its status
91 * as missing.
92 */
93 if (status == ERRATA_APPLIES && entry->chosen == 0) {
94 status = ERRATA_MISSING;
95 }
96
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010097 print_status(status, cpu_ops->cpu_str, entry->cve, entry->id);
Boyan Karatotev29fa56d2023-01-27 09:38:15 +000098
Boyan Karatoteva3e1b072023-06-09 13:22:16 +010099#if FEATURE_DETECTION
100 if (entry->cve) {
Boyan Karatotev29fa56d2023-01-27 09:38:15 +0000101 if (last_cve_yr > entry->cve ||
102 (last_cve_yr == entry->cve && last_erratum_id >= entry->id)) {
103 ERROR("CVE %u_%u was out of order!\n",
104 entry->cve, entry->id);
105 failed = true;
106 }
107 check_cve = true;
108 last_cve_yr = entry->cve;
109 } else {
Boyan Karatotev29fa56d2023-01-27 09:38:15 +0000110 if (last_erratum_id >= entry->id || check_cve) {
111 ERROR("Erratum %u was out of order!\n",
112 entry->id);
113 failed = true;
114 }
115 }
116 last_erratum_id = entry->id;
Boyan Karatoteva3e1b072023-06-09 13:22:16 +0100117#endif /* FEATURE_DETECTION */
Boyan Karatotev29fa56d2023-01-27 09:38:15 +0000118 }
119
Boyan Karatoteva3e1b072023-06-09 13:22:16 +0100120#if FEATURE_DETECTION
Boyan Karatotev29fa56d2023-01-27 09:38:15 +0000121 /*
122 * enforce errata and CVEs are in ascending order and that CVEs are
123 * after errata
124 */
125 assert(!failed);
Boyan Karatoteva3e1b072023-06-09 13:22:16 +0100126#endif /* FEATURE_DETECTION */
Boyan Karatotev29fa56d2023-01-27 09:38:15 +0000127}
128
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +0000129/*
130 * Returns whether errata needs to be reported. Passed arguments are private to
131 * a CPU type.
132 */
Boyan Karatotev06236c92023-01-25 18:50:10 +0000133static __unused int errata_needs_reporting(spinlock_t *lock, uint32_t *reported)
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +0000134{
Antonio Nino Diaz9fe40fd2018-10-25 17:11:02 +0100135 bool report_now;
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +0000136
137 /* If already reported, return false. */
Antonio Nino Diaz9fe40fd2018-10-25 17:11:02 +0100138 if (*reported != 0U)
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +0000139 return 0;
140
141 /*
142 * Acquire lock. Determine whether status needs reporting, and then mark
143 * report status to true.
144 */
145 spin_lock(lock);
Antonio Nino Diaz9fe40fd2018-10-25 17:11:02 +0100146 report_now = (*reported == 0U);
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +0000147 if (report_now)
148 *reported = 1;
149 spin_unlock(lock);
150
151 return report_now;
152}
153
154/*
Boyan Karatotev06236c92023-01-25 18:50:10 +0000155 * Function to print errata status for the calling CPU (and others of the same
156 * type). Must be called only:
157 * - when MMU and data caches are enabled;
158 * - after cpu_ops have been initialized in per-CPU data.
159 */
160void print_errata_status(void)
161{
Boyan Karatotev06236c92023-01-25 18:50:10 +0000162#ifdef IMAGE_BL1
Ryan Everettd34d7fd2024-05-10 14:56:02 +0100163 generic_errata_report();
Boyan Karatotev06236c92023-01-25 18:50:10 +0000164#else /* IMAGE_BL1 */
Ryan Everettd34d7fd2024-05-10 14:56:02 +0100165 struct cpu_ops *cpu_ops = (void *) get_cpu_data(cpu_ops_ptr);
Boyan Karatotev06236c92023-01-25 18:50:10 +0000166
167 assert(cpu_ops != NULL);
168
Boyan Karatotev06236c92023-01-25 18:50:10 +0000169 if (errata_needs_reporting(cpu_ops->errata_lock, cpu_ops->errata_reported)) {
Ryan Everettd34d7fd2024-05-10 14:56:02 +0100170 generic_errata_report();
Boyan Karatotev06236c92023-01-25 18:50:10 +0000171 }
172#endif /* IMAGE_BL1 */
173}
Boyan Karatotev06236c92023-01-25 18:50:10 +0000174#endif /* !REPORT_ERRATA */