Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 920f7970 authored by Russell King (Oracle)'s avatar Russell King (Oracle) Committed by Greg Kroah-Hartman
Browse files

ARM: Spectre-BHB workaround



commit b9baf5c8c5c356757f4f9d8180b5e9d234065bc3 upstream.

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>
[changes due to lack of SYSTEM_FREEING_INITMEM - gregkh]
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent dcf33beb
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
+73 −6
Original line number Diff line number Diff line
@@ -1005,12 +1005,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

	@
@@ -1031,6 +1030,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:
@@ -1039,6 +1076,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	)
@@ -1153,8 +1194,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)
@@ -1187,6 +1230,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
@@ -162,6 +162,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
@@ -169,6 +192,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			)
+4 −0
Original line number Diff line number Diff line
@@ -45,6 +45,10 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr,
		method = "Firmware call";
		break;

	case SPECTRE_V2_METHOD_LOOP8:
		method = "History overwrite";
		break;

	default:
		method = "Multiple mitigations";
		break;
Loading