
commit 558c303c9734af5a813739cd284879227f7297d2 upstream. Speculation attacks against some high-performance processors can make use of branch history to influence future speculation. When taking an exception from user-space, a sequence of branches or a firmware call overwrites or invalidates the branch history. The sequence of branches is added to the vectors, and should appear before the first indirect branch. For systems using KPTI the sequence is added to the kpti trampoline where it has a free register as the exit from the trampoline is via a 'ret'. For systems not using KPTI, the same register tricks are used to free up a register in the vectors. For the firmware call, arch-workaround-3 clobbers 4 registers, so there is no choice but to save them to the EL1 stack. This only happens for entry from EL0, so if we take an exception due to the stack access, it will not become re-entrant. For KVM, the existing branch-predictor-hardening vectors are used. When a spectre version of these vectors is in use, the firmware call is sufficient to mitigate against Spectre-BHB. For the non-spectre versions, the sequence of branches is added to the indirect vector. Bug: 215557547 Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Change-Id: I7d1f5a9767d1dbc9e6ef363ca3bf7bffe91c402c Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
67 lines
1.6 KiB
C
67 lines
1.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2022 ARM Ltd.
|
|
*/
|
|
#ifndef __ASM_VECTORS_H
|
|
#define __ASM_VECTORS_H
|
|
|
|
#include <linux/bug.h>
|
|
#include <linux/percpu.h>
|
|
|
|
#include <asm/fixmap.h>
|
|
|
|
extern char vectors[];
|
|
extern char tramp_vectors[];
|
|
extern char __bp_harden_el1_vectors[];
|
|
|
|
/*
|
|
* Note: the order of this enum corresponds to two arrays in entry.S:
|
|
* tramp_vecs and __bp_harden_el1_vectors. By default the canonical
|
|
* 'full fat' vectors are used directly.
|
|
*/
|
|
enum arm64_bp_harden_el1_vectors {
|
|
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
|
|
/*
|
|
* Perform the BHB loop mitigation, before branching to the canonical
|
|
* vectors.
|
|
*/
|
|
EL1_VECTOR_BHB_LOOP,
|
|
|
|
/*
|
|
* Make the SMC call for firmware mitigation, before branching to the
|
|
* canonical vectors.
|
|
*/
|
|
EL1_VECTOR_BHB_FW,
|
|
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
|
|
|
|
/*
|
|
* Remap the kernel before branching to the canonical vectors.
|
|
*/
|
|
EL1_VECTOR_KPTI,
|
|
};
|
|
|
|
#ifndef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
|
|
#define EL1_VECTOR_BHB_LOOP -1
|
|
#define EL1_VECTOR_BHB_FW -1
|
|
#endif /* !CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
|
|
|
|
/* The vectors to use on return from EL0. e.g. to remap the kernel */
|
|
DECLARE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector);
|
|
|
|
#ifndef CONFIG_UNMAP_KERNEL_AT_EL0
|
|
#define TRAMP_VALIAS 0
|
|
#endif
|
|
|
|
static inline const char *
|
|
arm64_get_bp_hardening_vector(enum arm64_bp_harden_el1_vectors slot)
|
|
{
|
|
if (arm64_kernel_unmapped_at_el0())
|
|
return (char *)TRAMP_VALIAS + SZ_2K * slot;
|
|
|
|
WARN_ON_ONCE(slot == EL1_VECTOR_KPTI);
|
|
|
|
return __bp_harden_el1_vectors + SZ_2K * slot;
|
|
}
|
|
|
|
#endif /* __ASM_VECTORS_H */
|