ARM Spectre variant 2 fixes
Subsystems (2)
Russell King - ARM Linux
maintainerv2 cover ARM Spectre variant 2 fixes
This is the second posting - the original cover note is below. Comments from previous series addresesd:
- Drop R7 and R8 changes.
- Remove "PSCI" from the hypervisor version of the workaround.
arch/arm/include/asm/bugs.h | 6 +- arch/arm/include/asm/cp15.h | 3 + arch/arm/include/asm/cputype.h | 5 ++ arch/arm/include/asm/kvm_asm.h | 2 - arch/arm/include/asm/kvm_host.h | 14 +++- arch/arm/include/asm/kvm_mmu.h | 23 +++++- arch/arm/include/asm/proc-fns.h | 4 + arch/arm/include/asm/system_misc.h | 8 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/bugs.c | 18 +++++ arch/arm/kernel/smp.c | 4 + arch/arm/kernel/suspend.c | 2 + arch/arm/kvm/hyp/hyp-entry.S | 108 +++++++++++++++++++++++++- arch/arm/mm/Kconfig | 23 ++++++ arch/arm/mm/Makefile | 2 +- arch/arm/mm/fault.c | 3 + arch/arm/mm/proc-macros.S | 3 +- arch/arm/mm/proc-v7-2level.S | 6 -- arch/arm/mm/proc-v7-bugs.c | 130 +++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 154 +++++++++++++++++++++++++++++-------- 20 files changed, 469 insertions(+), 50 deletions(-) create mode 100644 arch/arm/kernel/bugs.c create mode 100644 arch/arm/mm/proc-v7-bugs.c
Quoted 71 lines · Russell King - ARM Linux
This series addresses the Spectre variant 2 issues on ARM Cortex and Broadcom Brahma B15 CPUs. Due to the complexity of the bug, it is not possible to verify that this series fixes any of the bugs, since it has not been able to reproduce these exact scenarios using test programs.
I believe that this covers the entire extent of the Spectre variant 2 issues, with the exception of Cortex A53 and Cortex A72 processors as these require a substantially more complex solution (except where the workaround is implemented in PSCI firmware.)
Spectre variant 1 is not covered by this series.
The patch series is based partly on Marc Zyngier's work from February - two of the KVM patches are from Marc's work.
The main differences are:
- Inclusion of more processors as per current ARM Ltd security update documentation.
- Extension of "bugs" infrastructure to detect Cortex A8 and Cortex A15 CPUs missing out on the IBE bit being set on (re-)entry to the kernel through all paths.
- Handle all suspect userspace-touching-kernelspace aborts irrespective of mapping type.The first patch will trivially conflict with the Broadcom Brahma updates already in arm-soc - it has been necessary to independently add the ID definitions for the B15 CPU.
Having worked through this series, I'm of the opinion that the
define_processor_functionsmacro in proc-v7 are probably more hassle than they're worth - here, we don't need the global equivalent symbols, because we never refer to them from the kernel code for any V7 processor (MULTI_CPUis always defined.)This series is currently in my "spectre" branch (along with some Spectre variant 1 patches.)
Please carefully review.
arch/arm/include/asm/bugs.h | 6 +- arch/arm/include/asm/cp15.h | 3 + arch/arm/include/asm/cputype.h | 5 ++ arch/arm/include/asm/kvm_asm.h | 2 - arch/arm/include/asm/kvm_host.h | 14 +++- arch/arm/include/asm/kvm_mmu.h | 23 +++++- arch/arm/include/asm/proc-fns.h | 4 + arch/arm/include/asm/system_misc.h | 8 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/bugs.c | 18 +++++ arch/arm/kernel/smp.c | 4 + arch/arm/kernel/suspend.c | 2 + arch/arm/kvm/hyp/hyp-entry.S | 108 ++++++++++++++++++++++++- arch/arm/mm/Kconfig | 23 ++++++ arch/arm/mm/Makefile | 2 +- arch/arm/mm/fault.c | 3 + arch/arm/mm/proc-macros.S | 3 +- arch/arm/mm/proc-v7-2level.S | 6 -- arch/arm/mm/proc-v7-bugs.c | 130 ++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 158 +++++++++++++++++++++++++++++-------- 20 files changed, 471 insertions(+), 52 deletions(-)Signature · 8 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
PATCH 1/14 ARM: add CPU part numbers for Cortex A73, A75 and Brahma B15
Add CPU part numbers for the above mentioned CPUs
--- arch/arm/include/asm/cputype.h | 5 +++++ 1 file changed, 5 insertions(+)
arch/arm/include/asm/cputype.h +5 -0
@@ -77,8 +77,13 @@#define ARM_CPU_PART_CORTEX_A12 0x4100c0d0#define ARM_CPU_PART_CORTEX_A17 0x4100c0e0#define ARM_CPU_PART_CORTEX_A15 0x4100c0f0 +#define ARM_CPU_PART_CORTEX_A73 0x4100d090 +#define ARM_CPU_PART_CORTEX_A75 0x4100d0a0#define ARM_CPU_PART_MASK 0xff00fff0 +/* Broadcom cores */ +#define ARM_CPU_PART_BRAHMA_B15 0x420000f0 +/* DEC implemented cores */ #define ARM_CPU_PART_SA1100 0x4400a110
Signature · 1 line
2.7.4
PATCH 2/14 ARM: bugs: prepare processor bug infrastructure
In reply to Russell King - ARM LinuxPrepare the processor bug infrastructure so that it can be expanded to check for per-processor bugs.
--- arch/arm/include/asm/bugs.h | 4 ++-- arch/arm/kernel/Makefile | 1 + arch/arm/kernel/bugs.c | 9 +++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 arch/arm/kernel/bugs.c
arch/arm/include/asm/bugs.h +2 -2
@@ -10,10 +10,10 @@#ifndef __ASM_BUGS_H#define __ASM_BUGS_H -#ifdef CONFIG_MMU extern void check_writebuffer_bugs (void ); -#define check_bugs () check_writebuffer_bugs() +#ifdef CONFIG_MMU +extern void check_bugs (void );#else #define check_bugs () do { } while (0)#endif
arch/arm/kernel/Makefile +1 -0
@@ -31,6 +31,7 @@ else obj-y += entry-armv.o endif +obj-$(CONFIG_MMU) += bugs.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_ISA_DMA_API) += dma.o obj-$(CONFIG_FIQ) += fiq.o fiqasm.o
arch/arm/kernel/bugs.c new file +9 -0
@@ -0,0 +1,9 @@ +// SPDX-Identifier: GPL-2.0 +#include <linux/init.h> +#include <asm/bugs.h> +#include <asm/proc-fns.h> + +void __init check_bugs (void ) +{ +check_writebuffer_bugs (); +}
Signature · 1 line
2.7.4
PATCH 3/14 ARM: bugs: hook processor bug checking into SMP and suspend paths
In reply to Russell King - ARM LinuxCheck for CPU bugs when secondary processors are being brought online, and also when CPUs are resuming from a low power mode. This gives an opportunity to check that processor specific bug workarounds are correctly enabled for all paths that a CPU re-enters the kernel.
--- arch/arm/include/asm/bugs.h | 2 ++ arch/arm/kernel/bugs.c | 5 +++++ arch/arm/kernel/smp.c | 4 ++++ arch/arm/kernel/suspend.c | 2 ++ 4 files changed, 13 insertions(+)
arch/arm/include/asm/bugs.h +2 -0
@@ -14,8 +14,10 @@ extern void check_writebuffer_bugs(void);#ifdef CONFIG_MMU extern void check_bugs (void ); +extern void check_other_bugs (void );#else #define check_bugs () do { } while (0) +#define check_other_bugs () do { } while (0)#endif #endif
arch/arm/kernel/bugs.c +5 -0
@@ -3,7 +3,12 @@#include <asm/bugs.h> #include <asm/proc-fns.h> +void check_other_bugs (void ) +{ +} +void __init check_bugs (void ) {check_writebuffer_bugs (); +check_other_bugs (); }
arch/arm/kernel/smp.c +4 -0
@@ -31,6 +31,7 @@#include <linux/irq_work.h> #include <linux/atomic.h> +#include <asm/bugs.h> #include <asm/smp.h> #include <asm/cacheflush.h> #include <asm/cpu.h>
@@ -405,6 +406,9 @@ asmlinkage void secondary_start_kernel(void)* before we continue - which happens after __cpu_up returns. */ set_cpu_online (cpu, true); + +check_other_bugs (); +complete (&cpu_running);local_irq_enable ();
arch/arm/kernel/suspend.c +2 -0
@@ -3,6 +3,7 @@#include <linux/slab.h> #include <linux/mm_types.h> +#include <asm/bugs.h> #include <asm/cacheflush.h> #include <asm/idmap.h> #include <asm/pgalloc.h>
@@ -36,6 +37,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))cpu_switch_mm (mm->pgd, mm);local_flush_bp_all ();local_flush_tlb_all (); +check_other_bugs (); }return ret;
Signature · 1 line
2.7.4
Re: [PATCH 03/14] ARM: bugs: hook processor bug checking into SMP and suspend paths
Quoted 7 lines · Russell King
Check for CPU bugs when secondary processors are being brought online, and also when CPUs are resuming from a low power mode. This gives an opportunity to check that processor specific bug workarounds are correctly enabled for all paths that a CPU re-enters the kernel.
Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>
Something I missed, is that this correctly warns about e.g: missing the IBE bit for secondary cores, but it seems to be missing it for the boot CPU:
[ 0.001053] CPU: Testing write buffer coherency: ok [ 0.001086] CPU: Spectre v2: using ICIALLU workaround [ 0.001304] CPU0: update cpu_capacity 1024 [ 0.001316] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 [ 0.001693] Setting up static identity map for 0x200000 - 0x200060 [ 0.001769] Hierarchical SRCU implementation. [ 0.003951] brcmstb: biuctrl: MCP: Write pairing already disabled [ 0.004224] smp: Bringing up secondary CPUs ... [ 0.004874] CPU1: update cpu_capacity 1024 [ 0.004877] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001 [ 0.004881] CPU1: Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable [ 0.005604] CPU2: update cpu_capacity 1024 [ 0.005607] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002 [ 0.005610] CPU2: Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable [ 0.006295] CPU3: update cpu_capacity 1024 [ 0.006299] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003 [ 0.006302] CPU3: Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable [ 0.006377] smp: Brought up 1 node, 4 CPUs [ 0.006389] SMP: Total of 4 processors activated (216.00 BogoMIPS). [ 0.006398] CPU: All CPU(s) started in SVC mode.
Which could be confusing if you intentionally restricted a SMP system to UP with maxcpus=1 or smp=off:
[ 0.001043] CPU: Testing write buffer coherency: ok [ 0.001077] CPU: Spectre v2: using ICIALLU workaround [ 0.001291] CPU0: update cpu_capacity 1024 [ 0.001302] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 [ 0.001516] Setting up static identity map for 0x200000 - 0x200060 [ 0.001593] Hierarchical SRCU implementation. [ 0.003829] brcmstb: biuctrl: MCP: Write pairing already disabled [ 0.004097] smp: Bringing up secondary CPUs ... [ 0.004108] smp: Brought up 1 node, 1 CPU [ 0.004117] SMP: Total of 1 processors activated (54.00 BogoMIPS). [ 0.004126] CPU: All CPU(s) started in SVC mode.
Quoted 82 lines
--- arch/arm/include/asm/bugs.h | 2 ++ arch/arm/kernel/bugs.c | 5 +++++ arch/arm/kernel/smp.c | 4 ++++ arch/arm/kernel/suspend.c | 2 ++ 4 files changed, 13 insertions(+)arch/arm/include/asm/bugs.h +2
-0@@ -14,8 +14,10 @@ extern void check_writebuffer_bugs(void);#ifdef CONFIG_MMU extern void check_bugs (void ); +extern void check_other_bugs (void );#else #define check_bugs () do { } while (0) +#define check_other_bugs () do { } while (0)#endif #endif arch/arm/kernel/bugs.c +5
-0@@ -3,7 +3,12 @@#include <asm/bugs.h> #include <asm/proc-fns.h> +void check_other_bugs (void ) +{ +} +void __init check_bugs (void ) {check_writebuffer_bugs (); +check_other_bugs (); }arch/arm/kernel/smp.c +4
-0@@ -31,6 +31,7 @@#include <linux/irq_work.h> #include <linux/atomic.h> +#include <asm/bugs.h> #include <asm/smp.h> #include <asm/cacheflush.h> #include <asm/cpu.h> @@ -405,6 +406,9 @@ asmlinkage void secondary_start_kernel(void)* before we continue - which happens after __cpu_up returns. */ set_cpu_online (cpu, true); + +check_other_bugs (); +complete (&cpu_running);local_irq_enable ();arch/arm/kernel/suspend.c +2
-0@@ -3,6 +3,7 @@#include <linux/slab.h> #include <linux/mm_types.h> +#include <asm/bugs.h> #include <asm/cacheflush.h> #include <asm/idmap.h> #include <asm/pgalloc.h> @@ -36,6 +37,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))cpu_switch_mm (mm->pgd, mm);local_flush_bp_all ();local_flush_tlb_all (); +check_other_bugs (); }return ret;
Signature · 1 line
Florian
Russell King - ARM Linux
maintainerRe: [PATCH 03/14] ARM: bugs: hook processor bug checking into SMP and suspend paths
Quoted 11 lines · Florian Fainelli
Quoted 7 lines · Russell King
Check for CPU bugs when secondary processors are being brought online, and also when CPUs are resuming from a low power mode. This gives an opportunity to check that processor specific bug workarounds are correctly enabled for all paths that a CPU re-enters the kernel.
Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>Something I missed, is that this correctly warns about e.g: missing the IBE bit for secondary cores, but it seems to be missing it for the boot CPU:
Are you sure that the boot CPU has the IBE bit clear?
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Russell King - ARM Linux
maintainerRe: [PATCH 03/14] ARM: bugs: hook processor bug checking into SMP and suspend paths
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Florian Fainelli
Quoted 5 lines · Russell King
Check for CPU bugs when secondary processors are being brought online, and also when CPUs are resuming from a low power mode. This gives an opportunity to check that processor specific bug workarounds are correctly enabled for all paths that a CPU re-enters the kernel.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>Something I missed, is that this correctly warns about e.g: missing the IBE bit for secondary cores, but it seems to be missing it for the boot CPU:
Are you sure that the boot CPU has the IBE bit clear?
Here's what I get on TI Keystone 2, which doesn't set the IBE bit for any CPU:
CPU: Testing write buffer coherency: ok
CPU0: Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable
CPU0: Spectre v2: using ICIALLU workaround
/cpus/cpu@0 missing clock-frequency property
/cpus/cpu@1 missing clock-frequency property
/cpus/cpu@2 missing clock-frequency property
/cpus/cpu@3 missing clock-frequency property
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x80008300 - 0x80008438
Hierarchical SRCU implementation.
smp: Bringing up secondary CPUs ...
CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
CPU1: Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable
CPU1: Spectre v2: using ICIALLU workaround
CPU2: thread -1, cpu 2, socket 0, mpidr 80000002
CPU2: Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable
CPU2: Spectre v2: using ICIALLU workaround
CPU3: thread -1, cpu 3, socket 0, mpidr 80000003
CPU3: Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable
CPU3: Spectre v2: using ICIALLU workaround
It should be noted that, if we implement a "bugs" bit exported to userspace (as I think someone requested) that booting on a system where only the boot CPU initially comes up (which has the IBE bit set) and then bringing the secondary CPUs online after userspace has started (where those CPUs don't have the IBE bit set) will result in the system initially not being vulnerable, but then becoming vulnerable when running on those other CPUs.
If the bugs bit had already been checked by userspace, then it would think that there's no system level vulnerability. Userspace would need to check the status each time a CPU comes online.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
PATCH 4/14 ARM: bugs: add support for per-processor bug checking
In reply to Russell King - ARM LinuxAdd support for per-processor bug checking - each processor function descriptor gains a function pointer for this check, which must not be an __init function. If non-NULL, this will be called whenever a CPU enters the kernel via which ever path (boot CPU, secondary CPU startup, CPU resuming, etc.)
This allows processor specific bug checks to validate that workaround bits are properly enabled by firmware via all entry paths to the kernel.
--- arch/arm/include/asm/proc-fns.h | 4 ++++ arch/arm/kernel/bugs.c | 4 ++++ arch/arm/mm/proc-macros.S | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-)
arch/arm/include/asm/proc-fns.h +4 -0
@@ -37,6 +37,10 @@ extern struct processor {*/ void (*_proc_init)(void );/* +* Check for processor bugs +*/ +void (*check_bugs)(void ); +/* * Disable any processor specifics */ void (*_proc_fin)(void );
arch/arm/kernel/bugs.c +4 -0
@@ -5,6 +5,10 @@void check_other_bugs (void ) { +#ifdef MULTI_CPU +if (processor.check_bugs) + processor.check_bugs (); +#endif }void __init check_bugs (void )
arch/arm/mm/proc-macros.S +2 -1
@@ -273,13 +273,14 @@ mcr p15, 0, ip, c7, c10, 4 @ data write barrier .endm -.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0 +.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0, bugs=0 .type \name\()_processor_functions, #object .align 2 ENTRY(\name\()_processor_functions) .word \dabort .word \pabort .word cpu_\name\()_proc_init + .word \bugs .word cpu_\name\()_proc_fin .word cpu_\name\()_reset .word cpu_\name\()_do_idle
Signature · 1 line
2.7.4
PATCH 5/14 ARM: spectre: add Kconfig symbol for CPUs vulnerable to Spectre
In reply to Russell King - ARM LinuxAdd a Kconfig symbol for CPUs which are vulnerable to the Spectre attacks.
--- arch/arm/mm/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm/mm/Kconfig +4 -0
@@ -415,6 +415,7 @@ config CPU_V7 select CPU_CP15_MPU if !MMU select CPU_HAS_ASID if MMU select CPU_PABRT_V7 + select CPU_SPECTRE if MMU select CPU_THUMB_CAPABLE select CPU_TLB_V7 if MMU
@@ -826,6 +827,9 @@ config CPU_BPREDICT_DISABLE help Say Y here to disable branch prediction. If unsure, say N. +config CPU_SPECTRE + bool + config TLS_REG_EMUL bool select NEED_KUSER_HELPERS
Signature · 1 line
2.7.4
PATCH 6/14 ARM: spectre-v2: harden branch predictor on context switches
In reply to Russell King - ARM LinuxHarden the branch predictor against Spectre v2 attacks on context switches for ARMv7 and later CPUs. We do this by:
Cortex A9, A12, A17, A73, A75: invalidating the BTB. Cortex A15, Brahma B15: invalidating the instruction cache.
Cortex A57 and Cortex A72 are not addressed in this patch.
Cortex R7 and Cortex R8 are also not addressed as we do not enforce memory protection on these cores.
--- arch/arm/mm/Kconfig | 19 +++++++ arch/arm/mm/proc-v7-2level.S | 6 --- arch/arm/mm/proc-v7.S | 125 +++++++++++++++++++++++++++++++++---------- 3 files changed, 115 insertions(+), 35 deletions(-)
arch/arm/mm/Kconfig +19 -0
@@ -830,6 +830,25 @@ config CPU_BPREDICT_DISABLE config CPU_SPECTRE bool +config HARDEN_BRANCH_PREDICTOR + bool "Harden the branch predictor against aliasing attacks" if EXPERT + depends on CPU_SPECTRE + default y + help + Speculation attacks against some high-performance processors rely + on being able to manipulate the branch predictor for a victim + context by executing aliasing branches in the attacker context. + Such attacks can be partially mitigated against by clearing + internal branch predictor state and limiting the prediction + logic in some situations. + + This config option will take CPU-specific actions to harden + the branch predictor against aliasing attacks and may rely on + specific instruction sequences or control bits being set by + the system firmware. + + If unsure, say Y. + config TLS_REG_EMUL bool select NEED_KUSER_HELPERS
arch/arm/mm/proc-v7-2level.S +0 -6
@@ -41,11 +41,6 @@ * even on Cortex-A8 revisions not affected by 430973. * If IBE is not set, the flush BTAC/BTB won't do anything. */ -ENTRY(cpu_ca8_switch_mm) -#ifdef CONFIG_MMU - mov r2, #0 - mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB -#endif ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_MMU mmid r1, r1 @ get mm->context.id
@@ -66,7 +61,6 @@ ENTRY(cpu_v7_switch_mm) #endif bx lr ENDPROC(cpu_v7_switch_mm) -ENDPROC(cpu_ca8_switch_mm) /* * cpu_v7_set_pte_ext(ptep, pte)
arch/arm/mm/proc-v7.S +96 -29
173 lines not on this page · raw message
Signature · 1 line
2.7.4
Re: [PATCH 06/14] ARM: spectre-v2: harden branch predictor on context switches
Quoted 6 lines · Russell King
Harden the branch predictor against Spectre v2 attacks on context switches for ARMv7 and later CPUs. We do this by:
Cortex A9, A12, A17, A73, A75: invalidating the BTB. Cortex A15, Brahma B15: invalidating the instruction cache.
Quoted 6 lines
Cortex A57 and Cortex A72 are not addressed in this patch.
Cortex R7 and Cortex R8 are also not addressed as we do not enforce memory protection on these cores.
Signed-off-by Russell King <[email protected]>
Signature · 1 line
Florian
Russell King - ARM Linux
maintainerRe: [PATCH 06/14] ARM: spectre-v2: harden branch predictor on context switches
Quoted 9 lines · Florian Fainelli
Quoted 6 lines · Russell King
Harden the branch predictor against Spectre v2 attacks on context switches for ARMv7 and later CPUs. We do this by:
Cortex A9, A12, A17, A73, A75: invalidating the BTB. Cortex A15, Brahma B15: invalidating the instruction cache.
Quoted 8 lines
Quoted 6 lines
Cortex A57 and Cortex A72 are not addressed in this patch.
Cortex R7 and Cortex R8 are also not addressed as we do not enforce memory protection on these cores.
Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>
It does need this additional patch to avoid some build errors - I'm surprised that my autobuilder found it before the 0-day builder...
arch/arm/mm/proc-v7-bugs.c +4 -0
@@ -127,4 +127,8 @@ void cpu_v7_bugs_init(void)pr_info ("CPU: Spectre v2: using %s workaround\n" , spectre_v2_method); } +#else +void cpu_v7_bugs_init (void ) +{ +}#endif
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Re: [PATCH 06/14] ARM: spectre-v2: harden branch predictor on context switches
In reply to Russell KingQuoted 10 lines · Russell King
Harden the branch predictor against Spectre v2 attacks on context switches for ARMv7 and later CPUs. We do this by:
Cortex A9, A12, A17, A73, A75: invalidating the BTB. Cortex A15, Brahma B15: invalidating the instruction cache.
Cortex A57 and Cortex A72 are not addressed in this patch.
Cortex R7 and Cortex R8 are also not addressed as we do not enforce memory protection on these cores.
Not seeing regressions so:
PATCH 7/14 ARM: spectre-v2: add Cortex A8 and A15 validation of the IBE bit
In reply to Russell King - ARM LinuxWhen the branch predictor hardening is enabled, firmware must have set the IBE bit in the auxiliary control register. If this bit has not been set, the Spectre workarounds will not be functional.
Add validation that this bit is set, and print a warning at alert level if this is not the case.
--- arch/arm/mm/Makefile | 2 +- arch/arm/mm/proc-v7-bugs.c | 29 +++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 4 ++-- 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mm/proc-v7-bugs.c
arch/arm/mm/Makefile +1 -1
@@ -97,7 +97,7 @@ obj-$(CONFIG_CPU_MOHAWK) += proc-mohawk.o obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o obj-$(CONFIG_CPU_V6) += proc-v6.o obj-$(CONFIG_CPU_V6K) += proc-v6.o -obj-$(CONFIG_CPU_V7) += proc-v7.o +obj-$(CONFIG_CPU_V7) += proc-v7.o proc-v7-bugs.o obj-$(CONFIG_CPU_V7M) += proc-v7m.o AFLAGS_proc-v6.o :=-Wa,-march=armv6
arch/arm/mm/proc-v7-bugs.c new file +29 -0
@@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/kernel.h> +#include <linux/smp.h> + +static __maybe_unused void cpu_v7_check_auxcr_set (u32 mask,const char *msg) +{ +u32 aux_cr; + + asm("mrc p15, 0, %0, c1, c0, 1" :"=r" (aux_cr)); + +if ((aux_cr & mask) != mask) +pr_err ("CPU%u: %s" ,smp_processor_id (), msg); +} + +static void check_spectre_auxcr (u32 bit) +{ +if (IS_ENABLED (CONFIG_HARDEN_BRANCH_PREDICTOR )) +cpu_v7_check_auxcr_set (bit,"Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable\n" ); +} + +void cpu_v7_ca8_ibe (void ) +{ +check_spectre_auxcr (BIT (6 )); +} + +void cpu_v7_ca15_ibe (void ) +{ +check_spectre_auxcr (BIT (0 )); +}
arch/arm/mm/proc-v7.S +2 -2
@@ -569,7 +569,7 @@ ENDPROC(__v7_setup) globl_equ cpu_ca8_do_suspend, cpu_v7_do_suspend globl_equ cpu_ca8_do_resume, cpu_v7_do_resume #endif - define_processor_functions ca8, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions ca8, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_ca8_ibe @ Cortex-A9 - needs more registers preserved across suspend/resume @ and bpiall switch_mm for hardening
@@ -602,7 +602,7 @@ ENDPROC(__v7_setup) globl_equ cpu_ca15_suspend_size, cpu_v7_suspend_size globl_equ cpu_ca15_do_suspend, cpu_v7_do_suspend globl_equ cpu_ca15_do_resume, cpu_v7_do_resume - define_processor_functions ca15, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions ca15, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_ca15_ibe #ifdef CONFIG_CPU_PJ4B define_processor_functions pj4b, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 #endif
Signature · 1 line
2.7.4
Re: [PATCH 07/14] ARM: spectre-v2: add Cortex A8 and A15 validation of the IBE bit
Quoted 9 lines · Russell King
When the branch predictor hardening is enabled, firmware must have set the IBE bit in the auxiliary control register. If this bit has not been set, the Spectre workarounds will not be functional.
Add validation that this bit is set, and print a warning at alert level if this is not the case.
Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>
Yup the alert is working:
PATCH 8/14 ARM: spectre-v2: harden user aborts in kernel space
In reply to Russell King - ARM LinuxIn order to prevent aliasing attacks on the branch predictor, invalidate the BTB or instruction cache on CPUs that are known to be affected when taking an abort on a address that is outside of a user task limit:
Cortex A8, A9, A12, A17, A73, A75: flush BTB.
Cortex A15, Brahma B15: invalidate icache.
--- arch/arm/include/asm/cp15.h | 3 +++ arch/arm/include/asm/system_misc.h | 8 ++++++ arch/arm/mm/fault.c | 3 +++ arch/arm/mm/proc-v7-bugs.c | 51 ++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 8 +++--- 5 files changed, 70 insertions(+), 3 deletions(-)
arch/arm/include/asm/cp15.h +3 -0
@@ -65,6 +65,9 @@#define __write_sysreg (v, r, w, c, t) asm volatile(w " " c : : "r" ((t)(v)))#define write_sysreg (v, ...) __write_sysreg(v, __VA_ARGS__) +#define BPIALL __ACCESS_CP15(c7, 0, c5, 6) +#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) +extern unsigned long cr_alignment;/* defined in entry-armv.S */ static inline unsigned long get_cr (void )
arch/arm/include/asm/system_misc.h +8 -0
@@ -15,6 +15,14 @@ void soft_restart(unsigned long);extern void (*arm_pm_restart)(enum reboot_mode reboot_mode,const char *cmd);extern void (*arm_pm_idle)(void ); +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +extern void (*harden_branch_predictor)(void ); +#define harden_branch_predictor () \ + do { if (harden_branch_predictor) harden_branch_predictor(); } while (0) +#else +#define harden_branch_predictor () do { } while (0) +#endif +#define UDBG_UNDEFINED (1 << 0)#define UDBG_SYSCALL (1 << 1)#define UDBG_BADABORT (1 << 2)
arch/arm/mm/fault.c +3 -0
@@ -163,6 +163,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, {struct siginfo si; +if (addr >TASK_SIZE ) +harden_branch_predictor (); +#ifdef CONFIG_DEBUG_USER if (((user_debug &UDBG_SEGV ) && (sig ==SIGSEGV )) || ((user_debug &UDBG_BUS ) && (sig ==SIGBUS ))) {
arch/arm/mm/proc-v7-bugs.c +51 -0
66 lines not on this page · raw message
arch/arm/mm/proc-v7.S +5 -3
@@ -532,8 +532,10 @@ ENDPROC(__v7_setup) __INITDATA + .weak cpu_v7_bugs_init + @ define struct processor (see <asm/proc-fns.h> and proc-macros.S) - define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR @ generic v7 bpiall on context switch
@@ -548,7 +550,7 @@ ENDPROC(__v7_setup) globl_equ cpu_v7_bpiall_do_suspend, cpu_v7_do_suspend globl_equ cpu_v7_bpiall_do_resume, cpu_v7_do_resume #endif - define_processor_functions v7_bpiall, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions v7_bpiall, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init #define HARDENED_BPIALL_PROCESSOR_FUNCTIONS v7_bpiall_processor_functions #else
@@ -584,7 +586,7 @@ ENDPROC(__v7_setup) globl_equ cpu_ca9mp_switch_mm, cpu_v7_switch_mm #endif globl_equ cpu_ca9mp_set_pte_ext, cpu_v7_set_pte_ext - define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init #endif @ Cortex-A15 - needs iciallu switch_mm for hardening
Signature · 1 line
2.7.4
Re: [PATCH 08/14] ARM: spectre-v2: harden user aborts in kernel space
Quoted 104 lines · Russell King
In order to prevent aliasing attacks on the branch predictor, invalidate the BTB or instruction cache on CPUs that are known to be affected when taking an abort on a address that is outside of a user task limit:
Cortex A8, A9, A12, A17, A73, A75: flush BTB.
Cortex A15, Brahma B15: invalidate icache.Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>--- arch/arm/include/asm/cp15.h | 3 +++ arch/arm/include/asm/system_misc.h | 8 ++++++ arch/arm/mm/fault.c | 3 +++ arch/arm/mm/proc-v7-bugs.c | 51 ++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 8 +++--- 5 files changed, 70 insertions(+), 3 deletions(-)arch/arm/include/asm/cp15.h +3
-0@@ -65,6 +65,9 @@#define __write_sysreg (v, r, w, c, t) asm volatile(w " " c : : "r" ((t)(v)))#define write_sysreg (v, ...) __write_sysreg(v, __VA_ARGS__) +#define BPIALL __ACCESS_CP15(c7, 0, c5, 6) +#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) +extern unsigned long cr_alignment;/* defined in entry-armv.S */ static inline unsigned long get_cr (void )arch/arm/include/asm/system_misc.h +8
-0@@ -15,6 +15,14 @@ void soft_restart(unsigned long);extern void (*arm_pm_restart)(enum reboot_mode reboot_mode,const char *cmd);extern void (*arm_pm_idle)(void ); +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +extern void (*harden_branch_predictor)(void ); +#define harden_branch_predictor () \ + do { if (harden_branch_predictor) harden_branch_predictor(); } while (0) +#else +#define harden_branch_predictor () do { } while (0) +#endif +#define UDBG_UNDEFINED (1 << 0)#define UDBG_SYSCALL (1 << 1)#define UDBG_BADABORT (1 << 2)arch/arm/mm/fault.c +3
-0@@ -163,6 +163,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, {struct siginfo si; +if (addr >TASK_SIZE ) +harden_branch_predictor (); +#ifdef CONFIG_DEBUG_USER if (((user_debug &UDBG_SEGV ) && (sig ==SIGSEGV )) || ((user_debug &UDBG_BUS ) && (sig ==SIGBUS ))) {arch/arm/mm/proc-v7-bugs.c +19
-0@@ -2,6 +2,12 @@#include <linux/kernel.h> #include <linux/smp.h> +#include <asm/cp15.h> +#include <asm/cputype.h> +#include <asm/system_misc.h> + +void cpu_v7_bugs_init (void ); +static __maybe_unused void cpu_v7_check_auxcr_set (u32 mask,const char *msg) {u32 aux_cr;@@ -21,9 +27,54 @@ static void check_spectre_auxcr(u32 bit)void cpu_v7_ca8_ibe (void ) {check_spectre_auxcr (BIT (6 )); +cpu_v7_bugs_init (); }void cpu_v7_ca15_ibe (void ) {check_spectre_auxcr (BIT (0 )); +cpu_v7_bugs_init (); +} + +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +void (*harden_branch_predictor)(void ); + +static void harden_branch_predictor_bpiall (void ) +{ +write_sysreg (0 ,BPIALL ); +} + +static void harden_branch_predictor_iciallu (void )
arch/arm/mm/proc-v7-bugs.c static void check_spectre_auxcr(u32 bit) · line 57
Quoted 10 lines
arch/arm/mm/proc-v7-bugs.c +10
-0+{ +write_sysreg (0 ,ICIALLU ); +} + +void cpu_v7_bugs_init (void ) +{ +const char *spectre_v2_method =NULL ; + +if (harden_branch_predictor) +return ;
How does it work on a big-little systems where two CPUs have diverging mitigation methods? Let's say an hypothetical A15/A17 system? Or even a more common A15/A7 system, where the small core doesn't require the mitigation?
arch/arm/mm/proc-v7-bugs.c static void check_spectre_auxcr(u32 bit) · line 68
Quoted 11 lines
arch/arm/mm/proc-v7-bugs.c +11
-0+ +switch (read_cpuid_part ()) { +case ARM_CPU_PART_CORTEX_A8 : +case ARM_CPU_PART_CORTEX_A9 : +case ARM_CPU_PART_CORTEX_A12 : +case ARM_CPU_PART_CORTEX_A17 : +case ARM_CPU_PART_CORTEX_A73 : +case ARM_CPU_PART_CORTEX_A75 : + harden_branch_predictor = harden_branch_predictor_bpiall; + spectre_v2_method ="BPIALL" ; +break ;
You don't seem to take into account the PFR0.CSV2 field which indicates that the CPU has a branch predictor that is immune to Spectre-v2.
See for example the Cortex-A75 r3p0 TRM[1].
Quoted 39 lines
arch/arm/mm/proc-v7-bugs.c +11
-0+ +case ARM_CPU_PART_CORTEX_A15 : +case ARM_CPU_PART_BRAHMA_B15 : + harden_branch_predictor = harden_branch_predictor_iciallu; + spectre_v2_method ="ICIALLU" ; + break; + } +if (spectre_v2_method) +pr_info ("CPU: Spectre v2: using %s workaround\n" , + spectre_v2_method); } +#endif arch/arm/mm/proc-v7.S +4
-2@@ -532,8 +532,10 @@ ENDPROC(__v7_setup) __INITDATA + .weak cpu_v7_bugs_init + @ define struct processor (see <asm/proc-fns.h> and proc-macros.S) - define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR @ generic v7 bpiall on context switch@@ -548,7 +550,7 @@ ENDPROC(__v7_setup) globl_equ cpu_v7_bpiall_do_suspend, cpu_v7_do_suspend globl_equ cpu_v7_bpiall_do_resume, cpu_v7_do_resume #endif - define_processor_functions v7_bpiall, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions v7_bpiall, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init #define HARDENED_BPIALL_PROCESSOR_FUNCTIONS v7_bpiall_processor_functions #else
arch/arm/mm/proc-v7.S ENDPROC(__v7_setup) · line 592
Quoted 8 lines
arch/arm/mm/proc-v7.S +1
-1@@ -584,7 +586,7 @@ ENDPROC(__v7_setup) globl_equ cpu_ca9mp_switch_mm, cpu_v7_switch_mm #endif globl_equ cpu_ca9mp_set_pte_ext, cpu_v7_set_pte_ext - define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init #endif @ Cortex-A15 - needs iciallu switch_mm for hardening
Thanks,
M.
[1]
http://infocenter.arm.com/help/topic/com.arm.doc.100403_0300_00_en/axa1518783469631.html
Signature · 1 line
Jazz is not dead. It just smells funny...
Russell King - ARM Linux
maintainerRe: [PATCH 08/14] ARM: spectre-v2: harden user aborts in kernel space
Quoted 112 lines · Marc Zyngier
Quoted 111 lines · Russell King
In order to prevent aliasing attacks on the branch predictor, invalidate the BTB or instruction cache on CPUs that are known to be affected when taking an abort on a address that is outside of a user task limit:
Cortex A8, A9, A12, A17, A73, A75: flush BTB.
Cortex A15, Brahma B15: invalidate icache.Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>--- arch/arm/include/asm/cp15.h | 3 +++ arch/arm/include/asm/system_misc.h | 8 ++++++ arch/arm/mm/fault.c | 3 +++ arch/arm/mm/proc-v7-bugs.c | 51 ++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 8 +++--- 5 files changed, 70 insertions(+), 3 deletions(-)arch/arm/include/asm/cp15.h +3
-0@@ -65,6 +65,9 @@#define __write_sysreg (v, r, w, c, t) asm volatile(w " " c : : "r" ((t)(v)))#define write_sysreg (v, ...) __write_sysreg(v, __VA_ARGS__) +#define BPIALL __ACCESS_CP15(c7, 0, c5, 6) +#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) +extern unsigned long cr_alignment;/* defined in entry-armv.S */ static inline unsigned long get_cr (void )arch/arm/include/asm/system_misc.h +8
-0@@ -15,6 +15,14 @@ void soft_restart(unsigned long);extern void (*arm_pm_restart)(enum reboot_mode reboot_mode,const char *cmd);extern void (*arm_pm_idle)(void ); +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +extern void (*harden_branch_predictor)(void ); +#define harden_branch_predictor () \ + do { if (harden_branch_predictor) harden_branch_predictor(); } while (0) +#else +#define harden_branch_predictor () do { } while (0) +#endif +#define UDBG_UNDEFINED (1 << 0)#define UDBG_SYSCALL (1 << 1)#define UDBG_BADABORT (1 << 2)arch/arm/mm/fault.c +3
-0@@ -163,6 +163,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, {struct siginfo si; +if (addr >TASK_SIZE ) +harden_branch_predictor (); +#ifdef CONFIG_DEBUG_USER if (((user_debug &UDBG_SEGV ) && (sig ==SIGSEGV )) || ((user_debug &UDBG_BUS ) && (sig ==SIGBUS ))) {arch/arm/mm/proc-v7-bugs.c +26
-0@@ -2,6 +2,12 @@#include <linux/kernel.h> #include <linux/smp.h> +#include <asm/cp15.h> +#include <asm/cputype.h> +#include <asm/system_misc.h> + +void cpu_v7_bugs_init (void ); +static __maybe_unused void cpu_v7_check_auxcr_set (u32 mask,const char *msg) {u32 aux_cr;@@ -21,9 +27,54 @@ static void check_spectre_auxcr(u32 bit)void cpu_v7_ca8_ibe (void ) {check_spectre_auxcr (BIT (6 )); +cpu_v7_bugs_init (); }void cpu_v7_ca15_ibe (void ) {check_spectre_auxcr (BIT (0 )); +cpu_v7_bugs_init (); +} + +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +void (*harden_branch_predictor)(void ); + +static void harden_branch_predictor_bpiall (void ) +{ +write_sysreg (0 ,BPIALL ); +} + +static void harden_branch_predictor_iciallu (void ) +{ +write_sysreg (0 ,ICIALLU ); +} + +void cpu_v7_bugs_init (void ) +{ +const char *spectre_v2_method =NULL ;
Quoted 8 lines
arch/arm/mm/proc-v7-bugs.c static void check_spectre_auxcr(u32 bit) · line 57
Quoted 3 lines
arch/arm/mm/proc-v7-bugs.c +3
-0+ +if (harden_branch_predictor) +return ;How does it work on a big-little systems where two CPUs have diverging mitigation methods? Let's say an hypothetical A15/A17 system? Or even a more common A15/A7 system, where the small core doesn't require the mitigation?
Hmm, I'd forgotten about those, because I don't have them.
We don't have the ability to mitigate this on such systems at all at present, it would require a per-CPU cpu_switch_mm() implementation, and the code has no structure to support that at present without considerable rewrite of the CPU glue support.
I'm not even sure it could without checking deeper - I think there's some situations where we call this before we're sufficiently setup.
I'll drop this series from the for-next branch, I suspect it won't be making this merge window as a result, sorry.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Russell King - ARM Linux
maintainerRe: [PATCH 08/14] ARM: spectre-v2: harden user aborts in kernel space
Quoted 124 lines · Russell King - ARM Linux
Quoted 112 lines · Marc Zyngier
Quoted 111 lines · Russell King
In order to prevent aliasing attacks on the branch predictor, invalidate the BTB or instruction cache on CPUs that are known to be affected when taking an abort on a address that is outside of a user task limit:
Cortex A8, A9, A12, A17, A73, A75: flush BTB.
Cortex A15, Brahma B15: invalidate icache.Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>--- arch/arm/include/asm/cp15.h | 3 +++ arch/arm/include/asm/system_misc.h | 8 ++++++ arch/arm/mm/fault.c | 3 +++ arch/arm/mm/proc-v7-bugs.c | 51 ++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 8 +++--- 5 files changed, 70 insertions(+), 3 deletions(-)arch/arm/include/asm/cp15.h +3
-0@@ -65,6 +65,9 @@#define __write_sysreg (v, r, w, c, t) asm volatile(w " " c : : "r" ((t)(v)))#define write_sysreg (v, ...) __write_sysreg(v, __VA_ARGS__) +#define BPIALL __ACCESS_CP15(c7, 0, c5, 6) +#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) +extern unsigned long cr_alignment;/* defined in entry-armv.S */ static inline unsigned long get_cr (void )arch/arm/include/asm/system_misc.h +8
-0@@ -15,6 +15,14 @@ void soft_restart(unsigned long);extern void (*arm_pm_restart)(enum reboot_mode reboot_mode,const char *cmd);extern void (*arm_pm_idle)(void ); +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +extern void (*harden_branch_predictor)(void ); +#define harden_branch_predictor () \ + do { if (harden_branch_predictor) harden_branch_predictor(); } while (0) +#else +#define harden_branch_predictor () do { } while (0) +#endif +#define UDBG_UNDEFINED (1 << 0)#define UDBG_SYSCALL (1 << 1)#define UDBG_BADABORT (1 << 2)arch/arm/mm/fault.c +3
-0@@ -163,6 +163,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, {struct siginfo si; +if (addr >TASK_SIZE ) +harden_branch_predictor (); +#ifdef CONFIG_DEBUG_USER if (((user_debug &UDBG_SEGV ) && (sig ==SIGSEGV )) || ((user_debug &UDBG_BUS ) && (sig ==SIGBUS ))) {arch/arm/mm/proc-v7-bugs.c +26
-0@@ -2,6 +2,12 @@#include <linux/kernel.h> #include <linux/smp.h> +#include <asm/cp15.h> +#include <asm/cputype.h> +#include <asm/system_misc.h> + +void cpu_v7_bugs_init (void ); +static __maybe_unused void cpu_v7_check_auxcr_set (u32 mask,const char *msg) {u32 aux_cr;@@ -21,9 +27,54 @@ static void check_spectre_auxcr(u32 bit)void cpu_v7_ca8_ibe (void ) {check_spectre_auxcr (BIT (6 )); +cpu_v7_bugs_init (); }void cpu_v7_ca15_ibe (void ) {check_spectre_auxcr (BIT (0 )); +cpu_v7_bugs_init (); +} + +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +void (*harden_branch_predictor)(void ); + +static void harden_branch_predictor_bpiall (void ) +{ +write_sysreg (0 ,BPIALL ); +} + +static void harden_branch_predictor_iciallu (void ) +{ +write_sysreg (0 ,ICIALLU ); +} + +void cpu_v7_bugs_init (void ) +{ +const char *spectre_v2_method =NULL ;Quoted 8 lines
arch/arm/mm/proc-v7-bugs.c static void check_spectre_auxcr(u32 bit) · line 57
Quoted 3 lines
arch/arm/mm/proc-v7-bugs.c +3
-0+ +if (harden_branch_predictor) +return ;How does it work on a big-little systems where two CPUs have diverging mitigation methods? Let's say an hypothetical A15/A17 system? Or even a more common A15/A7 system, where the small core doesn't require the mitigation?
Hmm, I'd forgotten about those, because I don't have them.
Quoted 7 lines
We don't have the ability to mitigate this on such systems at all at present, it would require a per-CPU
cpu_switch_mm()implementation, and the code has no structure to support that at present without considerable rewrite of the CPU glue support.I'm not even sure it could without checking deeper - I think there's some situations where we call this before we're sufficiently setup.
Confirmed. We can't access per_cpu variables via cpu_switch_mm() because it is used prior to the per_cpu offset being initialised in the CPU. Eg,
secondary_start_kernel
{
...
cpu_switch_mm(mm->pgd, mm);
...
cpu_init(); /* <== per cpu setup */
}However, we can change harden_branch_predictor() to be a per-cpu function pointer to solve some of your concern, but it's still insufficient.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Re: [PATCH 08/14] ARM: spectre-v2: harden user aborts in kernel space
Quoted 140 lines · Russell King - ARM Linux
Quoted 124 lines · Russell King - ARM Linux
Quoted 112 lines · Marc Zyngier
Quoted 111 lines · Russell King
In order to prevent aliasing attacks on the branch predictor, invalidate the BTB or instruction cache on CPUs that are known to be affected when taking an abort on a address that is outside of a user task limit:
Cortex A8, A9, A12, A17, A73, A75: flush BTB.
Cortex A15, Brahma B15: invalidate icache.Signed-off-by Russell King <[email protected]>Reviewed-by Florian Fainelli <[email protected]>--- arch/arm/include/asm/cp15.h | 3 +++ arch/arm/include/asm/system_misc.h | 8 ++++++ arch/arm/mm/fault.c | 3 +++ arch/arm/mm/proc-v7-bugs.c | 51 ++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 8 +++--- 5 files changed, 70 insertions(+), 3 deletions(-)arch/arm/include/asm/cp15.h +3
-0@@ -65,6 +65,9 @@#define __write_sysreg (v, r, w, c, t) asm volatile(w " " c : : "r" ((t)(v)))#define write_sysreg (v, ...) __write_sysreg(v, __VA_ARGS__) +#define BPIALL __ACCESS_CP15(c7, 0, c5, 6) +#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) +extern unsigned long cr_alignment;/* defined in entry-armv.S */ static inline unsigned long get_cr (void )arch/arm/include/asm/system_misc.h +8
-0@@ -15,6 +15,14 @@ void soft_restart(unsigned long);extern void (*arm_pm_restart)(enum reboot_mode reboot_mode,const char *cmd);extern void (*arm_pm_idle)(void ); +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +extern void (*harden_branch_predictor)(void ); +#define harden_branch_predictor () \ + do { if (harden_branch_predictor) harden_branch_predictor(); } while (0) +#else +#define harden_branch_predictor () do { } while (0) +#endif +#define UDBG_UNDEFINED (1 << 0)#define UDBG_SYSCALL (1 << 1)#define UDBG_BADABORT (1 << 2)arch/arm/mm/fault.c +3
-0@@ -163,6 +163,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, {struct siginfo si; +if (addr >TASK_SIZE ) +harden_branch_predictor (); +#ifdef CONFIG_DEBUG_USER if (((user_debug &UDBG_SEGV ) && (sig ==SIGSEGV )) || ((user_debug &UDBG_BUS ) && (sig ==SIGBUS ))) {arch/arm/mm/proc-v7-bugs.c +26
-0@@ -2,6 +2,12 @@#include <linux/kernel.h> #include <linux/smp.h> +#include <asm/cp15.h> +#include <asm/cputype.h> +#include <asm/system_misc.h> + +void cpu_v7_bugs_init (void ); +static __maybe_unused void cpu_v7_check_auxcr_set (u32 mask,const char *msg) {u32 aux_cr;@@ -21,9 +27,54 @@ static void check_spectre_auxcr(u32 bit)void cpu_v7_ca8_ibe (void ) {check_spectre_auxcr (BIT (6 )); +cpu_v7_bugs_init (); }void cpu_v7_ca15_ibe (void ) {check_spectre_auxcr (BIT (0 )); +cpu_v7_bugs_init (); +} + +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +void (*harden_branch_predictor)(void ); + +static void harden_branch_predictor_bpiall (void ) +{ +write_sysreg (0 ,BPIALL ); +} + +static void harden_branch_predictor_iciallu (void ) +{ +write_sysreg (0 ,ICIALLU ); +} + +void cpu_v7_bugs_init (void ) +{ +const char *spectre_v2_method =NULL ;Quoted 8 lines
arch/arm/mm/proc-v7-bugs.c static void check_spectre_auxcr(u32 bit) · line 57
Quoted 3 lines
arch/arm/mm/proc-v7-bugs.c +3
-0+ +if (harden_branch_predictor) +return ;How does it work on a big-little systems where two CPUs have diverging mitigation methods? Let's say an hypothetical A15/A17 system? Or even a more common A15/A7 system, where the small core doesn't require the mitigation?
Hmm, I'd forgotten about those, because I don't have them.
Quoted 7 lines
We don't have the ability to mitigate this on such systems at all at present, it would require a per-CPU
cpu_switch_mm()implementation, and the code has no structure to support that at present without considerable rewrite of the CPU glue support.I'm not even sure it could without checking deeper - I think there's some situations where we call this before we're sufficiently setup.
Confirmed. We can't access
per_cpuvariables viacpu_switch_mm()because it is used prior to theper_cpuoffset being initialised in the CPU. Eg,
secondary_start_kernel
{
...
Quoted 8 lines
cpu_switch_mm(mm->pgd, mm); ... cpu_init(); /* <== per cpu setup */ }However, we can change
harden_branch_predictor()to be a per-cpu function pointer to solve some of your concern, but it's still insufficient.
I hate to play that card, but we have all been waiting for these patches to land in Linus' tree, so on one hand, waiting for the next merge window is probably doable, since nothing is there. On the other hand, does this absolutely needs to be addressed right now?
Signature · 1 line
Florian
Russell King - ARM Linux
maintainerRe: [PATCH 08/14] ARM: spectre-v2: harden user aborts in kernel space
In reply to Marc ZyngierQuoted 14 lines · Marc Zyngier
arch/arm/mm/proc-v7-bugs.c static void check_spectre_auxcr(u32 bit) · line 68
Quoted 10 lines · Russell King
arch/arm/mm/proc-v7-bugs.c +10
-0+switch (read_cpuid_part ()) { +case ARM_CPU_PART_CORTEX_A8 : +case ARM_CPU_PART_CORTEX_A9 : +case ARM_CPU_PART_CORTEX_A12 : +case ARM_CPU_PART_CORTEX_A17 : +case ARM_CPU_PART_CORTEX_A73 : +case ARM_CPU_PART_CORTEX_A75 : + harden_branch_predictor = harden_branch_predictor_bpiall; + spectre_v2_method ="BPIALL" ; +break ;You don't seem to take into account the PFR0.CSV2 field which indicates that the CPU has a branch predictor that is immune to Spectre-v2.
That information is not covered in the description of the vulnerability
- the published information on the security-updates site states that BPIALL is required without stating any conditions.
Quoted 1 line
See for example the Cortex-A75 r3p0 TRM[1].
So which cores should such a test be applied to? As I mention, the support site doesn't give this detail. That brings up the obvious question: what else does the web page miss out on?
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
PATCH 9/14 ARM: spectre-v2: add PSCI based hardening
In reply to Russell King - ARM LinuxAdd PSCI based hardening for cores that require more complex handling in firmware.
--- arch/arm/mm/proc-v7-bugs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 21 +++++++++++++++++++ 2 files changed, 71 insertions(+)
arch/arm/mm/proc-v7-bugs.c +50 -0
@@ -1,9 +1,12 @@// 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> void cpu_v7_bugs_init (void );
@@ -39,6 +42,9 @@ void cpu_v7_ca15_ibe(void)#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR void (*harden_branch_predictor)(void ); +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 );
@@ -49,6 +55,18 @@ static void harden_branch_predictor_iciallu(void)write_sysreg (0 ,ICIALLU ); } +#ifdef CONFIG_ARM_PSCI +static void call_smc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_smc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} + +static void call_hvc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_hvc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} +#endif +void cpu_v7_bugs_init (void ) {const char *spectre_v2_method =NULL ;
@@ -73,6 +91,38 @@ void cpu_v7_bugs_init(void) spectre_v2_method ="ICIALLU" ;break ; } + +#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ; + harden_branch_predictor = 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 ; + harden_branch_predictor = call_smc_arch_workaround_1; + processor.switch_mm = cpu_v7_smc_switch_mm; + spectre_v2_method ="firmware PSCI" ; +break ; + +default : +break ; + } + } +#endif +if (spectre_v2_method)pr_info ("CPU: Spectre v2: using %s workaround\n" , spectre_v2_method);
arch/arm/mm/proc-v7.S +21 -0
@@ -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>
@@ -93,6 +94,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_smc_switch_mm) +#endif ENTRY(cpu_v7_iciallu_switch_mm) mov r3, #0 mcr p15, 0, r3, c7, c5, 0 @ ICIALLU
Signature · 1 line
2.7.4
Re: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
Quoted 61 lines · Russell King
Add PSCI based hardening for cores that require more complex handling in firmware.
Signed-off-by Russell King <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/mm/proc-v7-bugs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 21 +++++++++++++++++++ 2 files changed, 71 insertions(+)arch/arm/mm/proc-v7-bugs.c +19
-0@@ -1,9 +1,12 @@// 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> void cpu_v7_bugs_init (void );@@ -39,6 +42,9 @@ void cpu_v7_ca15_ibe(void)#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR void (*harden_branch_predictor)(void ); +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 );@@ -49,6 +55,18 @@ static void harden_branch_predictor_iciallu(void)write_sysreg (0 ,ICIALLU ); } +#ifdef CONFIG_ARM_PSCI +static void call_smc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_smc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} + +static void call_hvc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_hvc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} +#endif +void cpu_v7_bugs_init (void ) {const char *spectre_v2_method =NULL ;@@ -73,6 +91,38 @@ void cpu_v7_bugs_init(void) spectre_v2_method ="ICIALLU" ;break ; } +
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;
I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
But that's probably moot if you don't support BL systems.
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 117
Quoted 13 lines
arch/arm/mm/proc-v7-bugs.c +13
-0+ harden_branch_predictor = 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 ; + harden_branch_predictor = call_smc_arch_workaround_1; + processor.switch_mm = cpu_v7_smc_switch_mm; + spectre_v2_method ="firmware PSCI" ;
My previous remark still stands: this is not really PSCI.
Thanks,
M.
Signature · 2 lines
Jazz is not dead. It just smells funny... -
Russell King - ARM Linux
maintainerRe: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
Quoted 83 lines · Marc Zyngier
Quoted 61 lines · Russell King
Add PSCI based hardening for cores that require more complex handling in firmware.
Signed-off-by Russell King <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/mm/proc-v7-bugs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 21 +++++++++++++++++++ 2 files changed, 71 insertions(+)arch/arm/mm/proc-v7-bugs.c +19
-0@@ -1,9 +1,12 @@// 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> void cpu_v7_bugs_init (void );@@ -39,6 +42,9 @@ void cpu_v7_ca15_ibe(void)#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR void (*harden_branch_predictor)(void ); +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 );@@ -49,6 +55,18 @@ static void harden_branch_predictor_iciallu(void)write_sysreg (0 ,ICIALLU ); } +#ifdef CONFIG_ARM_PSCI +static void call_smc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_smc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} + +static void call_hvc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_hvc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} +#endif +void cpu_v7_bugs_init (void ) {const char *spectre_v2_method =NULL ;@@ -73,6 +91,38 @@ void cpu_v7_bugs_init(void) spectre_v2_method ="ICIALLU" ;break ; } +arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
But that's probably moot if you don't support BL systems.
Quoted 15 lines
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 117
Quoted 13 lines
arch/arm/mm/proc-v7-bugs.c +13
-0+ harden_branch_predictor = 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 ; + harden_branch_predictor = call_smc_arch_workaround_1; + processor.switch_mm = cpu_v7_smc_switch_mm; + spectre_v2_method ="firmware PSCI" ;My previous remark still stands: this is not really PSCI.
Sorry, no. Your comment was for the HVC call, not the SMC. You said nothing about this one.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Re: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
Quoted 101 lines · Russell King
Quoted 83 lines · Marc Zyngier
Quoted 61 lines · Russell King
Add PSCI based hardening for cores that require more complex handling in firmware.
Signed-off-by Russell King <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/mm/proc-v7-bugs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 21 +++++++++++++++++++ 2 files changed, 71 insertions(+)arch/arm/mm/proc-v7-bugs.c +19
-0@@ -1,9 +1,12 @@// 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> void cpu_v7_bugs_init (void );@@ -39,6 +42,9 @@ void cpu_v7_ca15_ibe(void)#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR void (*harden_branch_predictor)(void ); +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 );@@ -49,6 +55,18 @@ static void harden_branch_predictor_iciallu(void)write_sysreg (0 ,ICIALLU ); } +#ifdef CONFIG_ARM_PSCI +static void call_smc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_smc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} + +static void call_hvc_arch_workaround_1 (void ) +{ +arm_smccc_1_1_hvc (ARM_SMCCC_ARCH_WORKAROUND_1 ,NULL ); +} +#endif +void cpu_v7_bugs_init (void ) {const char *spectre_v2_method =NULL ;@@ -73,6 +91,38 @@ void cpu_v7_bugs_init(void) spectre_v2_method ="ICIALLU" ;break ; } +arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
But that's probably moot if you don't support BL systems.
Quoted 15 lines
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 117
Quoted 13 lines
arch/arm/mm/proc-v7-bugs.c +13
-0+ harden_branch_predictor = 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 ; + harden_branch_predictor = call_smc_arch_workaround_1; + processor.switch_mm = cpu_v7_smc_switch_mm; + spectre_v2_method ="firmware PSCI" ;My previous remark still stands: this is not really PSCI.
Quoted 2 lines
Sorry, no. Your comment was for the HVC call, not the SMC. You said nothing about this one.
My bad then. For all intents and purposes, they are the same thing, just serviced by a different exception level.
M.
Signature · 1 line
Jazz is not dead, it just smell funny.
Russell King - ARM Linux
maintainerRe: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
In reply to Marc ZyngierQuoted 12 lines · Marc Zyngier
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines · Russell King
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;
Quoted 7 lines
I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
Okay, so digging further into the documentation seems to suggest that we only need to check the firmware for A72 and A57 CPUs, and given this statement:
"Arm recommends that the caller only call this on PEs for which a
firmware based mitigation of CVE-2017-5715 is required, or where a local workaround is infeasible."
it seems that the right answer is to ignore the PSCI based methods when we have anything but these CPUs. Do you agree?
Quoted 1 line
But that's probably moot if you don't support BL systems.
Any bL systems with A72 or A57?
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Re: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
Quoted 25 lines · Russell King - ARM Linux
Quoted 12 lines · Marc Zyngier
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines · Russell King
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;Quoted 7 lines
I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
Okay, so digging further into the documentation seems to suggest that we only need to check the firmware for A72 and A57 CPUs, and given this statement:
Quoted 6 lines
"Arm recommends that the caller only call this on PEs for which a
firmware based mitigation of CVE-2017-5715 is required, or where a local workaround is infeasible."it seems that the right answer is to ignore the PSCI based methods when we have anything but these CPUs. Do you agree?
For CPUs that are produced by ARM, I agree. I don't know about CPUs produced by ARM licensees though, so I'd rather use the opposite logic:
Use the firmware unless the CPU is one of those that can be easily mitigated at EL1 (or isn't affected).
Quoted 3 lines
Quoted 1 line
But that's probably moot if you don't support BL systems.
Any bL systems with A72 or A57?
Juno is a canonical example of such a system (either 2xA57+4xA53, or 2xA72+4xA53), and there is plenty of partner's silicon in the wild.
Thanks,
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Russell King - ARM Linux
maintainerRe: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
Quoted 30 lines · Marc Zyngier
Quoted 29 lines · Russell King - ARM Linux
Quoted 12 lines · Marc Zyngier
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines · Russell King
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;Quoted 7 lines
I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
Okay, so digging further into the documentation seems to suggest that we only need to check the firmware for A72 and A57 CPUs, and given this statement:
"Arm recommends that the caller only call this on PEs for which a
firmware based mitigation of CVE-2017-5715 is required, or where a local workaround is infeasible."
Quoted 7 lines
Quoted 2 lines
it seems that the right answer is to ignore the PSCI based methods when we have anything but these CPUs. Do you agree?
For CPUs that are produced by ARM, I agree. I don't know about CPUs produced by ARM licensees though, so I'd rather use the opposite logic:
Use the firmware unless the CPU is one of those that can be easily mitigated at EL1 (or isn't affected).
The "or isn't affected" is the difficult bit - I guess we could match on the CPU vendor field though, and just reject all ARM CPUs that aren't explicitly listed as having a problem.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Re: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
Quoted 34 lines · Russell King - ARM Linux
Quoted 33 lines · Marc Zyngier
Quoted 31 lines · Russell King - ARM Linux
Quoted 12 lines · Marc Zyngier
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines · Russell King
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;Quoted 7 lines
I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
Okay, so digging further into the documentation seems to suggest that we only need to check the firmware for A72 and A57 CPUs, and given this statement:
"Arm recommends that the caller only call this on PEs for which a
firmware based mitigation of CVE-2017-5715 is required, or where a local workaround is infeasible."it seems that the right answer is to ignore the PSCI based methods when we have anything but these CPUs. Do you agree?
Quoted 8 lines
Quoted 4 lines
For CPUs that are produced by ARM, I agree. I don't know about CPUs produced by ARM licensees though, so I'd rather use the opposite logic:
Use the firmware unless the CPU is one of those that can be easily mitigated at EL1 (or isn't affected).The "or isn't affected" is the difficult bit - I guess we could match on the CPU vendor field though, and just reject all ARM CPUs that aren't explicitly listed as having a problem.
That seems sensible. ARM has published an exhaustive status for all its cores, which we can trust. For architecture licensees, I'm not aware of such a list, but I'd expect them to communicate one if they were affected.
Thanks,
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Russell King - ARM Linux
maintainerRe: [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
Quoted 40 lines · Marc Zyngier
Quoted 39 lines · Russell King - ARM Linux
Quoted 37 lines · Marc Zyngier
Quoted 25 lines · Russell King - ARM Linux
Quoted 12 lines · Marc Zyngier
arch/arm/mm/proc-v7-bugs.c void cpu_v7_bugs_init(void) · line 104
Quoted 10 lines · Russell King
arch/arm/mm/proc-v7-bugs.c +10
-0+#ifdef CONFIG_ARM_PSCI +if (psci_ops.smccc_version !=SMCCC_VERSION_1_0 ) { +struct arm_smccc_res res; + +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 ;Quoted 7 lines
I just realised that there is a small, but significant difference between this and the arm64 version: On arm64, we have a table of vulnerable implementations, and we try the mitigation on a per-cpu basis. Here, you entirely rely on the firmware to discover whether the CPU needs mitigation or not. You then need to check for a return value of 1, which indicates that although the mitigation is implemented, it is not required on this particular CPU.
Okay, so digging further into the documentation seems to suggest that we only need to check the firmware for A72 and A57 CPUs, and given this statement:
Quoted 6 lines
"Arm recommends that the caller only call this on PEs for which a
firmware based mitigation of CVE-2017-5715 is required, or where a local workaround is infeasible."it seems that the right answer is to ignore the PSCI based methods when we have anything but these CPUs. Do you agree?
For CPUs that are produced by ARM, I agree. I don't know about CPUs produced by ARM licensees though, so I'd rather use the opposite logic:
Use the firmware unless the CPU is one of those that can be easily mitigated at EL1 (or isn't affected).
Quoted 7 lines
Quoted 3 lines
The "or isn't affected" is the difficult bit - I guess we could match on the CPU vendor field though, and just reject all ARM CPUs that aren't explicitly listed as having a problem.
That seems sensible. ARM has published an exhaustive status for all its cores, which we can trust. For architecture licensees, I'm not aware of such a list, but I'd expect them to communicate one if they were affected.
It's not that simple - there's an exhaustive list for those affected cores, but it says that cores which aren't listed are unaffected.
If we want to explicitly list each core, we need a complete list of both affected and unaffected cores to ensure that none are missed.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
PATCH 10/14 ARM: KVM: invalidate BTB on guest exit for Cortex-A12/A17
In reply to Russell King - ARM LinuxFrom: Marc Zyngier <[email protected]>
In order to avoid aliasing attacks against the branch predictor, let's invalidate the BTB on guest exit. This is made complicated by the fact that we cannot take a branch before invalidating the BTB.
We only apply this to A12 and A17, which are the only two ARM cores on which this useful.
--- arch/arm/include/asm/kvm_asm.h | 2 -- arch/arm/include/asm/kvm_mmu.h | 17 +++++++++- arch/arm/kvm/hyp/hyp-entry.S | 71 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 5 deletions(-)
arch/arm/include/asm/kvm_asm.h +0 -2
@@ -61,8 +61,6 @@ struct kvm_vcpu;extern char __kvm_hyp_init[];extern char __kvm_hyp_init_end[]; -extern char __kvm_hyp_vector[]; -extern void __kvm_flush_vm_context (void );extern void __kvm_tlb_flush_vmid_ipa (struct kvm *kvm,phys_addr_t ipa);extern void __kvm_tlb_flush_vmid (struct kvm *kvm);
arch/arm/include/asm/kvm_mmu.h +16 -1
@@ -297,7 +297,22 @@ static inline unsigned int kvm_get_vmid_bits(void)static inline void *kvm_get_hyp_vector (void ) { -return kvm_ksym_ref (__kvm_hyp_vector); +switch (read_cpuid_part ()) { +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +case ARM_CPU_PART_CORTEX_A12 : +case ARM_CPU_PART_CORTEX_A17 : + { +extern char __kvm_hyp_vector_bp_inv[]; +return kvm_ksym_ref (__kvm_hyp_vector_bp_inv); + } + +#endif +default : + { +extern char __kvm_hyp_vector[]; +return kvm_ksym_ref (__kvm_hyp_vector); + } + } }static inline int kvm_map_vectors (void )
arch/arm/kvm/hyp/hyp-entry.S +69 -2
89 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 11/14 ARM: KVM: invalidate icache on guest exit for Cortex-A15
In reply to Russell King - ARM LinuxFrom: Marc Zyngier <[email protected]>
In order to avoid aliasing attacks against the branch predictor on Cortex-A15, let's invalidate the BTB on guest exit, which can only be done by invalidating the icache (with ACTLR[0] being set).
We use the same hack as for A12/A17 to perform the vector decoding.
--- arch/arm/include/asm/kvm_mmu.h | 5 +++++ arch/arm/kvm/hyp/hyp-entry.S | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+)
arch/arm/include/asm/kvm_mmu.h +5 -0
@@ -306,6 +306,11 @@ static inline void *kvm_get_hyp_vector(void) return kvm_ksym_ref(__kvm_hyp_vector_bp_inv); } +case ARM_CPU_PART_CORTEX_A15 : + { +extern char __kvm_hyp_vector_ic_inv[]; +return kvm_ksym_ref (__kvm_hyp_vector_ic_inv); + }#endif default : {
arch/arm/kvm/hyp/hyp-entry.S +24 -0
@@ -73,6 +73,28 @@ #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR .align 5 +__kvm_hyp_vector_ic_inv: + .global __kvm_hyp_vector_ic_inv + + /* + * We encode the exception entry in the bottom 3 bits of + * SP, and we have to guarantee to be 8 bytes aligned. + */ + W(add) sp, sp, #1 /* Reset 7 */ + W(add) sp, sp, #1 /* Undef 6 */ + W(add) sp, sp, #1 /* Syscall 5 */ + W(add) sp, sp, #1 /* Prefetch abort 4 */ + W(add) sp, sp, #1 /* Data abort 3 */ + W(add) sp, sp, #1 /* HVC 2 */ + W(add) sp, sp, #1 /* IRQ 1 */ + W(nop) /* FIQ 0 */ + + mcr p15, 0, r0, c7, c5, 0 /* ICIALLU */ + isb + + b decode_vectors + + .align 5 __kvm_hyp_vector_bp_inv: .global __kvm_hyp_vector_bp_inv
@@ -92,6 +114,8 @@ mcr p15, 0, r0, c7, c5, 6 /* BPIALL */ isb +decode_vectors: + #ifdef CONFIG_THUMB2_KERNEL /* * Yet another silly hack: Use VPIDR as a temp register.
Signature · 1 line
2.7.4
PATCH 12/14 ARM: spectre-v2: KVM: invalidate icache on guest exit for Brahma B15
In reply to Russell King - ARM LinuxInclude Brahma B15 in the Spectre v2 KVM workarounds.
--- arch/arm/include/asm/kvm_mmu.h | 1 + 1 file changed, 1 insertion(+)
arch/arm/include/asm/kvm_mmu.h +1 -0
@@ -306,6 +306,7 @@ static inline void *kvm_get_hyp_vector(void)return kvm_ksym_ref (__kvm_hyp_vector_bp_inv); } +case ARM_CPU_PART_BRAHMA_B15 :case ARM_CPU_PART_CORTEX_A15 : {extern char __kvm_hyp_vector_ic_inv[];
Signature · 1 line
2.7.4
Re: [PATCH 12/14] ARM: spectre-v2: KVM: invalidate icache on guest exit for Brahma B15
Quoted 3 lines · Russell King
Include Brahma B15 in the Spectre v2 KVM workarounds.
Signed-off-by Russell King <[email protected]>
Signature · 1 line
Florian
PATCH 13/14 ARM: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
In reply to Russell King - ARM LinuxWe want SMCCC_ARCH_WORKAROUND_1 to be fast. As fast as possible. So let's intercept it as early as we can by testing for the function call number as soon as we've identified a HVC call coming from the guest.
--- arch/arm/kvm/hyp/hyp-entry.S | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
arch/arm/kvm/hyp/hyp-entry.S +12 -1
@@ -16,6 +16,7 @@ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <linux/arm-smccc.h> #include <linux/linkage.h> #include <asm/kvm_arm.h> #include <asm/kvm_asm.h>
@@ -202,7 +203,7 @@ ENDPROC(__hyp_do_panic) lsr r2, r2, #16 and r2, r2, #0xff cmp r2, #0 - bne guest_trap @ Guest called HVC + bne guest_hvc_trap @ Guest called HVC /* * Getting here means host called HVC, we shift parameters and branch
@@ -253,6 +254,16 @@ THUMB( orr lr, #1) pop {r2, lr} eret +guest_hvc_trap: + movw ip, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1 + movt ip, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1 + ldr r0, [sp] @ Guest's r0 + teq r0, ip + bne guest_trap + pop {r0, r1, r2} + mov r0, #0 + eret + guest_trap: load_vcpu r0 @ Load VCPU pointer to r0
Signature · 1 line
2.7.4
Re: [PATCH 13/14] ARM: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
Quoted 32 lines · Russell King
We want
SMCCC_ARCH_WORKAROUND_1to be fast. As fast as possible. So let's intercept it as early as we can by testing for the function call number as soon as we've identified a HVC call coming from the guest.Signed-off-by Russell King <[email protected]>--- arch/arm/kvm/hyp/hyp-entry.S | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)arch/arm/kvm/hyp/hyp-entry.S +2
-1@@ -16,6 +16,7 @@ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <linux/arm-smccc.h> #include <linux/linkage.h> #include <asm/kvm_arm.h> #include <asm/kvm_asm.h>@@ -202,7 +203,7 @@ ENDPROC(__hyp_do_panic) lsr r2, r2, #16 and r2, r2, #0xff cmp r2, #0 - bne guest_trap @ Guest called HVC + bne guest_hvc_trap @ Guest called HVC /* * Getting here means host called HVC, we shift parameters and branch
arch/arm/kvm/hyp/hyp-entry.S THUMB( orr lr, #1) · line 259
Quoted 6 lines
arch/arm/kvm/hyp/hyp-entry.S +3
-0@@ -253,6 +254,16 @@ THUMB( orr lr, #1) pop {r2, lr} eret +guest_hvc_trap: + movw ip, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1 + movt ip, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1
r12 is a live guest register, and only r0-r2 are saved at that stage. You could additionally corrupt r3 though, once you've identified that you're in the context of an SMCCC 1.1 call.
You should be able to replace r12 with r2.
arch/arm/kvm/hyp/hyp-entry.S THUMB( orr lr, #1) · line 263
Quoted 4 lines
arch/arm/kvm/hyp/hyp-entry.S +4
-0+ ldr r0, [sp] @ Guest's r0 + teq r0, ip + bne guest_trap + pop {r0, r1, r2}
You could replace this slightly more efficient
add sp, sp, #12
since we don't need to restore those registers to the guest. r2 would be left containing ARM_SMCCC_ARCH_WORKAROUND_1 (harmless), and r1 has the HSR value (perfectly predictable).
arch/arm/kvm/hyp/hyp-entry.S THUMB( orr lr, #1) · line 269
Quoted 7 lines
arch/arm/kvm/hyp/hyp-entry.S +3
-0+ mov r0, #0 + eret + guest_trap: load_vcpu r0 @ Load VCPU pointer to r0
Thanks,
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
PATCH 14/14 ARM: KVM: report support for SMCCC_ARCH_WORKAROUND_1
In reply to Russell King - ARM LinuxReport support for SMCCC_ARCH_WORKAROUND_1 to KVM guests for affected CPUs.
--- arch/arm/include/asm/kvm_host.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
arch/arm/include/asm/kvm_host.h +12 -2
@@ -21,6 +21,7 @@#include <linux/types.h> #include <linux/kvm_types.h> +#include <asm/cputype.h> #include <asm/kvm.h> #include <asm/kvm_asm.h> #include <asm/kvm_mmio.h>
@@ -311,8 +312,17 @@ static inline void kvm_arm_vhe_guest_exit(void) {}static inline bool kvm_arm_harden_branch_predictor (void ) { -/* No way to detect it yet, pretend it is not there. */ -return false; +switch (read_cpuid_part ()) { +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +case ARM_CPU_PART_BRAHMA_B15 : +case ARM_CPU_PART_CORTEX_A12 : +case ARM_CPU_PART_CORTEX_A15 : +case ARM_CPU_PART_CORTEX_A17 : +return true; +#endif +default : +return false; + } }#endif /* __ARM_KVM_HOST_H__ */
Signature · 1 line
2.7.4
Quoted 20 lines · Russell King - ARM Linux
This is the second posting - the original cover note is below. Comments from previous series addresesd:
- Drop R7 and R8 changes.
- Remove "PSCI" from the hypervisor version of the workaround.arch/arm/include/asm/bugs.h | 6 +- arch/arm/include/asm/cp15.h | 3 + arch/arm/include/asm/cputype.h | 5 ++ arch/arm/include/asm/kvm_asm.h | 2 - arch/arm/include/asm/kvm_host.h | 14 +++- arch/arm/include/asm/kvm_mmu.h | 23 +++++- arch/arm/include/asm/proc-fns.h | 4 + arch/arm/include/asm/system_misc.h | 8 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/bugs.c | 18 +++++ arch/arm/kernel/smp.c | 4 + arch/arm/kernel/suspend.c | 2 + arch/arm/kvm/hyp/hyp-entry.S | 108 +++++++++++++++++++++++++- arch/arm/mm/Kconfig | 23 ++++++ arch/arm/mm/Makefile | 2 +-
Quoted 8 lines
arch/arm/mm/fault.c | 3 + arch/arm/mm/proc-macros.S | 3 +- arch/arm/mm/proc-v7-2level.S | 6 -- arch/arm/mm/proc-v7-bugs.c | 130 +++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 154 +++++++++++++++++++++++++++++-------- 20 files changed, 469 insertions(+), 50 deletions(-) create mode 100644 arch/arm/kernel/bugs.c create mode 100644 arch/arm/mm/proc-v7-bugs.c
Since there appears to be more work needed in the PSCI/KVM changes (patches 9 through 14), how about we go with the "bare-metal" parts:
patches 1-8 first and try to get those included ASAP?
The rationale being that a lot of affected people have Linux running on ARMv7-A Cortex-A, typically A9, A15, Brahma-B15, and are in need of those patches but do not necessarily require KVM fixes right now, and even less so PSCI infrastructure to mitigate ARMv8-A running in AArch32.
In terms of backporting to -stable, and because the spectre variant 1 patches have not been submitted yet, it is not like we can lump everything in one go anyway, so we are not making the lives of the -stable maintainers any worse than it currently is?
Yay or nay?
Quoted 74 lines · Russell King - ARM Linux
Quoted 71 lines
This series addresses the Spectre variant 2 issues on ARM Cortex and Broadcom Brahma B15 CPUs. Due to the complexity of the bug, it is not possible to verify that this series fixes any of the bugs, since it has not been able to reproduce these exact scenarios using test programs.
I believe that this covers the entire extent of the Spectre variant 2 issues, with the exception of Cortex A53 and Cortex A72 processors as these require a substantially more complex solution (except where the workaround is implemented in PSCI firmware.)
Spectre variant 1 is not covered by this series.
The patch series is based partly on Marc Zyngier's work from February - two of the KVM patches are from Marc's work.
The main differences are:
- Inclusion of more processors as per current ARM Ltd security update documentation.
- Extension of "bugs" infrastructure to detect Cortex A8 and Cortex A15 CPUs missing out on the IBE bit being set on (re-)entry to the kernel through all paths.
- Handle all suspect userspace-touching-kernelspace aborts irrespective of mapping type.The first patch will trivially conflict with the Broadcom Brahma updates already in arm-soc - it has been necessary to independently add the ID definitions for the B15 CPU.
Having worked through this series, I'm of the opinion that the
define_processor_functionsmacro in proc-v7 are probably more hassle than they're worth - here, we don't need the global equivalent symbols, because we never refer to them from the kernel code for any V7 processor (MULTI_CPUis always defined.)This series is currently in my "spectre" branch (along with some Spectre variant 1 patches.)
Please carefully review.
arch/arm/include/asm/bugs.h | 6 +- arch/arm/include/asm/cp15.h | 3 + arch/arm/include/asm/cputype.h | 5 ++ arch/arm/include/asm/kvm_asm.h | 2 - arch/arm/include/asm/kvm_host.h | 14 +++- arch/arm/include/asm/kvm_mmu.h | 23 +++++- arch/arm/include/asm/proc-fns.h | 4 + arch/arm/include/asm/system_misc.h | 8 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/bugs.c | 18 +++++ arch/arm/kernel/smp.c | 4 + arch/arm/kernel/suspend.c | 2 + arch/arm/kvm/hyp/hyp-entry.S | 108 ++++++++++++++++++++++++- arch/arm/mm/Kconfig | 23 ++++++ arch/arm/mm/Makefile | 2 +- arch/arm/mm/fault.c | 3 + arch/arm/mm/proc-macros.S | 3 +- arch/arm/mm/proc-v7-2level.S | 6 -- arch/arm/mm/proc-v7-bugs.c | 130 ++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 158 +++++++++++++++++++++++++++++-------- 20 files changed, 471 insertions(+), 52 deletions(-)Signature · 8 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 1 line
Florian
Russell King - ARM Linux
maintainerQuoted 39 lines · Florian Fainelli
Quoted 20 lines · Russell King - ARM Linux
This is the second posting - the original cover note is below. Comments from previous series addresesd:
- Drop R7 and R8 changes.
- Remove "PSCI" from the hypervisor version of the workaround.arch/arm/include/asm/bugs.h | 6 +- arch/arm/include/asm/cp15.h | 3 + arch/arm/include/asm/cputype.h | 5 ++ arch/arm/include/asm/kvm_asm.h | 2 - arch/arm/include/asm/kvm_host.h | 14 +++- arch/arm/include/asm/kvm_mmu.h | 23 +++++- arch/arm/include/asm/proc-fns.h | 4 + arch/arm/include/asm/system_misc.h | 8 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/bugs.c | 18 +++++ arch/arm/kernel/smp.c | 4 + arch/arm/kernel/suspend.c | 2 + arch/arm/kvm/hyp/hyp-entry.S | 108 +++++++++++++++++++++++++- arch/arm/mm/Kconfig | 23 ++++++ arch/arm/mm/Makefile | 2 +-Quoted 8 lines
arch/arm/mm/fault.c | 3 + arch/arm/mm/proc-macros.S | 3 +- arch/arm/mm/proc-v7-2level.S | 6 -- arch/arm/mm/proc-v7-bugs.c | 130 +++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7.S | 154 +++++++++++++++++++++++++++++-------- 20 files changed, 469 insertions(+), 50 deletions(-) create mode 100644 arch/arm/kernel/bugs.c create mode 100644 arch/arm/mm/proc-v7-bugs.cSince there appears to be more work needed in the PSCI/KVM changes (patches 9 through 14), how about we go with the "bare-metal" parts:
patches 1-8 first and try to get those included ASAP?The rationale being that a lot of affected people have Linux running on ARMv7-A Cortex-A, typically A9, A15, Brahma-B15, and are in need of those patches but do not necessarily require KVM fixes right now, and even less so PSCI infrastructure to mitigate ARMv8-A running in AArch32.
Quoted 4 lines
In terms of backporting to -stable, and because the spectre variant 1 patches have not been submitted yet, it is not like we can lump everything in one go anyway, so we are not making the lives of the -stable maintainers any worse than it currently is?
Patch 6 is implicated in the rework - it will cause big.Little systems to either have the workaround applied when it isn't required or not applied when it is required. It depends which CPU is the boot CPU.
For example, a big.Little A7/A15 cluster - if the boot CPU is an A15, then we will use the ICIALLI switch_mm method for both the A15 and A7. If the boot CPU is an A7, then we will use the standard switch_mm method that does not contain the workaround even for the A15, and the A15 will then be vulnerable.
I don't think we have a way to identify if we boot on a big.Little system, so the kernel messages could claim to have the workarounds, but they won't be effective.
This is the hardest one to solve, because it means more invasive changes to deal with the MM switching paths, which need to become per-cpu. The problem is, there are times that we call into that path but the per-cpu variables are not accessible (because the CPU isn't initialised sufficiently for them to work.)
It's trivial to solve the issues in the later patches by comparison.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up