Skip to content

Commit 551717c

Browse files
James Morsegregkh
authored andcommitted
arm64: Use the clearbhb instruction in mitigations
commit 228a26b upstream. Future CPUs may implement a clearbhb instruction that is sufficient to mitigate SpectreBHB. CPUs that implement this instruction, but not CSV2.3 must be affected by Spectre-BHB. Add support to use this instruction as the BHB mitigation on CPUs that support it. The instruction is in the hint space, so it will be treated by a NOP as older CPUs. Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> [ modified for stable: Use a KVM vector template instead of alternatives, removed bitmap of mitigations ] Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 38c26bd commit 551717c

10 files changed

Lines changed: 61 additions & 0 deletions

File tree

arch/arm64/include/asm/assembler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@
9797
hint #20
9898
.endm
9999

100+
/*
101+
* Clear Branch History instruction
102+
*/
103+
.macro clearbhb
104+
hint #22
105+
.endm
106+
100107
/*
101108
* Speculation barrier
102109
*/

arch/arm64/include/asm/cpufeature.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,19 @@ static inline bool supports_csv2p3(int scope)
621621
return csv2_val == 3;
622622
}
623623

624+
static inline bool supports_clearbhb(int scope)
625+
{
626+
u64 isar2;
627+
628+
if (scope == SCOPE_LOCAL_CPU)
629+
isar2 = read_sysreg_s(SYS_ID_AA64ISAR2_EL1);
630+
else
631+
isar2 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1);
632+
633+
return cpuid_feature_extract_unsigned_field(isar2,
634+
ID_AA64ISAR2_CLEARBHB_SHIFT);
635+
}
636+
624637
static inline bool system_supports_32bit_el0(void)
625638
{
626639
return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);

arch/arm64/include/asm/insn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ enum aarch64_insn_hint_cr_op {
6565
AARCH64_INSN_HINT_PSB = 0x11 << 5,
6666
AARCH64_INSN_HINT_TSB = 0x12 << 5,
6767
AARCH64_INSN_HINT_CSDB = 0x14 << 5,
68+
AARCH64_INSN_HINT_CLEARBHB = 0x16 << 5,
6869

6970
AARCH64_INSN_HINT_BTI = 0x20 << 5,
7071
AARCH64_INSN_HINT_BTIC = 0x22 << 5,

arch/arm64/include/asm/kvm_asm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define __SMCCC_WORKAROUND_1_SMC_SZ 36
3838
#define __SMCCC_WORKAROUND_3_SMC_SZ 36
3939
#define __SPECTRE_BHB_LOOP_SZ 44
40+
#define __SPECTRE_BHB_CLEARBHB_SZ 12
4041

4142
#define KVM_HOST_SMCCC_ID(id) \
4243
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
@@ -205,6 +206,7 @@ extern char __smccc_workaround_3_smc[__SMCCC_WORKAROUND_3_SMC_SZ];
205206
extern char __spectre_bhb_loop_k8[__SPECTRE_BHB_LOOP_SZ];
206207
extern char __spectre_bhb_loop_k24[__SPECTRE_BHB_LOOP_SZ];
207208
extern char __spectre_bhb_loop_k32[__SPECTRE_BHB_LOOP_SZ];
209+
extern char __spectre_bhb_clearbhb[__SPECTRE_BHB_LOOP_SZ];
208210

209211
/*
210212
* Obtain the PC-relative address of a kernel symbol

arch/arm64/include/asm/sysreg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@
689689
#define ID_AA64ISAR1_GPI_IMP_DEF 0x1
690690

691691
/* id_aa64isar2 */
692+
#define ID_AA64ISAR2_CLEARBHB_SHIFT 28
692693
#define ID_AA64ISAR2_RPRES_SHIFT 4
693694
#define ID_AA64ISAR2_WFXT_SHIFT 0
694695

arch/arm64/include/asm/vectors.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ enum arm64_bp_harden_el1_vectors {
3232
* canonical vectors.
3333
*/
3434
EL1_VECTOR_BHB_FW,
35+
36+
/*
37+
* Use the ClearBHB instruction, before branching to the canonical
38+
* vectors.
39+
*/
40+
EL1_VECTOR_BHB_CLEAR_INSN,
3541
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
3642

3743
/*
@@ -43,6 +49,7 @@ enum arm64_bp_harden_el1_vectors {
4349
#ifndef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
4450
#define EL1_VECTOR_BHB_LOOP -1
4551
#define EL1_VECTOR_BHB_FW -1
52+
#define EL1_VECTOR_BHB_CLEAR_INSN -1
4653
#endif /* !CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
4754

4855
/* The vectors to use on return from EL0. e.g. to remap the kernel */

arch/arm64/kernel/cpufeature.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
211211
};
212212

213213
static const struct arm64_ftr_bits ftr_id_aa64isar2[] = {
214+
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_CLEARBHB_SHIFT, 4, 0),
214215
ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_RPRES_SHIFT, 4, 0),
215216
ARM64_FTR_END,
216217
};

arch/arm64/kernel/entry.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ alternative_else_nop_endif
827827
#define BHB_MITIGATION_NONE 0
828828
#define BHB_MITIGATION_LOOP 1
829829
#define BHB_MITIGATION_FW 2
830+
#define BHB_MITIGATION_INSN 3
830831

831832
.macro tramp_ventry, vector_start, regsize, kpti, bhb
832833
.align 7
@@ -843,6 +844,11 @@ alternative_else_nop_endif
843844
__mitigate_spectre_bhb_loop x30
844845
.endif // \bhb == BHB_MITIGATION_LOOP
845846

847+
.if \bhb == BHB_MITIGATION_INSN
848+
clearbhb
849+
isb
850+
.endif // \bhb == BHB_MITIGATION_INSN
851+
846852
.if \kpti == 1
847853
/*
848854
* Defend against branch aliasing attacks by pushing a dummy
@@ -919,6 +925,7 @@ SYM_CODE_START_NOALIGN(tramp_vectors)
919925
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
920926
generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_LOOP
921927
generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_FW
928+
generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_INSN
922929
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
923930
generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_NONE
924931
SYM_CODE_END(tramp_vectors)
@@ -981,6 +988,7 @@ SYM_CODE_START(__bp_harden_el1_vectors)
981988
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
982989
generate_el1_vector bhb=BHB_MITIGATION_LOOP
983990
generate_el1_vector bhb=BHB_MITIGATION_FW
991+
generate_el1_vector bhb=BHB_MITIGATION_INSN
984992
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
985993
SYM_CODE_END(__bp_harden_el1_vectors)
986994
.popsection

arch/arm64/kernel/proton-pack.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,7 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
824824
* - Mitigated by a branchy loop a CPU specific number of times, and listed
825825
* in our "loop mitigated list".
826826
* - Mitigated in software by the firmware Spectre v2 call.
827+
* - Has the ClearBHB instruction to perform the mitigation.
827828
* - Has the 'Exception Clears Branch History Buffer' (ECBHB) feature, so no
828829
* software mitigation in the vectors is needed.
829830
* - Has CSV2.3, so is unaffected.
@@ -949,6 +950,9 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
949950
if (supports_csv2p3(scope))
950951
return false;
951952

953+
if (supports_clearbhb(scope))
954+
return true;
955+
952956
if (spectre_bhb_loop_affected(scope))
953957
return true;
954958

@@ -987,6 +991,8 @@ static int kvm_bhb_get_vecs_size(const char *start)
987991
start == __spectre_bhb_loop_k24 ||
988992
start == __spectre_bhb_loop_k32)
989993
return __SPECTRE_BHB_LOOP_SZ;
994+
else if (start == __spectre_bhb_clearbhb)
995+
return __SPECTRE_BHB_CLEARBHB_SZ;
990996

991997
return 0;
992998
}
@@ -1027,6 +1033,7 @@ static void kvm_setup_bhb_slot(const char *hyp_vecs_start)
10271033
#define __spectre_bhb_loop_k8 NULL
10281034
#define __spectre_bhb_loop_k24 NULL
10291035
#define __spectre_bhb_loop_k32 NULL
1036+
#define __spectre_bhb_clearbhb NULL
10301037

10311038
static void kvm_setup_bhb_slot(const char *hyp_vecs_start) { }
10321039
#endif /* CONFIG_KVM */
@@ -1045,6 +1052,11 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
10451052
} else if (cpu_mitigations_off()) {
10461053
pr_info_once("spectre-bhb mitigation disabled by command line option\n");
10471054
} else if (supports_ecbhb(SCOPE_LOCAL_CPU)) {
1055+
state = SPECTRE_MITIGATED;
1056+
} else if (supports_clearbhb(SCOPE_LOCAL_CPU)) {
1057+
kvm_setup_bhb_slot(__spectre_bhb_clearbhb);
1058+
this_cpu_set_vectors(EL1_VECTOR_BHB_CLEAR_INSN);
1059+
10481060
state = SPECTRE_MITIGATED;
10491061
} else if (spectre_bhb_loop_affected(SCOPE_LOCAL_CPU)) {
10501062
switch (spectre_bhb_loop_affected(SCOPE_SYSTEM)) {

arch/arm64/kvm/hyp/smccc_wa.S

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,12 @@ SYM_DATA_START(__spectre_bhb_loop_k32)
9696
1: .org __spectre_bhb_loop_k32 + __SPECTRE_BHB_LOOP_SZ
9797
.org 1b
9898
SYM_DATA_END(__spectre_bhb_loop_k32)
99+
100+
.global __spectre_bhb_clearbhb
101+
SYM_DATA_START(__spectre_bhb_clearbhb)
102+
esb
103+
clearbhb
104+
isb
105+
1: .org __spectre_bhb_clearbhb + __SPECTRE_BHB_CLEARBHB_SZ
106+
.org 1b
107+
SYM_DATA_END(__spectre_bhb_clearbhb)

0 commit comments

Comments
 (0)