diff --git a/docs/cpu-errata-workarounds.md b/docs/cpu-errata-workarounds.md index 8285d89..09f7c72 100644 --- a/docs/cpu-errata-workarounds.md +++ b/docs/cpu-errata-workarounds.md @@ -5,7 +5,7 @@ errata workarounds that are applied to each CPU by the reset handler. The errata details can be found in the CPU specifc errata documents published by ARM. The errata workarounds are implemented for a particular revision -or a set of processor revisions. This check is done in the debug build. +or a set of processor revisions. This is checked by reset handler at runtime. Each errata workaround is identified by its `ID` as specified in the processor's errata notice document. The format of the define used to enable/disable the errata is `ERRATA__` where the `Processor name` @@ -13,7 +13,10 @@ All workarounds are disabled by default. The platform is reponsible for enabling these workarounds according to its requirement by defining the -errata workaround build flags in the platform specific makefile. +errata workaround build flags in the platform specific makefile. In case +these workarounds are enabled for the wrong CPU revision then the errata +workaround is not applied. In the DEBUG build, this is indicated by +printing a warning to the crash console. In the current implementation, a platform which has more than 1 variant with different revisions of a processor has no runtime mechanism available @@ -22,12 +25,12 @@ The value of the build flags are 0 by default, that is, disabled. Any other value will enable it. -For Cortex A57, following errata build flags are defined : +For Cortex-A57, following errata build flags are defined : -* `ERRATA_A57_806969`: This applies errata 806969 workaround to cortex a57 +* `ERRATA_A57_806969`: This applies errata 806969 workaround to Cortex-A57 CPU. This needs to be enabled only for revision r0p0 of the CPU. -* `ERRATA_A57_813420`: This applies errata 813420 workaround to cortex a57 +* `ERRATA_A57_813420`: This applies errata 813420 workaround to Cortex-A57 CPU. This needs to be enabled only for revision r0p0 of the CPU. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index e5b2bf8..476c9c5 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -38,7 +38,9 @@ #define MIDR_IMPL_MASK 0xff #define MIDR_IMPL_SHIFT 0x18 #define MIDR_VAR_SHIFT 20 +#define MIDR_VAR_BITS 4 #define MIDR_REV_SHIFT 0 +#define MIDR_REV_BITS 4 #define MIDR_PN_MASK 0xfff #define MIDR_PN_SHIFT 0x4 diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S index 3e55297..e777497 100644 --- a/lib/cpus/aarch64/cortex_a57.S +++ b/lib/cpus/aarch64/cortex_a57.S @@ -81,33 +81,79 @@ dsb sy ret -func cortex_a57_reset_func -#if ERRATA_A57_806969 || ERRATA_A57_813420 - /* --------------------------------------------- - * Ensure that the following errata is only - * applied on r0p0 parts. - * --------------------------------------------- + /* -------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #806969. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * -------------------------------------------------- */ -#if ASM_ASSERTION - mrs x0, midr_el1 - ubfx x1, x0, #MIDR_VAR_SHIFT, #4 - ubfx x2, x0, #MIDR_REV_SHIFT, #4 - orr x0, x1, x2 - cmp x0, #0 - ASM_ASSERT(eq) +func errata_a57_806969_wa + /* + * Compare x0 against revision r0p0 + */ + cbz x0, apply_806969 +#if DEBUG + b print_revision_warning +#else + ret #endif - mov x1, xzr -#if ERRATA_A57_806969 +apply_806969: + mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_NO_ALLOC_WBWA + msr CPUACTLR_EL1, x1 + ret + + + /* --------------------------------------------------- + * 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. + * --------------------------------------------------- + */ +func errata_a57_813420_wa + /* + * Compare x0 against revision r0p0 + */ + cbz x0, apply_813420 +#if DEBUG + b print_revision_warning +#else + ret #endif -#if ERRATA_A57_813420 +apply_813420: + mrs x1, CPUACTLR_EL1 orr x1, x1, #CPUACTLR_DCC_AS_DCCI -#endif - mrs x0, CPUACTLR_EL1 - orr x0, x0, x1 - msr CPUACTLR_EL1, x0 + msr CPUACTLR_EL1, x1 + ret + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A57. + * ------------------------------------------------- + */ +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 x20[0:7] as variant[4:7] and revision[0:3]. + * First extract x0[16:23] to x20[0:7] and zero fill the rest. + * Then extract x0[0:3] into x20[0:3] retaining other bits. + */ + ubfx x20, x0, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) + bfxil x20, x0, #MIDR_REV_SHIFT, #MIDR_REV_BITS + +#if ERRATA_A57_806969 + mov x0, x20 + bl errata_a57_806969_wa #endif +#if ERRATA_A57_813420 + mov x0, x20 + bl errata_a57_813420_wa +#endif /* --------------------------------------------- * As a bare minimum enable the SMP bit. * --------------------------------------------- @@ -116,8 +162,12 @@ orr x0, x0, #CPUECTLR_SMP_BIT msr CPUECTLR_EL1, x0 isb - ret + ret x19 + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A57. + * ---------------------------------------------------- + */ func cortex_a57_core_pwr_dwn mov x18, x30 @@ -153,6 +203,10 @@ mov x30, x18 b cortex_a57_disable_ext_debug + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A57. + * ------------------------------------------------------- + */ func cortex_a57_cluster_pwr_dwn mov x18, x30 diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S index 46584b3..f053d44 100644 --- a/lib/cpus/aarch64/cpu_helpers.S +++ b/lib/cpus/aarch64/cpu_helpers.S @@ -45,7 +45,7 @@ */ .globl reset_handler func reset_handler - mov x10, x30 + mov x19, x30 bl plat_reset_handler @@ -58,10 +58,11 @@ /* Get the cpu_ops reset handler */ ldr x2, [x0, #CPU_RESET_FUNC] + mov x30, x19 cbz x2, 1f - blr x2 + br x2 1: - ret x10 + ret #endif /* IMAGE_BL1 || (IMAGE_BL31 && RESET_TO_BL31) */ @@ -191,3 +192,29 @@ sub x0, x4, #(CPU_OPS_SIZE + CPU_MIDR) error_exit: ret + +#if DEBUG + /* + * This function prints a warning message to the crash console + * if the CPU revision/part number does not match the errata + * workaround enabled in the build. + * Clobber: x30, x0 - x5 + */ +.section .rodata.rev_warn_str, "aS" +rev_warn_str: + .asciz "Warning: Skipping Errata workaround for non matching CPU revision number.\n" + + .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_warn_str + bl asm_print_str +1: + ret x5 +#endif +