Skip to content

Commit 9013fd4

Browse files
James Morsegregkh
James Morse
authored andcommitted
arm64: Mitigate spectre style branch history side channels
commit 558c303 upstream. Speculation attacks against some high-performance processors can make use of branch history to influence future speculation. When taking an exception from user-space, a sequence of branches or a firmware call overwrites or invalidates the branch history. The sequence of branches is added to the vectors, and should appear before the first indirect branch. For systems using KPTI the sequence is added to the kpti trampoline where it has a free register as the exit from the trampoline is via a 'ret'. For systems not using KPTI, the same register tricks are used to free up a register in the vectors. For the firmware call, arch-workaround-3 clobbers 4 registers, so there is no choice but to save them to the EL1 stack. This only happens for entry from EL0, so if we take an exception due to the stack access, it will not become re-entrant. For KVM, the existing branch-predictor-hardening vectors are used. When a spectre version of these vectors is in use, the firmware call is sufficient to mitigate against Spectre-BHB. For the non-spectre versions, the sequence of branches is added to the indirect vector. Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Cc: <stable@kernel.org> # <v5.17.x 72bb9dc arm64: Add Cortex-X2 CPU part definition Cc: <stable@kernel.org> # <v5.16.x 2d0d656 arm64: Add Neoverse-N2, Cortex-A710 CPU part definition Cc: <stable@kernel.org> # <v5.10.x 8a6b88e arm64: Add part number for Arm Cortex-A77 [ modified for stable, moved code to cpu_errata.c removed bitmap of mitigations, use kvm template infrastructure ] Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 26129ea commit 9013fd4

File tree

8 files changed

+316
-4
lines changed

8 files changed

+316
-4
lines changed

Diff for: arch/arm64/Kconfig

+9
Original file line numberDiff line numberDiff line change
@@ -1139,6 +1139,15 @@ config ARM64_SSBD
11391139

11401140
If unsure, say Y.
11411141

1142+
config MITIGATE_SPECTRE_BRANCH_HISTORY
1143+
bool "Mitigate Spectre style attacks against branch history" if EXPERT
1144+
default y
1145+
help
1146+
Speculation attacks against some high-performance processors can
1147+
make use of branch history to influence future speculation.
1148+
When taking an exception from user-space, a sequence of branches
1149+
or a firmware call overwrites the branch history.
1150+
11421151
config RODATA_FULL_DEFAULT_ENABLED
11431152
bool "Apply r/o permissions of VM areas also to their linear aliases"
11441153
default y

Diff for: arch/arm64/include/asm/assembler.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,9 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
759759

760760
.macro __mitigate_spectre_bhb_loop tmp
761761
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
762-
mov \tmp, #32
762+
alternative_cb spectre_bhb_patch_loop_iter
763+
mov \tmp, #32 // Patched to correct the immediate
764+
alternative_cb_end
763765
.Lspectre_bhb_loop\@:
764766
b . + 4
765767
subs \tmp, \tmp, #1
@@ -774,7 +776,7 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
774776
stp x0, x1, [sp, #-16]!
775777
stp x2, x3, [sp, #-16]!
776778
mov w0, #ARM_SMCCC_ARCH_WORKAROUND_3
777-
alternative_cb smccc_patch_fw_mitigation_conduit
779+
alternative_cb arm64_update_smccc_conduit
778780
nop // Patched to SMC/HVC #0
779781
alternative_cb_end
780782
ldp x2, x3, [sp], #16

Diff for: arch/arm64/include/asm/cpufeature.h

+18
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,21 @@ static inline bool cpu_supports_mixed_endian_el0(void)
508508
return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
509509
}
510510

511+
static inline bool supports_csv2p3(int scope)
512+
{
513+
u64 pfr0;
514+
u8 csv2_val;
515+
516+
if (scope == SCOPE_LOCAL_CPU)
517+
pfr0 = read_sysreg_s(SYS_ID_AA64PFR0_EL1);
518+
else
519+
pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
520+
521+
csv2_val = cpuid_feature_extract_unsigned_field(pfr0,
522+
ID_AA64PFR0_CSV2_SHIFT);
523+
return csv2_val == 3;
524+
}
525+
511526
static inline bool system_supports_32bit_el0(void)
512527
{
513528
return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);
@@ -647,6 +662,9 @@ enum mitigation_state {
647662
};
648663

649664
enum mitigation_state arm64_get_spectre_bhb_state(void);
665+
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
666+
u8 spectre_bhb_loop_affected(int scope);
667+
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
650668

651669
extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
652670

Diff for: arch/arm64/include/asm/cputype.h

+8
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,13 @@
7272
#define ARM_CPU_PART_CORTEX_A76 0xD0B
7373
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
7474
#define ARM_CPU_PART_CORTEX_A77 0xD0D
75+
#define ARM_CPU_PART_NEOVERSE_V1 0xD40
76+
#define ARM_CPU_PART_CORTEX_A78 0xD41
77+
#define ARM_CPU_PART_CORTEX_X1 0xD44
7578
#define ARM_CPU_PART_CORTEX_A710 0xD47
7679
#define ARM_CPU_PART_CORTEX_X2 0xD48
7780
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
81+
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
7882

7983
#define APM_CPU_PART_POTENZA 0x000
8084

@@ -107,9 +111,13 @@
107111
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
108112
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
109113
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
114+
#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
115+
#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
116+
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
110117
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
111118
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
112119
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
120+
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
113121
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
114122
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
115123
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)

Diff for: arch/arm64/include/asm/sysreg.h

+1
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@
661661
#endif
662662

663663
/* id_aa64mmfr1 */
664+
#define ID_AA64MMFR1_ECBHB_SHIFT 60
664665
#define ID_AA64MMFR1_PAN_SHIFT 20
665666
#define ID_AA64MMFR1_LOR_SHIFT 16
666667
#define ID_AA64MMFR1_HPD_SHIFT 12

Diff for: arch/arm64/include/asm/vectors.h

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ enum arm64_bp_harden_el1_vectors {
4040
EL1_VECTOR_KPTI,
4141
};
4242

43+
#ifndef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
44+
#define EL1_VECTOR_BHB_LOOP -1
45+
#define EL1_VECTOR_BHB_FW -1
46+
#endif /* !CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
47+
4348
/* The vectors to use on return from EL0. e.g. to remap the kernel */
4449
DECLARE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector);
4550

0 commit comments

Comments
 (0)