1 /* 2 * Copyright (c) 2017-2020, 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(__arch64__) && 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 */ 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 */ 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