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

Commit 1a6c401c authored by James Morse's avatar James Morse Committed by Gerrit - the friendly Code Review server
Browse files

arm64: Use the clearbhb instruction in mitigations



commit 228a26b912287934789023b4132ba76065d9491c 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: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
[ modified for stable: Use a KVM vector template instead of alternatives ]
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Git-commit: ed5dec3f
Git-repo: https://android.googlesource.com/kernel/common/


Change-Id: I78e5a1888e44ef45294ed35226c4cce43f249126
Signed-off-by: default avatarKishor Krishna Bhat <quic_kishkris@quicinc.com>
parent 5ad450e3
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -140,6 +140,13 @@
	hint	#20
	.endm

/*
 * Clear Branch History instruction
 */
	.macro clearbhb
	hint	#22
	.endm

/*
 * Sanitise a 64-bit bounded index wrt speculation, returning zero if out
 * of bounds.
+13 −0
Original line number Diff line number Diff line
@@ -497,6 +497,19 @@ static inline bool supports_csv2p3(int scope)
	return csv2_val == 3;
}

static inline bool supports_clearbhb(int scope)
{
	u64 isar2;

	if (scope == SCOPE_LOCAL_CPU)
		isar2 = read_sysreg_s(SYS_ID_AA64ISAR2_EL1);
	else
		isar2 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1);

	return cpuid_feature_extract_unsigned_field(isar2,
						    ID_AA64ISAR2_CLEARBHB_SHIFT);
}

static inline bool system_supports_32bit_el0(void)
{
	return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);
+3 −0
Original line number Diff line number Diff line
@@ -537,6 +537,9 @@
#define ID_AA64ISAR1_JSCVT_SHIFT	12
#define ID_AA64ISAR1_DPB_SHIFT		0

/* id_aa64isar2 */
#define ID_AA64ISAR2_CLEARBHB_SHIFT	28

/* id_aa64pfr0 */
#define ID_AA64PFR0_CSV3_SHIFT		60
#define ID_AA64PFR0_CSV2_SHIFT		56
+7 −0
Original line number Diff line number Diff line
@@ -33,6 +33,12 @@ enum arm64_bp_harden_el1_vectors {
	 * canonical vectors.
	 */
	EL1_VECTOR_BHB_FW,

	/*
	 * Use the ClearBHB instruction, before branching to the canonical
	 * vectors.
	 */
	EL1_VECTOR_BHB_CLEAR_INSN,
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */

	/*
@@ -44,6 +50,7 @@ enum arm64_bp_harden_el1_vectors {
#ifndef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
#define EL1_VECTOR_BHB_LOOP		-1
#define EL1_VECTOR_BHB_FW		-1
#define EL1_VECTOR_BHB_CLEAR_INSN	-1
#endif /* !CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */

/* The vectors to use on return from EL0. e.g. to remap the kernel */
+13 −1
Original line number Diff line number Diff line
@@ -107,6 +107,8 @@ extern char __spectre_bhb_loop_k24_start[];
extern char __spectre_bhb_loop_k24_end[];
extern char __spectre_bhb_loop_k32_start[];
extern char __spectre_bhb_loop_k32_end[];
extern char __spectre_bhb_clearbhb_start[];
extern char __spectre_bhb_clearbhb_end[];

static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
				const char *hyp_vecs_end)
@@ -1015,6 +1017,7 @@ static void update_mitigation_state(enum mitigation_state *oldp,
 * - Mitigated by a branchy loop a CPU specific number of times, and listed
 *   in our "loop mitigated list".
 * - Mitigated in software by the firmware Spectre v2 call.
 * - Has the ClearBHB instruction to perform the mitigation.
 * - Has the 'Exception Clears Branch History Buffer' (ECBHB) feature, so no
 *   software mitigation in the vectors is needed.
 * - Has CSV2.3, so is unaffected.
@@ -1155,6 +1158,9 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
	if (supports_csv2p3(scope))
		return false;

	if (supports_clearbhb(scope))
		return true;

	if (spectre_bhb_loop_affected(scope))
		return true;

@@ -1195,7 +1201,8 @@ else if (start == __spectre_bhb_loop_k24_start)
		return __spectre_bhb_loop_k24_end;
else if (start == __spectre_bhb_loop_k32_start)
		return __spectre_bhb_loop_k32_end;

else if (start == __spectre_bhb_clearbhb_start)
		return __spectre_bhb_clearbhb_end;
	return NULL;


@@ -1234,6 +1241,7 @@ if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
#define __spectre_bhb_loop_k8_start NULL
#define __spectre_bhb_loop_k24_start NULL
#define __spectre_bhb_loop_k32_start NULL
#define __spectre_bhb_clearbhb_start NULL

static void kvm_setup_bhb_slot(const char *hyp_vecs_start) { };
#endif
@@ -1270,6 +1278,10 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
		pr_info_once("spectre-bhb mitigation disabled by command line option\n");
	} else if (supports_ecbhb(SCOPE_LOCAL_CPU)) {
		state = SPECTRE_MITIGATED;
	} else if (supports_clearbhb(SCOPE_LOCAL_CPU)) {
		kvm_setup_bhb_slot(__spectre_bhb_clearbhb_start);
		this_cpu_set_vectors(EL1_VECTOR_BHB_CLEAR_INSN);
		state = SPECTRE_MITIGATED;
	} else if (spectre_bhb_loop_affected(SCOPE_LOCAL_CPU)) {
		switch (spectre_bhb_loop_affected(SCOPE_SYSTEM)) {
		case 8:
Loading