Commit b9baf5c8 authored by Russell King (Oracle)'s avatar Russell King (Oracle)
Browse files

ARM: Spectre-BHB workaround



Workaround the Spectre BHB issues for Cortex-A15, Cortex-A57,
Cortex-A72, Cortex-A73 and Cortex-A75. We also include Brahma B15 as
well to be safe, which is affected by Spectre V2 in the same ways as
Cortex-A15.

Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
parent 8d9d651f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -107,6 +107,16 @@
	.endm
#endif

#if __LINUX_ARM_ARCH__ < 7
	.macro	dsb, args
	mcr	p15, 0, r0, c7, c10, 4
	.endm

	.macro	isb, args
	mcr	p15, 0, r0, c7, r5, 4
	.endm
#endif

	.macro asm_trace_hardirqs_off, save=1
#if defined(CONFIG_TRACE_IRQFLAGS)
	.if \save
+4 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ enum {
	__SPECTRE_V2_METHOD_ICIALLU,
	__SPECTRE_V2_METHOD_SMC,
	__SPECTRE_V2_METHOD_HVC,
	__SPECTRE_V2_METHOD_LOOP8,
};

enum {
@@ -21,8 +22,11 @@ enum {
	SPECTRE_V2_METHOD_ICIALLU = BIT(__SPECTRE_V2_METHOD_ICIALLU),
	SPECTRE_V2_METHOD_SMC = BIT(__SPECTRE_V2_METHOD_SMC),
	SPECTRE_V2_METHOD_HVC = BIT(__SPECTRE_V2_METHOD_HVC),
	SPECTRE_V2_METHOD_LOOP8 = BIT(__SPECTRE_V2_METHOD_LOOP8),
};

void spectre_v2_update_state(unsigned int state, unsigned int methods);

int spectre_bhb_update_vectors(unsigned int method);

#endif
+15 −3
Original line number Diff line number Diff line
@@ -116,11 +116,23 @@
 */
#define ARM_VECTORS							\
	__vectors_lma = .;						\
	.vectors 0xffff0000 : AT(__vectors_start) {			\
	OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) {		\
		.vectors {						\
			*(.vectors)					\
		}							\
		.vectors.bhb.loop8 {					\
			*(.vectors.bhb.loop8)				\
		}							\
		.vectors.bhb.bpiall {					\
			*(.vectors.bhb.bpiall)				\
		}							\
	}								\
	ARM_LMA(__vectors, .vectors);					\
	. = __vectors_lma + SIZEOF(.vectors);				\
	ARM_LMA(__vectors_bhb_loop8, .vectors.bhb.loop8);		\
	ARM_LMA(__vectors_bhb_bpiall, .vectors.bhb.bpiall);		\
	. = __vectors_lma + SIZEOF(.vectors) +				\
		SIZEOF(.vectors.bhb.loop8) +				\
		SIZEOF(.vectors.bhb.bpiall);				\
									\
	__stubs_lma = .;						\
	.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) {		\
+73 −6
Original line number Diff line number Diff line
@@ -1002,12 +1002,11 @@ vector_\name:
	sub	lr, lr, #\correction
	.endif

	@
	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
	@ (parent CPSR)
	@
	@ Save r0, lr_<exception> (parent PC)
	stmia	sp, {r0, lr}		@ save r0, lr
	mrs	lr, spsr

	@ Save spsr_<exception> (parent CPSR)
2:	mrs	lr, spsr
	str	lr, [sp, #8]		@ save spsr

	@
@@ -1028,6 +1027,44 @@ vector_\name:
	movs	pc, lr			@ branch to handler in SVC mode
ENDPROC(vector_\name)

#ifdef CONFIG_HARDEN_BRANCH_HISTORY
	.subsection 1
	.align 5
vector_bhb_loop8_\name:
	.if \correction
	sub	lr, lr, #\correction
	.endif

	@ Save r0, lr_<exception> (parent PC)
	stmia	sp, {r0, lr}

	@ bhb workaround
	mov	r0, #8
1:	b	. + 4
	subs	r0, r0, #1
	bne	1b
	dsb
	isb
	b	2b
ENDPROC(vector_bhb_loop8_\name)

vector_bhb_bpiall_\name:
	.if \correction
	sub	lr, lr, #\correction
	.endif

	@ Save r0, lr_<exception> (parent PC)
	stmia	sp, {r0, lr}

	@ bhb workaround
	mcr	p15, 0, r0, c7, c5, 6	@ BPIALL
	@ isb not needed due to "movs pc, lr" in the vector stub
	@ which gives a "context synchronisation".
	b	2b
ENDPROC(vector_bhb_bpiall_\name)
	.previous
#endif

	.align	2
	@ handler addresses follow this label
1:
@@ -1036,6 +1073,10 @@ ENDPROC(vector_\name)
	.section .stubs, "ax", %progbits
	@ This must be the first word
	.word	vector_swi
#ifdef CONFIG_HARDEN_BRANCH_HISTORY
	.word	vector_bhb_loop8_swi
	.word	vector_bhb_bpiall_swi
#endif

vector_rst:
 ARM(	swi	SYS_ERROR0	)
@@ -1150,8 +1191,10 @@ vector_addrexcptn:
 * FIQ "NMI" handler
 *-----------------------------------------------------------------------------
 * Handle a FIQ using the SVC stack allowing FIQ act like NMI on x86
 * systems.
 * systems. This must be the last vector stub, so lets place it in its own
 * subsection.
 */
	.subsection 2
	vector_stub	fiq, FIQ_MODE, 4

	.long	__fiq_usr			@  0  (USR_26 / USR_32)
@@ -1184,6 +1227,30 @@ vector_addrexcptn:
	W(b)	vector_irq
	W(b)	vector_fiq

#ifdef CONFIG_HARDEN_BRANCH_HISTORY
	.section .vectors.bhb.loop8, "ax", %progbits
.L__vectors_bhb_loop8_start:
	W(b)	vector_rst
	W(b)	vector_bhb_loop8_und
	W(ldr)	pc, .L__vectors_bhb_loop8_start + 0x1004
	W(b)	vector_bhb_loop8_pabt
	W(b)	vector_bhb_loop8_dabt
	W(b)	vector_addrexcptn
	W(b)	vector_bhb_loop8_irq
	W(b)	vector_bhb_loop8_fiq

	.section .vectors.bhb.bpiall, "ax", %progbits
.L__vectors_bhb_bpiall_start:
	W(b)	vector_rst
	W(b)	vector_bhb_bpiall_und
	W(ldr)	pc, .L__vectors_bhb_bpiall_start + 0x1008
	W(b)	vector_bhb_bpiall_pabt
	W(b)	vector_bhb_bpiall_dabt
	W(b)	vector_addrexcptn
	W(b)	vector_bhb_bpiall_irq
	W(b)	vector_bhb_bpiall_fiq
#endif

	.data
	.align	2

+24 −0
Original line number Diff line number Diff line
@@ -153,6 +153,29 @@ ENDPROC(ret_from_fork)
 *-----------------------------------------------------------------------------
 */

	.align	5
#ifdef CONFIG_HARDEN_BRANCH_HISTORY
ENTRY(vector_bhb_loop8_swi)
	sub	sp, sp, #PT_REGS_SIZE
	stmia	sp, {r0 - r12}
	mov	r8, #8
1:	b	2f
2:	subs	r8, r8, #1
	bne	1b
	dsb
	isb
	b	3f
ENDPROC(vector_bhb_loop8_swi)

	.align	5
ENTRY(vector_bhb_bpiall_swi)
	sub	sp, sp, #PT_REGS_SIZE
	stmia	sp, {r0 - r12}
	mcr	p15, 0, r8, c7, c5, 6	@ BPIALL
	isb
	b	3f
ENDPROC(vector_bhb_bpiall_swi)
#endif
	.align	5
ENTRY(vector_swi)
#ifdef CONFIG_CPU_V7M
@@ -160,6 +183,7 @@ ENTRY(vector_swi)
#else
	sub	sp, sp, #PT_REGS_SIZE
	stmia	sp, {r0 - r12}			@ Calling r0 - r12
3:
 ARM(	add	r8, sp, #S_PC		)
 ARM(	stmdb	r8, {sp, lr}^		)	@ Calling sp, lr
 THUMB(	mov	r8, sp			)
Loading