110bcd761SJeenu Viswambharan /* 242d4d3baSArvind Ram Prakash * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved. 310bcd761SJeenu Viswambharan * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 510bcd761SJeenu Viswambharan */ 610bcd761SJeenu Viswambharan 710bcd761SJeenu Viswambharan /* Runtime firmware routines to report errata status for the current CPU. */ 810bcd761SJeenu Viswambharan 910bcd761SJeenu Viswambharan #include <assert.h> 1043534997SAntonio Nino Diaz #include <stdbool.h> 1109d40e0eSAntonio Nino Diaz 1209d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1309d40e0eSAntonio Nino Diaz #include <common/debug.h> 14*dd9fae1cSBoyan Karatotev #include <lib/cpus/cpu_ops.h> 156bb96fa6SBoyan Karatotev #include <lib/cpus/errata.h> 1609d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/cpu_data.h> 1709d40e0eSAntonio Nino Diaz #include <lib/spinlock.h> 1810bcd761SJeenu Viswambharan 1910bcd761SJeenu Viswambharan #ifdef IMAGE_BL1 2010bcd761SJeenu Viswambharan # define BL_STRING "BL1" 21402b3cf8SJulius Werner #elif defined(__aarch64__) && defined(IMAGE_BL31) 2210bcd761SJeenu Viswambharan # define BL_STRING "BL31" 23322e60a6SYann Gautier #elif !defined(__aarch64__) && defined(IMAGE_BL32) 2410bcd761SJeenu Viswambharan # define BL_STRING "BL32" 2542d4d3baSArvind Ram Prakash #elif defined(IMAGE_BL2) && RESET_TO_BL2 26b1d27b48SRoberto Vargas # define BL_STRING "BL2" 2710bcd761SJeenu Viswambharan #else 2810bcd761SJeenu Viswambharan # error This image should not be printing errata status 2910bcd761SJeenu Viswambharan #endif 3010bcd761SJeenu Viswambharan 3110bcd761SJeenu Viswambharan /* Errata format: BL stage, CPU, errata ID, message */ 32c0ca14d6SDimitris Papastamos #define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n" 3310bcd761SJeenu Viswambharan 34*dd9fae1cSBoyan Karatotev #if !REPORT_ERRATA 35*dd9fae1cSBoyan Karatotev void print_errata_status(void) {} 36*dd9fae1cSBoyan Karatotev #else /* !REPORT_ERRATA */ 3710bcd761SJeenu Viswambharan /* 3810bcd761SJeenu Viswambharan * Returns whether errata needs to be reported. Passed arguments are private to 3910bcd761SJeenu Viswambharan * a CPU type. 4010bcd761SJeenu Viswambharan */ 41*dd9fae1cSBoyan Karatotev static __unused int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) 4210bcd761SJeenu Viswambharan { 4343534997SAntonio Nino Diaz bool report_now; 4410bcd761SJeenu Viswambharan 4510bcd761SJeenu Viswambharan /* If already reported, return false. */ 4643534997SAntonio Nino Diaz if (*reported != 0U) 4710bcd761SJeenu Viswambharan return 0; 4810bcd761SJeenu Viswambharan 4910bcd761SJeenu Viswambharan /* 5010bcd761SJeenu Viswambharan * Acquire lock. Determine whether status needs reporting, and then mark 5110bcd761SJeenu Viswambharan * report status to true. 5210bcd761SJeenu Viswambharan */ 5310bcd761SJeenu Viswambharan spin_lock(lock); 5443534997SAntonio Nino Diaz report_now = (*reported == 0U); 5510bcd761SJeenu Viswambharan if (report_now) 5610bcd761SJeenu Viswambharan *reported = 1; 5710bcd761SJeenu Viswambharan spin_unlock(lock); 5810bcd761SJeenu Viswambharan 5910bcd761SJeenu Viswambharan return report_now; 6010bcd761SJeenu Viswambharan } 6110bcd761SJeenu Viswambharan 6210bcd761SJeenu Viswambharan /* 63*dd9fae1cSBoyan Karatotev * Function to print errata status for the calling CPU (and others of the same 64*dd9fae1cSBoyan Karatotev * type). Must be called only: 65*dd9fae1cSBoyan Karatotev * - when MMU and data caches are enabled; 66*dd9fae1cSBoyan Karatotev * - after cpu_ops have been initialized in per-CPU data. 67*dd9fae1cSBoyan Karatotev */ 68*dd9fae1cSBoyan Karatotev void print_errata_status(void) 69*dd9fae1cSBoyan Karatotev { 70*dd9fae1cSBoyan Karatotev struct cpu_ops *cpu_ops; 71*dd9fae1cSBoyan Karatotev #ifdef IMAGE_BL1 72*dd9fae1cSBoyan Karatotev /* 73*dd9fae1cSBoyan Karatotev * BL1 doesn't have per-CPU data. So retrieve the CPU operations 74*dd9fae1cSBoyan Karatotev * directly. 75*dd9fae1cSBoyan Karatotev */ 76*dd9fae1cSBoyan Karatotev cpu_ops = get_cpu_ops_ptr(); 77*dd9fae1cSBoyan Karatotev 78*dd9fae1cSBoyan Karatotev if (cpu_ops->errata_func != NULL) { 79*dd9fae1cSBoyan Karatotev cpu_ops->errata_func(); 80*dd9fae1cSBoyan Karatotev } 81*dd9fae1cSBoyan Karatotev #else /* IMAGE_BL1 */ 82*dd9fae1cSBoyan Karatotev cpu_ops = (void *) get_cpu_data(cpu_ops_ptr); 83*dd9fae1cSBoyan Karatotev 84*dd9fae1cSBoyan Karatotev assert(cpu_ops != NULL); 85*dd9fae1cSBoyan Karatotev 86*dd9fae1cSBoyan Karatotev if (cpu_ops->errata_func == NULL) { 87*dd9fae1cSBoyan Karatotev return; 88*dd9fae1cSBoyan Karatotev } 89*dd9fae1cSBoyan Karatotev 90*dd9fae1cSBoyan Karatotev if (errata_needs_reporting(cpu_ops->errata_lock, cpu_ops->errata_reported)) { 91*dd9fae1cSBoyan Karatotev cpu_ops->errata_func(); 92*dd9fae1cSBoyan Karatotev } 93*dd9fae1cSBoyan Karatotev #endif /* IMAGE_BL1 */ 94*dd9fae1cSBoyan Karatotev } 95*dd9fae1cSBoyan Karatotev 96*dd9fae1cSBoyan Karatotev /* 9710bcd761SJeenu Viswambharan * Print errata status message. 9810bcd761SJeenu Viswambharan * 9910bcd761SJeenu Viswambharan * Unknown: WARN 10010bcd761SJeenu Viswambharan * Missing: WARN 10110bcd761SJeenu Viswambharan * Applied: INFO 10210bcd761SJeenu Viswambharan * Not applied: VERBOSE 10310bcd761SJeenu Viswambharan */ 1046311f63dSVarun Wadekar void errata_print_msg(unsigned int status, const char *cpu, const char *id) 10510bcd761SJeenu Viswambharan { 10610bcd761SJeenu Viswambharan /* Errata status strings */ 10710bcd761SJeenu Viswambharan static const char *const errata_status_str[] = { 10810bcd761SJeenu Viswambharan [ERRATA_NOT_APPLIES] = "not applied", 10910bcd761SJeenu Viswambharan [ERRATA_APPLIES] = "applied", 11010bcd761SJeenu Viswambharan [ERRATA_MISSING] = "missing!" 11110bcd761SJeenu Viswambharan }; 11210bcd761SJeenu Viswambharan static const char *const __unused bl_str = BL_STRING; 11310bcd761SJeenu Viswambharan const char *msg __unused; 11410bcd761SJeenu Viswambharan 11510bcd761SJeenu Viswambharan 1160dd41951SDavid Cunado assert(status < ARRAY_SIZE(errata_status_str)); 11743534997SAntonio Nino Diaz assert(cpu != NULL); 11843534997SAntonio Nino Diaz assert(id != NULL); 11910bcd761SJeenu Viswambharan 12010bcd761SJeenu Viswambharan msg = errata_status_str[status]; 12110bcd761SJeenu Viswambharan 12210bcd761SJeenu Viswambharan switch (status) { 12310bcd761SJeenu Viswambharan case ERRATA_NOT_APPLIES: 12410bcd761SJeenu Viswambharan VERBOSE(ERRATA_FORMAT, bl_str, cpu, id, msg); 12510bcd761SJeenu Viswambharan break; 12610bcd761SJeenu Viswambharan 12710bcd761SJeenu Viswambharan case ERRATA_APPLIES: 12810bcd761SJeenu Viswambharan INFO(ERRATA_FORMAT, bl_str, cpu, id, msg); 12910bcd761SJeenu Viswambharan break; 13010bcd761SJeenu Viswambharan 13110bcd761SJeenu Viswambharan case ERRATA_MISSING: 13210bcd761SJeenu Viswambharan WARN(ERRATA_FORMAT, bl_str, cpu, id, msg); 13310bcd761SJeenu Viswambharan break; 13410bcd761SJeenu Viswambharan 13510bcd761SJeenu Viswambharan default: 13610bcd761SJeenu Viswambharan WARN(ERRATA_FORMAT, bl_str, cpu, id, "unknown"); 13710bcd761SJeenu Viswambharan break; 13810bcd761SJeenu Viswambharan } 13910bcd761SJeenu Viswambharan } 140*dd9fae1cSBoyan Karatotev #endif /* !REPORT_ERRATA */ 141