summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2017-01-31 15:40:20 +0000
committerGitHub <noreply@github.com>2017-01-31 15:40:20 +0000
commitbcc2bf097703c07aabe543681ee2676981831f76 (patch)
tree08f959e45d3c7441d747e0a854b4a069a0b82990 /lib
parent474d4eca1ca907968b04a4903d4adefaec4568e1 (diff)
parent10bcd761574a5aaa208041382399e05275011603 (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.S85
-rw-r--r--lib/cpus/aarch64/cortex_a53.S91
-rw-r--r--lib/cpus/aarch64/cortex_a57.S226
-rw-r--r--lib/cpus/aarch64/cpu_helpers.S111
-rw-r--r--lib/cpus/errata_report.c122
-rw-r--r--lib/psci/psci_lib.mk3
-rw-r--r--lib/psci/psci_setup.c6
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();
}
/******************************************************************************