1d4647f0aSWill Deacon /* SPDX-License-Identifier: GPL-2.0-only */
2d4647f0aSWill Deacon /*
3d4647f0aSWill Deacon * Interface for managing mitigations for Spectre vulnerabilities.
4d4647f0aSWill Deacon *
5d4647f0aSWill Deacon * Copyright (C) 2020 Google LLC
6d4647f0aSWill Deacon * Author: Will Deacon <will@kernel.org>
7d4647f0aSWill Deacon */
8d4647f0aSWill Deacon
9d4647f0aSWill Deacon #ifndef __ASM_SPECTRE_H
10d4647f0aSWill Deacon #define __ASM_SPECTRE_H
11d4647f0aSWill Deacon
126279017eSWill Deacon #define BP_HARDEN_EL2_SLOTS 4
134f6a36feSWill Deacon #define __BP_HARDEN_HYP_VECS_SZ ((BP_HARDEN_EL2_SLOTS - 1) * SZ_2K)
146279017eSWill Deacon
156279017eSWill Deacon #ifndef __ASSEMBLY__
166279017eSWill Deacon
176279017eSWill Deacon #include <linux/percpu.h>
186279017eSWill Deacon
19d4647f0aSWill Deacon #include <asm/cpufeature.h>
206279017eSWill Deacon #include <asm/virt.h>
21d4647f0aSWill Deacon
22d4647f0aSWill Deacon /* Watch out, ordering is important here. */
23d4647f0aSWill Deacon enum mitigation_state {
24d4647f0aSWill Deacon SPECTRE_UNAFFECTED,
25d4647f0aSWill Deacon SPECTRE_MITIGATED,
26d4647f0aSWill Deacon SPECTRE_VULNERABLE,
27d4647f0aSWill Deacon };
28d4647f0aSWill Deacon
29bff8f413SMark Rutland struct pt_regs;
30d4647f0aSWill Deacon struct task_struct;
31d4647f0aSWill Deacon
32b881cdceSWill Deacon /*
33b881cdceSWill Deacon * Note: the order of this enum corresponds to __bp_harden_hyp_vecs and
34b881cdceSWill Deacon * we rely on having the direct vectors first.
35b881cdceSWill Deacon */
36b881cdceSWill Deacon enum arm64_hyp_spectre_vector {
37b881cdceSWill Deacon /*
38b881cdceSWill Deacon * Take exceptions directly to __kvm_hyp_vector. This must be
39b881cdceSWill Deacon * 0 so that it used by default when mitigations are not needed.
40b881cdceSWill Deacon */
41b881cdceSWill Deacon HYP_VECTOR_DIRECT,
42b881cdceSWill Deacon
43b881cdceSWill Deacon /*
44b881cdceSWill Deacon * Bounce via a slot in the hypervisor text mapping of
45b881cdceSWill Deacon * __bp_harden_hyp_vecs, which contains an SMC call.
46b881cdceSWill Deacon */
47b881cdceSWill Deacon HYP_VECTOR_SPECTRE_DIRECT,
48b881cdceSWill Deacon
49b881cdceSWill Deacon /*
50b881cdceSWill Deacon * Bounce via a slot in a special mapping of __bp_harden_hyp_vecs
51b881cdceSWill Deacon * next to the idmap page.
52b881cdceSWill Deacon */
53b881cdceSWill Deacon HYP_VECTOR_INDIRECT,
54b881cdceSWill Deacon
55b881cdceSWill Deacon /*
56b881cdceSWill Deacon * Bounce via a slot in a special mapping of __bp_harden_hyp_vecs
57b881cdceSWill Deacon * next to the idmap page, which contains an SMC call.
58b881cdceSWill Deacon */
59b881cdceSWill Deacon HYP_VECTOR_SPECTRE_INDIRECT,
60b881cdceSWill Deacon };
61b881cdceSWill Deacon
626279017eSWill Deacon typedef void (*bp_hardening_cb_t)(void);
636279017eSWill Deacon
646279017eSWill Deacon struct bp_hardening_data {
65b881cdceSWill Deacon enum arm64_hyp_spectre_vector slot;
666279017eSWill Deacon bp_hardening_cb_t fn;
676279017eSWill Deacon };
686279017eSWill Deacon
696279017eSWill Deacon DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
706279017eSWill Deacon
71614c0b9fSMark Rutland /* Called during entry so must be __always_inline */
arm64_apply_bp_hardening(void)72614c0b9fSMark Rutland static __always_inline void arm64_apply_bp_hardening(void)
736279017eSWill Deacon {
746279017eSWill Deacon struct bp_hardening_data *d;
756279017eSWill Deacon
766279017eSWill Deacon if (!cpus_have_const_cap(ARM64_SPECTRE_V2))
776279017eSWill Deacon return;
786279017eSWill Deacon
796279017eSWill Deacon d = this_cpu_ptr(&bp_hardening_data);
806279017eSWill Deacon if (d->fn)
816279017eSWill Deacon d->fn();
826279017eSWill Deacon }
836279017eSWill Deacon
84d4647f0aSWill Deacon enum mitigation_state arm64_get_spectre_v2_state(void);
85d4647f0aSWill Deacon bool has_spectre_v2(const struct arm64_cpu_capabilities *cap, int scope);
86d4647f0aSWill Deacon void spectre_v2_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
87d4647f0aSWill Deacon
88cd1f56b9SWill Deacon bool has_spectre_v3a(const struct arm64_cpu_capabilities *cap, int scope);
89c4792b6dSWill Deacon void spectre_v3a_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
90b881cdceSWill Deacon
91c2876207SWill Deacon enum mitigation_state arm64_get_spectre_v4_state(void);
92c2876207SWill Deacon bool has_spectre_v4(const struct arm64_cpu_capabilities *cap, int scope);
93c2876207SWill Deacon void spectre_v4_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
94c2876207SWill Deacon void spectre_v4_enable_task_mitigation(struct task_struct *tsk);
95c2876207SWill Deacon
967f43c201SMarc Zyngier enum mitigation_state arm64_get_meltdown_state(void);
977f43c201SMarc Zyngier
98dee435beSJames Morse enum mitigation_state arm64_get_spectre_bhb_state(void);
99558c303cSJames Morse bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
100558c303cSJames Morse u8 spectre_bhb_loop_affected(int scope);
101558c303cSJames Morse void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
102bff8f413SMark Rutland bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr);
103*010089e9SArnd Bergmann
104*010089e9SArnd Bergmann void spectre_v4_patch_fw_mitigation_enable(struct alt_instr *alt, __le32 *origptr,
105*010089e9SArnd Bergmann __le32 *updptr, int nr_inst);
106*010089e9SArnd Bergmann void smccc_patch_fw_mitigation_conduit(struct alt_instr *alt, __le32 *origptr,
107*010089e9SArnd Bergmann __le32 *updptr, int nr_inst);
108*010089e9SArnd Bergmann void spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt, __le32 *origptr,
109*010089e9SArnd Bergmann __le32 *updptr, int nr_inst);
110*010089e9SArnd Bergmann void spectre_bhb_patch_fw_mitigation_enabled(struct alt_instr *alt, __le32 *origptr,
111*010089e9SArnd Bergmann __le32 *updptr, int nr_inst);
112*010089e9SArnd Bergmann void spectre_bhb_patch_loop_iter(struct alt_instr *alt,
113*010089e9SArnd Bergmann __le32 *origptr, __le32 *updptr, int nr_inst);
114*010089e9SArnd Bergmann void spectre_bhb_patch_wa3(struct alt_instr *alt,
115*010089e9SArnd Bergmann __le32 *origptr, __le32 *updptr, int nr_inst);
116*010089e9SArnd Bergmann void spectre_bhb_patch_clearbhb(struct alt_instr *alt,
117*010089e9SArnd Bergmann __le32 *origptr, __le32 *updptr, int nr_inst);
118*010089e9SArnd Bergmann
1196279017eSWill Deacon #endif /* __ASSEMBLY__ */
120d4647f0aSWill Deacon #endif /* __ASM_SPECTRE_H */
121