xref: /openbmc/linux/arch/arm64/include/asm/spectre.h (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
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