Marc, Can you please ack this to say that you are now happy with it after your comments on version 1, so we can move forward and have Greg merge it. Thanks. On Wed, Nov 07, 2018 at 11:43:47AM -0500, David Long wrote: > From: Russell King <rmk+kernel@xxxxxxxxxxxxxxx> > > Commit 10115105cb3aa17b5da1cb726ae8dd5f6854bd93 upstream. > Commit 6282e916f774e37845c65d1eae9f8c649004f033 upstream. > > Add firmware based hardening for cores that require more complex > handling in firmware. > > Signed-off-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxx> > Boot-tested-by: Tony Lindgren <tony@xxxxxxxxxxx> > Reviewed-by: Tony Lindgren <tony@xxxxxxxxxxx> > Reviewed-by: Marc Zyngier <marc.zyngier@xxxxxxx> > Signed-off-by: David A. Long <dave.long@xxxxxxxxxx> > --- > arch/arm/mm/proc-v7-bugs.c | 60 ++++++++++++++++++++++++++++++++++++++ > arch/arm/mm/proc-v7.S | 21 +++++++++++++ > 2 files changed, 81 insertions(+) > > diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c > index 85a2e3d6263c..da25a38e1897 100644 > --- a/arch/arm/mm/proc-v7-bugs.c > +++ b/arch/arm/mm/proc-v7-bugs.c > @@ -1,14 +1,20 @@ > // SPDX-License-Identifier: GPL-2.0 > +#include <linux/arm-smccc.h> > #include <linux/kernel.h> > +#include <linux/psci.h> > #include <linux/smp.h> > > #include <asm/cp15.h> > #include <asm/cputype.h> > +#include <asm/proc-fns.h> > #include <asm/system_misc.h> > > #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR > DEFINE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn); > > +extern void cpu_v7_smc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); > +extern void cpu_v7_hvc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); > + > static void harden_branch_predictor_bpiall(void) > { > write_sysreg(0, BPIALL); > @@ -19,6 +25,16 @@ static void harden_branch_predictor_iciallu(void) > write_sysreg(0, ICIALLU); > } > > +static void __maybe_unused call_smc_arch_workaround_1(void) > +{ > + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); > +} > + > +static void __maybe_unused call_hvc_arch_workaround_1(void) > +{ > + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); > +} > + > static void cpu_v7_spectre_init(void) > { > const char *spectre_v2_method = NULL; > @@ -45,7 +61,51 @@ static void cpu_v7_spectre_init(void) > harden_branch_predictor_iciallu; > spectre_v2_method = "ICIALLU"; > break; > + > +#ifdef CONFIG_ARM_PSCI > + default: > + /* Other ARM CPUs require no workaround */ > + if (read_cpuid_implementor() == ARM_CPU_IMP_ARM) > + break; > + /* fallthrough */ > + /* Cortex A57/A72 require firmware workaround */ > + case ARM_CPU_PART_CORTEX_A57: > + case ARM_CPU_PART_CORTEX_A72: { > + struct arm_smccc_res res; > + > + if (psci_ops.smccc_version == SMCCC_VERSION_1_0) > + break; > + > + switch (psci_ops.conduit) { > + case PSCI_CONDUIT_HVC: > + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, > + ARM_SMCCC_ARCH_WORKAROUND_1, &res); > + if ((int)res.a0 != 0) > + break; > + per_cpu(harden_branch_predictor_fn, cpu) = > + call_hvc_arch_workaround_1; > + processor.switch_mm = cpu_v7_hvc_switch_mm; > + spectre_v2_method = "hypervisor"; > + break; > + > + case PSCI_CONDUIT_SMC: > + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, > + ARM_SMCCC_ARCH_WORKAROUND_1, &res); > + if ((int)res.a0 != 0) > + break; > + per_cpu(harden_branch_predictor_fn, cpu) = > + call_smc_arch_workaround_1; > + processor.switch_mm = cpu_v7_smc_switch_mm; > + spectre_v2_method = "firmware"; > + break; > + > + default: > + break; > + } > } > +#endif > + } > + > if (spectre_v2_method) > pr_info("CPU%u: Spectre v2: using %s workaround\n", > smp_processor_id(), spectre_v2_method); > diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S > index 2d2e5ae85816..850c22bca19c 100644 > --- a/arch/arm/mm/proc-v7.S > +++ b/arch/arm/mm/proc-v7.S > @@ -9,6 +9,7 @@ > * > * This is the "shell" of the ARMv7 processor support. > */ > +#include <linux/arm-smccc.h> > #include <linux/init.h> > #include <linux/linkage.h> > #include <asm/assembler.h> > @@ -88,6 +89,26 @@ ENTRY(cpu_v7_dcache_clean_area) > ret lr > ENDPROC(cpu_v7_dcache_clean_area) > > +#ifdef CONFIG_ARM_PSCI > + .arch_extension sec > +ENTRY(cpu_v7_smc_switch_mm) > + stmfd sp!, {r0 - r3} > + movw r0, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1 > + movt r0, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1 > + smc #0 > + ldmfd sp!, {r0 - r3} > + b cpu_v7_switch_mm > +ENDPROC(cpu_v7_smc_switch_mm) > + .arch_extension virt > +ENTRY(cpu_v7_hvc_switch_mm) > + stmfd sp!, {r0 - r3} > + movw r0, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1 > + movt r0, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1 > + hvc #0 > + ldmfd sp!, {r0 - r3} > + b cpu_v7_switch_mm > +ENDPROC(cpu_v7_hvc_switch_mm) > +#endif > ENTRY(cpu_v7_iciallu_switch_mm) > mov r3, #0 > mcr p15, 0, r3, c7, c5, 0 @ ICIALLU > -- > 2.17.1 > -- RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up According to speedtest.net: 11.9Mbps down 500kbps up