Skip to content

Commit bd4fb6d

Browse files
committed
arm64: Add support for SB barrier and patch in over DSB; ISB sequences
We currently use a DSB; ISB sequence to inhibit speculation in set_fs(). Whilst this works for current CPUs, future CPUs may implement a new SB barrier instruction which acts as an architected speculation barrier. On CPUs that support it, patch in an SB; NOP sequence over the DSB; ISB sequence and advertise the presence of the new instruction to userspace. Signed-off-by: Will Deacon <[email protected]>
1 parent 0b587c8 commit bd4fb6d

File tree

8 files changed

+40
-3
lines changed

8 files changed

+40
-3
lines changed

arch/arm64/include/asm/assembler.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,19 @@
122122
hint #20
123123
.endm
124124

125+
/*
126+
* Speculation barrier
127+
*/
128+
.macro sb
129+
alternative_if_not ARM64_HAS_SB
130+
dsb nsh
131+
isb
132+
alternative_else
133+
SB_BARRIER_INSN
134+
nop
135+
alternative_endif
136+
.endm
137+
125138
/*
126139
* Sanitise a 64-bit bounded index wrt speculation, returning zero if out
127140
* of bounds.

arch/arm64/include/asm/barrier.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
#define psb_csync() asm volatile("hint #17" : : : "memory")
3535
#define csdb() asm volatile("hint #20" : : : "memory")
3636

37+
#define spec_bar() asm volatile(ALTERNATIVE("dsb nsh\nisb\n", \
38+
SB_BARRIER_INSN"nop\n", \
39+
ARM64_HAS_SB))
40+
3741
#define mb() dsb(sy)
3842
#define rmb() dsb(ld)
3943
#define wmb() dsb(st)

arch/arm64/include/asm/cpucaps.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
#define ARM64_HAS_CRC32 33
5555
#define ARM64_SSBS 34
5656
#define ARM64_WORKAROUND_1188873 35
57+
#define ARM64_HAS_SB 36
5758

58-
#define ARM64_NCAPS 36
59+
#define ARM64_NCAPS 37
5960

6061
#endif /* __ASM_CPUCAPS_H */

arch/arm64/include/asm/sysreg.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@
104104
#define SET_PSTATE_UAO(x) __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift))
105105
#define SET_PSTATE_SSBS(x) __emit_inst(0xd500401f | PSTATE_SSBS | ((!!x) << PSTATE_Imm_shift))
106106

107+
#define __SYS_BARRIER_INSN(CRm, op2, Rt) \
108+
__emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f))
109+
110+
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
111+
107112
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
108113
#define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2)
109114
#define SYS_DC_CISW sys_insn(1, 0, 7, 14, 2)
@@ -528,6 +533,7 @@
528533
#define ID_AA64ISAR0_AES_SHIFT 4
529534

530535
/* id_aa64isar1 */
536+
#define ID_AA64ISAR1_SB_SHIFT 36
531537
#define ID_AA64ISAR1_LRCPC_SHIFT 20
532538
#define ID_AA64ISAR1_FCMA_SHIFT 16
533539
#define ID_AA64ISAR1_JSCVT_SHIFT 12

arch/arm64/include/asm/uaccess.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ static inline void set_fs(mm_segment_t fs)
4545
* Prevent a mispredicted conditional call to set_fs from forwarding
4646
* the wrong address limit to access_ok under speculation.
4747
*/
48-
dsb(nsh);
49-
isb();
48+
spec_bar();
5049

5150
/* On user-mode return, check fs is correct */
5251
set_thread_flag(TIF_FSCHECK);

arch/arm64/include/uapi/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@
4949
#define HWCAP_ILRCPC (1 << 26)
5050
#define HWCAP_FLAGM (1 << 27)
5151
#define HWCAP_SSBS (1 << 28)
52+
#define HWCAP_SB (1 << 29)
5253

5354
#endif /* _UAPI__ASM_HWCAP_H */

arch/arm64/kernel/cpufeature.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
142142
};
143143

144144
static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
145+
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_SB_SHIFT, 4, 0),
145146
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
146147
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
147148
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
@@ -1398,6 +1399,16 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
13981399
.cpu_enable = cpu_enable_cnp,
13991400
},
14001401
#endif
1402+
{
1403+
.desc = "Speculation barrier (SB)",
1404+
.capability = ARM64_HAS_SB,
1405+
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
1406+
.matches = has_cpuid_feature,
1407+
.sys_reg = SYS_ID_AA64ISAR1_EL1,
1408+
.field_pos = ID_AA64ISAR1_SB_SHIFT,
1409+
.sign = FTR_UNSIGNED,
1410+
.min_field_value = 1,
1411+
},
14011412
{},
14021413
};
14031414

@@ -1439,6 +1450,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
14391450
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_FCMA),
14401451
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_LRCPC),
14411452
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_ILRCPC),
1453+
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_SB_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SB),
14421454
HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_AT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_USCAT),
14431455
#ifdef CONFIG_ARM64_SVE
14441456
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_SVE_SHIFT, FTR_UNSIGNED, ID_AA64PFR0_SVE, CAP_HWCAP, HWCAP_SVE),

arch/arm64/kernel/cpuinfo.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ static const char *const hwcap_str[] = {
8282
"ilrcpc",
8383
"flagm",
8484
"ssbs",
85+
"sb",
8586
NULL
8687
};
8788

0 commit comments

Comments
 (0)