diff options
author | danh-arm <dan.handley@arm.com> | 2017-01-31 15:40:20 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-31 15:40:20 +0000 |
commit | bcc2bf097703c07aabe543681ee2676981831f76 (patch) | |
tree | 08f959e45d3c7441d747e0a854b4a069a0b82990 /lib | |
parent | 474d4eca1ca907968b04a4903d4adefaec4568e1 (diff) | |
parent | 10bcd761574a5aaa208041382399e05275011603 (diff) |
Merge pull request #821 from jeenu-arm/errata-printing
Errata printing infrastructure
Diffstat (limited to 'lib')
-rw-r--r-- | lib/cpus/aarch32/cpu_helpers.S | 85 | ||||
-rw-r--r-- | lib/cpus/aarch64/cortex_a53.S | 91 | ||||
-rw-r--r-- | lib/cpus/aarch64/cortex_a57.S | 226 | ||||
-rw-r--r-- | lib/cpus/aarch64/cpu_helpers.S | 111 | ||||
-rw-r--r-- | lib/cpus/errata_report.c | 122 | ||||
-rw-r--r-- | lib/psci/psci_lib.mk | 3 | ||||
-rw-r--r-- | lib/psci/psci_setup.c | 6 |
7 files changed, 485 insertions, 159 deletions
diff --git a/lib/cpus/aarch32/cpu_helpers.S b/lib/cpus/aarch32/cpu_helpers.S index d8cabfe5..c41978ed 100644 --- a/lib/cpus/aarch32/cpu_helpers.S +++ b/lib/cpus/aarch32/cpu_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -172,3 +172,86 @@ func get_cpu_ops_ptr error_exit: bx lr endfunc get_cpu_ops_ptr + +/* + * Extract CPU revision and variant, and combine them into a single numeric for + * easier comparison. + */ + .globl cpu_get_rev_var +func cpu_get_rev_var + ldcopr r1, MIDR + + /* + * Extract the variant[23:20] and revision[3:0] from r1 and pack it in + * r0[0:7] as variant[7:4] and revision[3:0]: + * + * First extract r1[23:16] to r0[7:0] and zero fill the rest. Then + * extract r1[3:0] into r0[3:0] retaining other bits. + */ + ubfx r0, r1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) + bfi r0, r1, #MIDR_REV_SHIFT, #MIDR_REV_BITS + bx lr +endfunc cpu_get_rev_var + +/* + * Compare the CPU's revision-variant (r0) with a given value (r1), for errata + * application purposes. If the revision-variant is less than or same as a given + * value, indicates that errata applies; otherwise not. + */ + .globl cpu_rev_var_ls +func cpu_rev_var_ls + cmp r0, r1 + movls r0, #ERRATA_APPLIES + movhi r0, #ERRATA_NOT_APPLIES + bx lr +endfunc cpu_rev_var_ls + +#if REPORT_ERRATA +/* + * void print_errata_status(void); + * + * Function to print errata status for CPUs of its class. Must be called only: + * + * - with MMU and data caches are enabled; + * - after cpu_ops have been initialized in per-CPU data. + */ + .globl print_errata_status +func print_errata_status + push {r4, lr} +#ifdef IMAGE_BL1 + /* + * BL1 doesn't have per-CPU data. So retrieve the CPU operations + * directly. + */ + bl get_cpu_ops_ptr + ldr r0, [r0, #CPU_ERRATA_FUNC] + cmp r0, #0 + blxne r0 +#else + /* + * Retrieve pointer to cpu_ops, and further, the errata printing + * function. If it's non-NULL, jump to the function in turn. + */ + bl _cpu_data + ldr r1, [r0, #CPU_DATA_CPU_OPS_PTR] + ldr r0, [r1, #CPU_ERRATA_FUNC] + cmp r0, #0 + beq 1f + + mov r4, r0 + + /* + * Load pointers to errata lock and printed flag. Call + * errata_needs_reporting to check whether this CPU needs to report + * errata status pertaining to its class. + */ + ldr r0, [r1, #CPU_ERRATA_LOCK] + ldr r1, [r1, #CPU_ERRATA_PRINTED] + bl errata_needs_reporting + cmp r0, #0 + blxne r4 +1: +#endif + pop {r4, pc} +endfunc print_errata_status +#endif diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S index 06be9ce6..1dd8a865 100644 --- a/lib/cpus/aarch64/cortex_a53.S +++ b/lib/cpus/aarch64/cortex_a53.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -35,6 +35,11 @@ #include <debug.h> #include <plat_macros.S> +#if A53_DISABLE_NON_TEMPORAL_HINT +#undef ERRATA_A53_836870 +#define ERRATA_A53_836870 1 +#endif + /* --------------------------------------------- * Disable L1 data cache and unified L2 cache * --------------------------------------------- @@ -65,28 +70,29 @@ endfunc cortex_a53_disable_smp * This applies only to revision <= r0p2 of Cortex A53. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * -------------------------------------------------- */ func errata_a53_826319_wa /* * Compare x0 against revision r0p2 */ - cmp x0, #2 - b.ls apply_826319 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_826319: + mov x17, x30 + bl check_errata_826319 + cbz x0, 1f mrs x1, L2ACTLR_EL1 bic x1, x1, #L2ACTLR_ENABLE_UNIQUECLEAN orr x1, x1, #L2ACTLR_DISABLE_CLEAN_PUSH msr L2ACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a53_826319_wa +func check_errata_826319 + mov x1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_826319 + /* --------------------------------------------------------------------- * Disable the cache non-temporal hint. * @@ -101,53 +107,46 @@ endfunc errata_a53_826319_wa * * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * --------------------------------------------------------------------- */ func a53_disable_non_temporal_hint /* * Compare x0 against revision r0p3 */ - cmp x0, #3 - b.ls disable_hint -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -disable_hint: + mov x17, x30 + bl check_errata_disable_non_temporal_hint + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_DTAH msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc a53_disable_non_temporal_hint +func check_errata_disable_non_temporal_hint + mov x1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_disable_non_temporal_hint + /* ------------------------------------------------- * The CPU Ops reset function for Cortex-A53. - * Clobbers: x0-x5, x15, x19, x30 + * Shall clobber: x0-x19 * ------------------------------------------------- */ func cortex_a53_reset_func mov x19, x30 - mrs x0, midr_el1 + bl cpu_get_rev_var + mov x18, x0 - /* - * Extract the variant[20:23] and revision[0:3] from x0 - * and pack it in x15[0:7] as variant[4:7] and revision[0:3]. - * First extract x0[16:23] to x15[0:7] and zero fill the rest. - * Then extract x0[0:3] into x15[0:3] retaining other bits. - */ - ubfx x15, x0, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), \ - #(MIDR_REV_BITS + MIDR_VAR_BITS) - bfxil x15, x0, #MIDR_REV_SHIFT, #MIDR_REV_BITS #if ERRATA_A53_826319 - mov x0, x15 + mov x0, x18 bl errata_a53_826319_wa #endif -#if ERRATA_A53_836870 || A53_DISABLE_NON_TEMPORAL_HINT - mov x0, x15 +#if ERRATA_A53_836870 + mov x0, x18 bl a53_disable_non_temporal_hint #endif @@ -223,6 +222,28 @@ func cortex_a53_cluster_pwr_dwn b cortex_a53_disable_smp endfunc cortex_a53_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A53. Must follow AAPCS. + */ +func cortex_a53_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A53_826319, cortex_a53, 826319 + report_errata ERRATA_A53_836870, cortex_a53, disable_non_temporal_hint + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a53_errata_report +#endif + /* --------------------------------------------- * This function provides cortex_a53 specific * register information for crash reporting. diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S index e531b1e3..ffdc9309 100644 --- a/lib/cpus/aarch64/cortex_a57.S +++ b/lib/cpus/aarch64/cortex_a57.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -92,52 +92,55 @@ endfunc cortex_a57_disable_ext_debug * This applies only to revision r0p0 of Cortex A57. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * -------------------------------------------------- */ func errata_a57_806969_wa /* * Compare x0 against revision r0p0 */ - cbz x0, apply_806969 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_806969: + mov x17, x30 + bl check_errata_806969 + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_NO_ALLOC_WBWA msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a57_806969_wa +func check_errata_806969 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_806969 /* --------------------------------------------------- * Errata Workaround for Cortex A57 Errata #813420. * This applies only to revision r0p0 of Cortex A57. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * --------------------------------------------------- */ func errata_a57_813420_wa /* * Compare x0 against revision r0p0 */ - cbz x0, apply_813420 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_813420: + mov x17, x30 + bl check_errata_813420 + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_DCC_AS_DCCI msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a57_813420_wa +func check_errata_813420 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_813420 + /* -------------------------------------------------------------------- * Disable the over-read from the LDNP instruction. * @@ -146,99 +149,97 @@ endfunc errata_a57_813420_wa * * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5, x30 + * Shall clobber: x0-x17 * --------------------------------------------------------------------- */ func a57_disable_ldnp_overread /* * Compare x0 against revision r1p2 */ - cmp x0, #0x12 - b.ls disable_hint -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -disable_hint: + mov x17, x30 + bl check_errata_disable_ldnp_overread + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_DIS_OVERREAD msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc a57_disable_ldnp_overread +func check_errata_disable_ldnp_overread + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_disable_ldnp_overread + /* --------------------------------------------------- * Errata Workaround for Cortex A57 Errata #826974. * This applies only to revision <= r1p1 of Cortex A57. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * --------------------------------------------------- */ func errata_a57_826974_wa /* * Compare x0 against revision r1p1 */ - cmp x0, #0x11 - b.ls apply_826974 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_826974: + mov x17, x30 + bl check_errata_826974 + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_DIS_LOAD_PASS_DMB msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a57_826974_wa +func check_errata_826974 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826974 + /* --------------------------------------------------- * Errata Workaround for Cortex A57 Errata #826977. * This applies only to revision <= r1p1 of Cortex A57. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * --------------------------------------------------- */ func errata_a57_826977_wa /* * Compare x0 against revision r1p1 */ - cmp x0, #0x11 - b.ls apply_826977 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_826977: + mov x17, x30 + bl check_errata_826977 + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_GRE_NGRE_AS_NGNRE msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a57_826977_wa +func check_errata_826977 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826977 + /* --------------------------------------------------- * Errata Workaround for Cortex A57 Errata #828024. * This applies only to revision <= r1p1 of Cortex A57. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * --------------------------------------------------- */ func errata_a57_828024_wa /* * Compare x0 against revision r1p1 */ - cmp x0, #0x11 - b.ls apply_828024 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_828024: + mov x17, x30 + bl check_errata_828024 + cbz x0, 1f mrs x1, CPUACTLR_EL1 /* * Setting the relevant bits in CPUACTLR_EL1 has to be done in 2 @@ -248,116 +249,116 @@ apply_828024: orr x1, x1, #CPUACTLR_NO_ALLOC_WBWA orr x1, x1, #(CPUACTLR_DIS_L1_STREAMING | CPUACTLR_DIS_STREAMING) msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a57_828024_wa +func check_errata_828024 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_828024 + /* --------------------------------------------------- * Errata Workaround for Cortex A57 Errata #829520. * This applies only to revision <= r1p2 of Cortex A57. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * --------------------------------------------------- */ func errata_a57_829520_wa /* * Compare x0 against revision r1p2 */ - cmp x0, #0x12 - b.ls apply_829520 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_829520: + mov x17, x30 + bl check_errata_829520 + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_DIS_INDIRECT_PREDICTOR msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a57_829520_wa +func check_errata_829520 + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_829520 + /* --------------------------------------------------- * Errata Workaround for Cortex A57 Errata #833471. * This applies only to revision <= r1p2 of Cortex A57. * Inputs: * x0: variant[4:7] and revision[0:3] of current cpu. - * Clobbers : x0 - x5 + * Shall clobber: x0-x17 * --------------------------------------------------- */ func errata_a57_833471_wa /* * Compare x0 against revision r1p2 */ - cmp x0, #0x12 - b.ls apply_833471 -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - b print_revision_warning -#else - ret -#endif -apply_833471: + mov x17, x30 + bl check_errata_833471 + cbz x0, 1f mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_FORCE_FPSCR_FLUSH msr CPUACTLR_EL1, x1 - ret +1: + ret x17 endfunc errata_a57_833471_wa +func check_errata_833471 + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_833471 + /* ------------------------------------------------- * The CPU Ops reset function for Cortex-A57. - * Clobbers: x0-x5, x15, x19, x30 + * Shall clobber: x0-x19 * ------------------------------------------------- */ func cortex_a57_reset_func mov x19, x30 - mrs x0, midr_el1 - - /* - * Extract the variant[20:23] and revision[0:3] from x0 - * and pack it in x15[0:7] as variant[4:7] and revision[0:3]. - * First extract x0[16:23] to x15[0:7] and zero fill the rest. - * Then extract x0[0:3] into x15[0:3] retaining other bits. - */ - ubfx x15, x0, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) - bfxil x15, x0, #MIDR_REV_SHIFT, #MIDR_REV_BITS + bl cpu_get_rev_var + mov x18, x0 #if ERRATA_A57_806969 - mov x0, x15 + mov x0, x18 bl errata_a57_806969_wa #endif #if ERRATA_A57_813420 - mov x0, x15 + mov x0, x18 bl errata_a57_813420_wa #endif #if A57_DISABLE_NON_TEMPORAL_HINT - mov x0, x15 + mov x0, x18 bl a57_disable_ldnp_overread #endif #if ERRATA_A57_826974 - mov x0, x15 + mov x0, x18 bl errata_a57_826974_wa #endif #if ERRATA_A57_826977 - mov x0, x15 + mov x0, x18 bl errata_a57_826977_wa #endif #if ERRATA_A57_828024 - mov x0, x15 + mov x0, x18 bl errata_a57_828024_wa #endif #if ERRATA_A57_829520 - mov x0, x15 + mov x0, x18 bl errata_a57_829520_wa #endif #if ERRATA_A57_833471 - mov x0, x15 + mov x0, x18 bl errata_a57_833471_wa #endif @@ -466,6 +467,35 @@ func cortex_a57_cluster_pwr_dwn b cortex_a57_disable_ext_debug endfunc cortex_a57_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A57. Must follow AAPCS. + */ +func cortex_a57_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A57_806969, cortex_a57, 806969 + report_errata ERRATA_A57_813420, cortex_a57, 813420 + report_errata A57_DISABLE_NON_TEMPORAL_HINT, cortex_a57, \ + disable_ldnp_overread + report_errata ERRATA_A57_826974, cortex_a57, 826974 + report_errata ERRATA_A57_826977, cortex_a57, 826977 + report_errata ERRATA_A57_828024, cortex_a57, 828024 + report_errata ERRATA_A57_829520, cortex_a57, 829520 + report_errata ERRATA_A57_833471, cortex_a57, 833471 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a57_errata_report +#endif + /* --------------------------------------------- * This function provides cortex_a57 specific * register information for crash reporting. diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S index 7365d35e..6a3669de 100644 --- a/lib/cpus/aarch64/cpu_helpers.S +++ b/lib/cpus/aarch64/cpu_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -36,6 +36,7 @@ #endif #include <cpu_macros.S> #include <debug.h> +#include <errata_report.h> /* Reset fn is needed in BL at reset vector */ #if defined(IMAGE_BL1) || defined(IMAGE_BL31) @@ -199,30 +200,94 @@ error_exit: ret endfunc get_cpu_ops_ptr -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -.section .rodata.rev_verbose_str, "aS" -rev_verbose_str: - .asciz "VERBOSE: Skipping CPU specific reset operation for non-matching CPU revision number.\n" +/* + * Extract CPU revision and variant, and combine them into a single numeric for + * easier comparison. + */ + .globl cpu_get_rev_var +func cpu_get_rev_var + mrs x1, midr_el1 /* - * This function prints the above warning message to the crash console. - * It should be called when a CPU specific operation is enabled in the - * build but doesn't apply to this CPU revision/part number. + * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them + * as variant[7:4] and revision[3:0] of x0. * - * Clobber: x30, x0 - x5 + * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then + * extract x1[3:0] into x0[3:0] retaining other bits. */ - .globl print_revision_warning -func print_revision_warning - mov x5, x30 - /* Ensure the console is initialized */ - bl plat_crash_console_init - /* Check if the console is initialized */ - cbz x0, 1f - /* The console is initialized */ - adr x4, rev_verbose_str - bl asm_print_str -1: - ret x5 -endfunc print_revision_warning -#endif + ubfx x0, x1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) + bfxil x0, x1, #MIDR_REV_SHIFT, #MIDR_REV_BITS + ret +endfunc cpu_get_rev_var +/* + * Compare the CPU's revision-variant (x0) with a given value (x1), for errata + * application purposes. If the revision-variant is less than or same as a given + * value, indicates that errata applies; otherwise not. + */ + .globl cpu_rev_var_ls +func cpu_rev_var_ls + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x0, x2, x3, ls + ret +endfunc cpu_rev_var_ls + +#if REPORT_ERRATA +/* + * void print_errata_status(void); + * + * Function to print errata status for CPUs of its class. Must be called only: + * + * - with MMU and data caches are enabled; + * - after cpu_ops have been initialized in per-CPU data. + */ + .globl print_errata_status +func print_errata_status +#ifdef IMAGE_BL1 + /* + * BL1 doesn't have per-CPU data. So retrieve the CPU operations + * directly. + */ + stp xzr, x30, [sp, #-16]! + bl get_cpu_ops_ptr + ldp xzr, x30, [sp], #16 + ldr x1, [x0, #CPU_ERRATA_FUNC] + cbnz x1, .Lprint +#else + /* + * Retrieve pointer to cpu_ops from per-CPU data, and further, the + * errata printing function. If it's non-NULL, jump to the function in + * turn. + */ + mrs x0, tpidr_el3 + ldr x1, [x0, #CPU_DATA_CPU_OPS_PTR] + ldr x0, [x1, #CPU_ERRATA_FUNC] + cbz x0, .Lnoprint + + /* + * Printing errata status requires atomically testing the printed flag. + */ + stp x8, x30, [sp, #-16]! + mov x8, x0 + + /* + * Load pointers to errata lock and printed flag. Call + * errata_needs_reporting to check whether this CPU needs to report + * errata status pertaining to its class. + */ + ldr x0, [x1, #CPU_ERRATA_LOCK] + ldr x1, [x1, #CPU_ERRATA_PRINTED] + bl errata_needs_reporting + mov x1, x8 + ldp x8, x30, [sp], #16 + cbnz x0, .Lprint +#endif +.Lnoprint: + ret +.Lprint: + /* Jump to errata reporting function for this CPU */ + br x1 +endfunc print_errata_status +#endif diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c new file mode 100644 index 00000000..29b26c2e --- /dev/null +++ b/lib/cpus/errata_report.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Runtime firmware routines to report errata status for the current CPU. */ + +#include <arch_helpers.h> +#include <assert.h> +#include <cpu_data.h> +#include <debug.h> +#include <errata_report.h> +#include <spinlock.h> +#include <utils.h> + +#ifdef IMAGE_BL1 +# define BL_STRING "BL1" +#elif defined(AARCH64) && defined(IMAGE_BL31) +# define BL_STRING "BL31" +#elif defined(AARCH32) && defined(IMAGE_BL32) +# define BL_STRING "BL32" +#else +# error This image should not be printing errata status +#endif + +/* Errata format: BL stage, CPU, errata ID, message */ +#define ERRATA_FORMAT "%s: %s: errata workaround for %s was %s\n" + +/* + * Returns whether errata needs to be reported. Passed arguments are private to + * a CPU type. + */ +int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) +{ + int report_now; + + /* If already reported, return false. */ + if (*reported) + return 0; + + /* + * Acquire lock. Determine whether status needs reporting, and then mark + * report status to true. + */ + spin_lock(lock); + report_now = !(*reported); + if (report_now) + *reported = 1; + spin_unlock(lock); + + return report_now; +} + +/* + * Print errata status message. + * + * Unknown: WARN + * Missing: WARN + * Applied: INFO + * Not applied: VERBOSE + */ +void errata_print_msg(int status, const char *cpu, const char *id) +{ + /* Errata status strings */ + static const char *const errata_status_str[] = { + [ERRATA_NOT_APPLIES] = "not applied", + [ERRATA_APPLIES] = "applied", + [ERRATA_MISSING] = "missing!" + }; + static const char *const __unused bl_str = BL_STRING; + const char *msg __unused; + + + assert(status >= 0 && status < ARRAY_SIZE(errata_status_str)); + assert(cpu); + assert(id); + + msg = errata_status_str[status]; + + switch (status) { + case ERRATA_NOT_APPLIES: + VERBOSE(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + case ERRATA_APPLIES: + INFO(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + case ERRATA_MISSING: + WARN(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + default: + WARN(ERRATA_FORMAT, bl_str, cpu, id, "unknown"); + break; + } +} diff --git a/lib/psci/psci_lib.mk b/lib/psci/psci_lib.mk index 8daa8318..82736cdd 100644 --- a/lib/psci/psci_lib.mk +++ b/lib/psci/psci_lib.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -32,6 +32,7 @@ PSCI_LIB_SOURCES := lib/el3_runtime/cpu_data_array.c \ lib/el3_runtime/${ARCH}/cpu_data.S \ lib/el3_runtime/${ARCH}/context_mgmt.c \ lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c \ lib/locks/exclusive/${ARCH}/spinlock.S \ lib/psci/psci_off.c \ lib/psci/psci_on.c \ diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c index cb8b77db..7327b92e 100644 --- a/lib/psci/psci_setup.c +++ b/lib/psci/psci_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -34,6 +34,7 @@ #include <bl_common.h> #include <context.h> #include <context_mgmt.h> +#include <errata_report.h> #include <platform.h> #include <stddef.h> #include "psci_private.h" @@ -287,6 +288,9 @@ void psci_arch_setup(void) /* Initialize the cpu_ops pointer. */ init_cpu_ops(); + + /* Having initialized cpu_ops, we can now print errata status */ + print_errata_status(); } /****************************************************************************** |