Skip to content

Commit ba26892

Browse files
author
James Morse
committed
arm64: entry: Add vectors that have the bhb mitigation sequences
Some CPUs affected by Spectre-BHB need a sequence of branches, or a firmware call to be run before any indirect branch. This needs to go in the vectors. No CPU needs both. While this can be patched in, it would run on all CPUs as there is a single set of vectors. If only one part of a big/little combination is affected, the unaffected CPUs have to run the mitigation too. Create extra vectors that include the sequence. Subsequent patches will allow affected CPUs to select this set of vectors. Later patches will modify the loop count to match what the CPU requires. Reviewed-by: Catalin Marinas <[email protected]> Signed-off-by: James Morse <[email protected]>
1 parent aff6539 commit ba26892

File tree

5 files changed

+123
-9
lines changed

5 files changed

+123
-9
lines changed

arch/arm64/include/asm/assembler.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,4 +850,28 @@ alternative_endif
850850

851851
#endif /* GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT */
852852

853+
.macro __mitigate_spectre_bhb_loop tmp
854+
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
855+
mov \tmp, #32
856+
.Lspectre_bhb_loop\@:
857+
b . + 4
858+
subs \tmp, \tmp, #1
859+
b.ne .Lspectre_bhb_loop\@
860+
sb
861+
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
862+
.endm
863+
864+
/* Save/restores x0-x3 to the stack */
865+
.macro __mitigate_spectre_bhb_fw
866+
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
867+
stp x0, x1, [sp, #-16]!
868+
stp x2, x3, [sp, #-16]!
869+
mov w0, #ARM_SMCCC_ARCH_WORKAROUND_3
870+
alternative_cb smccc_patch_fw_mitigation_conduit
871+
nop // Patched to SMC/HVC #0
872+
alternative_cb_end
873+
ldp x2, x3, [sp], #16
874+
ldp x0, x1, [sp], #16
875+
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
876+
.endm
853877
#endif /* __ASM_ASSEMBLER_H */

arch/arm64/include/asm/vectors.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2022 ARM Ltd.
4+
*/
5+
#ifndef __ASM_VECTORS_H
6+
#define __ASM_VECTORS_H
7+
8+
/*
9+
* Note: the order of this enum corresponds to two arrays in entry.S:
10+
* tramp_vecs and __bp_harden_el1_vectors. By default the canonical
11+
* 'full fat' vectors are used directly.
12+
*/
13+
enum arm64_bp_harden_el1_vectors {
14+
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
15+
/*
16+
* Perform the BHB loop mitigation, before branching to the canonical
17+
* vectors.
18+
*/
19+
EL1_VECTOR_BHB_LOOP,
20+
21+
/*
22+
* Make the SMC call for firmware mitigation, before branching to the
23+
* canonical vectors.
24+
*/
25+
EL1_VECTOR_BHB_FW,
26+
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
27+
28+
/*
29+
* Remap the kernel before branching to the canonical vectors.
30+
*/
31+
EL1_VECTOR_KPTI,
32+
+};
33+
34+
#endif /* __ASM_VECTORS_H */

arch/arm64/kernel/entry.S

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -646,13 +646,26 @@ alternative_else_nop_endif
646646
sub \dst, \dst, PAGE_SIZE
647647
.endm
648648

649-
.macro tramp_ventry, vector_start, regsize, kpti
649+
650+
#define BHB_MITIGATION_NONE 0
651+
#define BHB_MITIGATION_LOOP 1
652+
#define BHB_MITIGATION_FW 2
653+
654+
.macro tramp_ventry, vector_start, regsize, kpti, bhb
650655
.align 7
651656
1:
652657
.if \regsize == 64
653658
msr tpidrro_el0, x30 // Restored in kernel_ventry
654659
.endif
655660

661+
.if \bhb == BHB_MITIGATION_LOOP
662+
/*
663+
* This sequence must appear before the first indirect branch. i.e. the
664+
* ret out of tramp_ventry. It appears here because x30 is free.
665+
*/
666+
__mitigate_spectre_bhb_loop x30
667+
.endif // \bhb == BHB_MITIGATION_LOOP
668+
656669
.if \kpti == 1
657670
/*
658671
* Defend against branch aliasing attacks by pushing a dummy
@@ -680,13 +693,25 @@ alternative_else_nop_endif
680693
ldr x30, =vectors
681694
.endif // \kpti == 1
682695

696+
.if \bhb == BHB_MITIGATION_FW
697+
/*
698+
* The firmware sequence must appear before the first indirect branch.
699+
* i.e. the ret out of tramp_ventry. But it also needs the stack to be
700+
* mapped to save/restore the registers the SMC clobbers.
701+
*/
702+
__mitigate_spectre_bhb_fw
703+
.endif // \bhb == BHB_MITIGATION_FW
704+
683705
add x30, x30, #(1b - \vector_start + 4)
684706
ret
685707
.org 1b + 128 // Did we overflow the ventry slot?
686708
.endm
687709

688710
.macro tramp_exit, regsize = 64
689711
adr x30, tramp_vectors
712+
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
713+
add x30, x30, SZ_4K
714+
#endif
690715
msr vbar_el1, x30
691716
ldr lr, [sp, #S_LR]
692717
tramp_unmap_kernel x29
@@ -698,26 +723,32 @@ alternative_else_nop_endif
698723
sb
699724
.endm
700725

701-
.macro generate_tramp_vector, kpti
726+
.macro generate_tramp_vector, kpti, bhb
702727
.Lvector_start\@:
703728
.space 0x400
704729

705730
.rept 4
706-
tramp_ventry .Lvector_start\@, 64, \kpti
731+
tramp_ventry .Lvector_start\@, 64, \kpti, \bhb
707732
.endr
708733
.rept 4
709-
tramp_ventry .Lvector_start\@, 32, \kpti
734+
tramp_ventry .Lvector_start\@, 32, \kpti, \bhb
710735
.endr
711736
.endm
712737

713738
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
714739
/*
715740
* Exception vectors trampoline.
741+
* The order must match __bp_harden_el1_vectors and the
742+
* arm64_bp_harden_el1_vectors enum.
716743
*/
717744
.pushsection ".entry.tramp.text", "ax"
718745
.align 11
719746
SYM_CODE_START_NOALIGN(tramp_vectors)
720-
generate_tramp_vector kpti=1
747+
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
748+
generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_LOOP
749+
generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_FW
750+
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
751+
generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_NONE
721752
SYM_CODE_END(tramp_vectors)
722753

723754
SYM_CODE_START(tramp_exit_native)
@@ -744,7 +775,7 @@ SYM_DATA_END(__entry_tramp_data_start)
744775
* Exception vectors for spectre mitigations on entry from EL1 when
745776
* kpti is not in use.
746777
*/
747-
.macro generate_el1_vector
778+
.macro generate_el1_vector, bhb
748779
.Lvector_start\@:
749780
kernel_ventry 1, t, 64, sync // Synchronous EL1t
750781
kernel_ventry 1, t, 64, irq // IRQ EL1t
@@ -757,17 +788,21 @@ SYM_DATA_END(__entry_tramp_data_start)
757788
kernel_ventry 1, h, 64, error // Error EL1h
758789

759790
.rept 4
760-
tramp_ventry .Lvector_start\@, 64, kpti=0
791+
tramp_ventry .Lvector_start\@, 64, 0, \bhb
761792
.endr
762793
.rept 4
763-
tramp_ventry .Lvector_start\@, 32, kpti=0
794+
tramp_ventry .Lvector_start\@, 32, 0, \bhb
764795
.endr
765796
.endm
766797

798+
/* The order must match tramp_vecs and the arm64_bp_harden_el1_vectors enum. */
767799
.pushsection ".entry.text", "ax"
768800
.align 11
769801
SYM_CODE_START(__bp_harden_el1_vectors)
770-
generate_el1_vector
802+
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
803+
generate_el1_vector bhb=BHB_MITIGATION_LOOP
804+
generate_el1_vector bhb=BHB_MITIGATION_FW
805+
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
771806
SYM_CODE_END(__bp_harden_el1_vectors)
772807
.popsection
773808

arch/arm64/kernel/proton-pack.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,3 +770,19 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
770770
return -ENODEV;
771771
}
772772
}
773+
774+
/* Patched to NOP when enabled */
775+
void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt,
776+
__le32 *origptr,
777+
__le32 *updptr, int nr_inst)
778+
{
779+
BUG_ON(nr_inst != 1);
780+
}
781+
782+
/* Patched to NOP when enabled */
783+
void noinstr spectre_bhb_patch_fw_mitigation_enabled(struct alt_instr *alt,
784+
__le32 *origptr,
785+
__le32 *updptr, int nr_inst)
786+
{
787+
BUG_ON(nr_inst != 1);
788+
}

include/linux/arm-smccc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@
9292
ARM_SMCCC_SMC_32, \
9393
0, 0x7fff)
9494

95+
#define ARM_SMCCC_ARCH_WORKAROUND_3 \
96+
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
97+
ARM_SMCCC_SMC_32, \
98+
0, 0x3fff)
99+
95100
#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \
96101
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
97102
ARM_SMCCC_SMC_32, \

0 commit comments

Comments
 (0)