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