[PATCH v3 03/16] arm64: errata: Add workaround for TSB flush failures
Will Deacon
will at kernel.org
Mon Oct 11 03:20:38 PDT 2021
On Fri, Oct 08, 2021 at 07:28:53PM +0100, Suzuki K Poulose wrote:
> Arm Neoverse-N2 (#2067961) and Cortex-A710 (#2054223) suffers
> from errata, where a TSB (trace synchronization barrier)
> fails to flush the trace data completely, when executed from
> a trace prohibited region. In Linux we always execute it
> after we have moved the PE to trace prohibited region. So,
> we can apply the workaround every time a TSB is executed.
>
> The work around is to issue two TSB consecutively.
>
> NOTE: This errata is defined as LOCAL_CPU_ERRATUM, implying
> that a late CPU could be blocked from booting if it is the
> first CPU that requires the workaround. This is because we
> do not allow setting a cpu_hwcaps after the SMP boot. The
> other alternative is to use "this_cpu_has_cap()" instead
> of the faster system wide check, which may be a bit of an
> overhead, given we may have to do this in nvhe KVM host
> before a guest entry.
>
> Cc: Will Deacon <will at kernel.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
> Cc: Mike Leach <mike.leach at linaro.org>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> Cc: Marc Zyngier <maz at kernel.org>
> Acked-by: Catalin Marinas <catalin.marinas at arm.com>
> Reviewed-by: Mathieu Poirier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
> Changes since v2:
> - Split the Kconfig/erratum list update to a later patch
> I have retained the tags, as there were no changes to
> the patches as such, except for split and move
> ---
> arch/arm64/include/asm/barrier.h | 16 +++++++++++++++-
> arch/arm64/kernel/cpu_errata.c | 19 +++++++++++++++++++
> arch/arm64/tools/cpucaps | 1 +
> 3 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
> index 451e11e5fd23..1c5a00598458 100644
> --- a/arch/arm64/include/asm/barrier.h
> +++ b/arch/arm64/include/asm/barrier.h
> @@ -23,7 +23,7 @@
> #define dsb(opt) asm volatile("dsb " #opt : : : "memory")
>
> #define psb_csync() asm volatile("hint #17" : : : "memory")
> -#define tsb_csync() asm volatile("hint #18" : : : "memory")
> +#define __tsb_csync() asm volatile("hint #18" : : : "memory")
> #define csdb() asm volatile("hint #20" : : : "memory")
>
> #ifdef CONFIG_ARM64_PSEUDO_NMI
> @@ -46,6 +46,20 @@
> #define dma_rmb() dmb(oshld)
> #define dma_wmb() dmb(oshst)
>
> +
> +#define tsb_csync() \
> + do { \
> + /* \
> + * CPUs affected by Arm Erratum 2054223 or 2067961 needs \
> + * another TSB to ensure the trace is flushed. The barriers \
> + * don't have to be strictly back to back, as long as the \
> + * CPU is in trace prohibited state. \
> + */ \
> + if (cpus_have_final_cap(ARM64_WORKAROUND_TSB_FLUSH_FAILURE)) \
> + __tsb_csync(); \
> + __tsb_csync(); \
> + } while (0)
> +
> /*
> * Generate a mask for array_index__nospec() that is ~0UL when 0 <= idx < sz
> * and 0 otherwise.
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index ccd757373f36..bdbeac75ead6 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -352,6 +352,18 @@ static const struct midr_range trbe_overwrite_fill_mode_cpus[] = {
> };
> #endif /* CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE */
>
> +#ifdef CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE
> +static const struct midr_range tsb_flush_fail_cpus[] = {
> +#ifdef CONFIG_ARM64_ERRATUM_2067961
> + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
> +#endif
> +#ifdef CONFIG_ARM64_ERRATUM_2054223
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
> +#endif
> + {},
> +};
> +#endif /* CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE */
> +
> const struct arm64_cpu_capabilities arm64_errata[] = {
> #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
> {
> @@ -558,6 +570,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
> .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
> CAP_MIDR_RANGE_LIST(trbe_overwrite_fill_mode_cpus),
> },
> +#endif
> +#ifdef CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILRE
:/
So I think maybe we should revisit my suggestion to put the Kconfig stuff
at the end and instead let's keep all the arm64 changes together so the
arm64 parts can be built in isolation. Make 'em depend on COMPILE_TEST or
something, then remove that at the end?
Will
More information about the linux-arm-kernel
mailing list