David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | |
Borislav Petkov | 7a32fc5 | 2018-01-26 13:11:37 +0100 | [diff] [blame] | 3 | #ifndef _ASM_X86_NOSPEC_BRANCH_H_ |
| 4 | #define _ASM_X86_NOSPEC_BRANCH_H_ |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 5 | |
Thomas Gleixner | fa1202ef | 2018-11-25 19:33:45 +0100 | [diff] [blame] | 6 | #include <linux/static_key.h> |
Julien Thierry | 00089c0 | 2020-09-04 16:30:25 +0100 | [diff] [blame] | 7 | #include <linux/objtool.h> |
Peter Zijlstra | 6fda8a3 | 2021-10-26 14:01:40 +0200 | [diff] [blame] | 8 | #include <linux/linkage.h> |
Thomas Gleixner | fa1202ef | 2018-11-25 19:33:45 +0100 | [diff] [blame] | 9 | |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 10 | #include <asm/alternative.h> |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 11 | #include <asm/cpufeatures.h> |
Peter Zijlstra | ea00f30 | 2018-02-13 14:28:19 +0100 | [diff] [blame] | 12 | #include <asm/msr-index.h> |
Peter Zijlstra | 089dd8e | 2020-04-14 12:36:16 +0200 | [diff] [blame] | 13 | #include <asm/unwind_hints.h> |
Nathan Chancellor | db88697 | 2022-07-13 08:24:37 -0700 | [diff] [blame] | 14 | #include <asm/percpu.h> |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 15 | #include <asm/current.h> |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 16 | |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 17 | /* |
| 18 | * Call depth tracking for Intel SKL CPUs to address the RSB underflow |
| 19 | * issue in software. |
| 20 | * |
| 21 | * The tracking does not use a counter. It uses uses arithmetic shift |
| 22 | * right on call entry and logical shift left on return. |
| 23 | * |
| 24 | * The depth tracking variable is initialized to 0x8000.... when the call |
| 25 | * depth is zero. The arithmetic shift right sign extends the MSB and |
| 26 | * saturates after the 12th call. The shift count is 5 for both directions |
| 27 | * so the tracking covers 12 nested calls. |
| 28 | * |
| 29 | * Call |
| 30 | * 0: 0x8000000000000000 0x0000000000000000 |
| 31 | * 1: 0xfc00000000000000 0xf000000000000000 |
| 32 | * ... |
| 33 | * 11: 0xfffffffffffffff8 0xfffffffffffffc00 |
| 34 | * 12: 0xffffffffffffffff 0xffffffffffffffe0 |
| 35 | * |
| 36 | * After a return buffer fill the depth is credited 12 calls before the |
| 37 | * next stuffing has to take place. |
| 38 | * |
| 39 | * There is a inaccuracy for situations like this: |
| 40 | * |
| 41 | * 10 calls |
| 42 | * 5 returns |
| 43 | * 3 calls |
| 44 | * 4 returns |
| 45 | * 3 calls |
| 46 | * .... |
| 47 | * |
| 48 | * The shift count might cause this to be off by one in either direction, |
| 49 | * but there is still a cushion vs. the RSB depth. The algorithm does not |
| 50 | * claim to be perfect and it can be speculated around by the CPU, but it |
| 51 | * is considered that it obfuscates the problem enough to make exploitation |
Bjorn Helgaas | 54aa699 | 2024-01-02 18:40:11 -0600 | [diff] [blame] | 52 | * extremely difficult. |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 53 | */ |
| 54 | #define RET_DEPTH_SHIFT 5 |
| 55 | #define RSB_RET_STUFF_LOOPS 16 |
| 56 | #define RET_DEPTH_INIT 0x8000000000000000ULL |
| 57 | #define RET_DEPTH_INIT_FROM_CALL 0xfc00000000000000ULL |
| 58 | #define RET_DEPTH_CREDIT 0xffffffffffffffffULL |
| 59 | |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 60 | #ifdef CONFIG_CALL_THUNKS_DEBUG |
| 61 | # define CALL_THUNKS_DEBUG_INC_CALLS \ |
Uros Bizjak | 2adeed9 | 2023-11-05 22:34:37 +0100 | [diff] [blame] | 62 | incq PER_CPU_VAR(__x86_call_count); |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 63 | # define CALL_THUNKS_DEBUG_INC_RETS \ |
Uros Bizjak | 2adeed9 | 2023-11-05 22:34:37 +0100 | [diff] [blame] | 64 | incq PER_CPU_VAR(__x86_ret_count); |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 65 | # define CALL_THUNKS_DEBUG_INC_STUFFS \ |
Uros Bizjak | 2adeed9 | 2023-11-05 22:34:37 +0100 | [diff] [blame] | 66 | incq PER_CPU_VAR(__x86_stuffs_count); |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 67 | # define CALL_THUNKS_DEBUG_INC_CTXSW \ |
Uros Bizjak | 2adeed9 | 2023-11-05 22:34:37 +0100 | [diff] [blame] | 68 | incq PER_CPU_VAR(__x86_ctxsw_count); |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 69 | #else |
| 70 | # define CALL_THUNKS_DEBUG_INC_CALLS |
| 71 | # define CALL_THUNKS_DEBUG_INC_RETS |
| 72 | # define CALL_THUNKS_DEBUG_INC_STUFFS |
| 73 | # define CALL_THUNKS_DEBUG_INC_CTXSW |
| 74 | #endif |
| 75 | |
Breno Leitao | 5fa31af | 2023-11-21 08:07:30 -0800 | [diff] [blame] | 76 | #if defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) && !defined(COMPILE_OFFSETS) |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 77 | |
| 78 | #include <asm/asm-offsets.h> |
| 79 | |
| 80 | #define CREDIT_CALL_DEPTH \ |
| 81 | movq $-1, PER_CPU_VAR(pcpu_hot + X86_call_depth); |
| 82 | |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 83 | #define RESET_CALL_DEPTH \ |
Peter Zijlstra | 3496d1c | 2023-02-10 10:10:57 +0000 | [diff] [blame] | 84 | xor %eax, %eax; \ |
| 85 | bts $63, %rax; \ |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 86 | movq %rax, PER_CPU_VAR(pcpu_hot + X86_call_depth); |
| 87 | |
| 88 | #define RESET_CALL_DEPTH_FROM_CALL \ |
Peter Zijlstra | 3496d1c | 2023-02-10 10:10:57 +0000 | [diff] [blame] | 89 | movb $0xfc, %al; \ |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 90 | shl $56, %rax; \ |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 91 | movq %rax, PER_CPU_VAR(pcpu_hot + X86_call_depth); \ |
| 92 | CALL_THUNKS_DEBUG_INC_CALLS |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 93 | |
| 94 | #define INCREMENT_CALL_DEPTH \ |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 95 | sarq $5, PER_CPU_VAR(pcpu_hot + X86_call_depth); \ |
| 96 | CALL_THUNKS_DEBUG_INC_CALLS |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 97 | |
| 98 | #else |
| 99 | #define CREDIT_CALL_DEPTH |
| 100 | #define RESET_CALL_DEPTH |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 101 | #define RESET_CALL_DEPTH_FROM_CALL |
Uros Bizjak | 2adeed9 | 2023-11-05 22:34:37 +0100 | [diff] [blame] | 102 | #define INCREMENT_CALL_DEPTH |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 103 | #endif |
Peter Zijlstra | 1a6f744 | 2021-10-26 14:01:41 +0200 | [diff] [blame] | 104 | |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 105 | /* |
| 106 | * Fill the CPU return stack buffer. |
| 107 | * |
| 108 | * Each entry in the RSB, if used for a speculative 'ret', contains an |
| 109 | * infinite 'pause; lfence; jmp' loop to capture speculative execution. |
| 110 | * |
| 111 | * This is required in various cases for retpoline and IBRS-based |
| 112 | * mitigations for the Spectre variant 2 vulnerability. Sometimes to |
| 113 | * eliminate potentially bogus entries from the RSB, and sometimes |
| 114 | * purely to ensure that it doesn't get empty, which on some CPUs would |
| 115 | * allow predictions from other (unwanted!) sources to be used. |
| 116 | * |
| 117 | * We define a CPP macro such that it can be used from both .S files and |
| 118 | * inline assembly. It's possible to do a .macro and then include that |
| 119 | * from C via asm(".include <asm/nospec-branch.h>") but let's not go there. |
| 120 | */ |
| 121 | |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 122 | #define RETPOLINE_THUNK_SIZE 32 |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 123 | #define RSB_CLEAR_LOOPS 32 /* To forcibly overwrite all entries */ |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 124 | |
| 125 | /* |
Peter Zijlstra | 4e3aa92 | 2022-08-16 14:28:36 +0200 | [diff] [blame] | 126 | * Common helper for __FILL_RETURN_BUFFER and __FILL_ONE_RETURN. |
| 127 | */ |
| 128 | #define __FILL_RETURN_SLOT \ |
| 129 | ANNOTATE_INTRA_FUNCTION_CALL; \ |
| 130 | call 772f; \ |
| 131 | int3; \ |
| 132 | 772: |
| 133 | |
| 134 | /* |
| 135 | * Stuff the entire RSB. |
| 136 | * |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 137 | * Google experimented with loop-unrolling and this turned out to be |
Ingo Molnar | c681df8 | 2021-03-21 23:32:33 +0100 | [diff] [blame] | 138 | * the optimal version - two calls, each with their own speculation |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 139 | * trap should their return address end up getting used, in a loop. |
| 140 | */ |
Peter Zijlstra | 3329249 | 2022-08-19 13:01:35 +0200 | [diff] [blame] | 141 | #ifdef CONFIG_X86_64 |
Peter Zijlstra | 4e3aa92 | 2022-08-16 14:28:36 +0200 | [diff] [blame] | 142 | #define __FILL_RETURN_BUFFER(reg, nr) \ |
| 143 | mov $(nr/2), reg; \ |
| 144 | 771: \ |
| 145 | __FILL_RETURN_SLOT \ |
| 146 | __FILL_RETURN_SLOT \ |
| 147 | add $(BITS_PER_LONG/8) * 2, %_ASM_SP; \ |
| 148 | dec reg; \ |
| 149 | jnz 771b; \ |
| 150 | /* barrier for jnz misprediction */ \ |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 151 | lfence; \ |
Uros Bizjak | 2adeed9 | 2023-11-05 22:34:37 +0100 | [diff] [blame] | 152 | CREDIT_CALL_DEPTH \ |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 153 | CALL_THUNKS_DEBUG_INC_CTXSW |
Peter Zijlstra | 3329249 | 2022-08-19 13:01:35 +0200 | [diff] [blame] | 154 | #else |
| 155 | /* |
| 156 | * i386 doesn't unconditionally have LFENCE, as such it can't |
| 157 | * do a loop. |
| 158 | */ |
| 159 | #define __FILL_RETURN_BUFFER(reg, nr) \ |
| 160 | .rept nr; \ |
| 161 | __FILL_RETURN_SLOT; \ |
| 162 | .endr; \ |
| 163 | add $(BITS_PER_LONG/8) * nr, %_ASM_SP; |
| 164 | #endif |
Peter Zijlstra | 4e3aa92 | 2022-08-16 14:28:36 +0200 | [diff] [blame] | 165 | |
| 166 | /* |
| 167 | * Stuff a single RSB slot. |
| 168 | * |
| 169 | * To mitigate Post-Barrier RSB speculation, one CALL instruction must be |
| 170 | * forced to retire before letting a RET instruction execute. |
| 171 | * |
| 172 | * On PBRSB-vulnerable CPUs, it is not safe for a RET to be executed |
| 173 | * before this point. |
| 174 | */ |
| 175 | #define __FILL_ONE_RETURN \ |
| 176 | __FILL_RETURN_SLOT \ |
| 177 | add $(BITS_PER_LONG/8), %_ASM_SP; \ |
Pawan Gupta | ba6e31a | 2022-08-02 15:47:02 -0700 | [diff] [blame] | 178 | lfence; |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 179 | |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 180 | #ifdef __ASSEMBLY__ |
| 181 | |
| 182 | /* |
Peter Zijlstra | 9e0e3c5 | 2018-01-17 22:34:34 +0100 | [diff] [blame] | 183 | * This should be used immediately before an indirect jump/call. It tells |
| 184 | * objtool the subsequent indirect jump/call is vouched safe for retpoline |
| 185 | * builds. |
| 186 | */ |
| 187 | .macro ANNOTATE_RETPOLINE_SAFE |
Josh Poimboeuf | 1c0c1fa | 2023-03-01 07:13:08 -0800 | [diff] [blame] | 188 | .Lhere_\@: |
Peter Zijlstra | 9e0e3c5 | 2018-01-17 22:34:34 +0100 | [diff] [blame] | 189 | .pushsection .discard.retpoline_safe |
Fangrui Song | b8ec60e | 2023-09-19 17:17:28 -0700 | [diff] [blame] | 190 | .long .Lhere_\@ |
Peter Zijlstra | 9e0e3c5 | 2018-01-17 22:34:34 +0100 | [diff] [blame] | 191 | .popsection |
| 192 | .endm |
| 193 | |
| 194 | /* |
Peter Zijlstra | 9bb2ec6 | 2022-06-14 23:15:59 +0200 | [diff] [blame] | 195 | * (ab)use RETPOLINE_SAFE on RET to annotate away 'bare' RET instructions |
| 196 | * vs RETBleed validation. |
| 197 | */ |
| 198 | #define ANNOTATE_UNRET_SAFE ANNOTATE_RETPOLINE_SAFE |
| 199 | |
| 200 | /* |
Peter Zijlstra | a09a6e2 | 2022-06-14 23:16:03 +0200 | [diff] [blame] | 201 | * Abuse ANNOTATE_RETPOLINE_SAFE on a NOP to indicate UNRET_END, should |
Bjorn Helgaas | 54aa699 | 2024-01-02 18:40:11 -0600 | [diff] [blame] | 202 | * eventually turn into its own annotation. |
Peter Zijlstra | a09a6e2 | 2022-06-14 23:16:03 +0200 | [diff] [blame] | 203 | */ |
Josh Poimboeuf | 4708ea1 | 2023-03-01 07:13:11 -0800 | [diff] [blame] | 204 | .macro VALIDATE_UNRET_END |
Borislav Petkov (AMD) | fb3bd91 | 2023-06-28 11:02:39 +0200 | [diff] [blame] | 205 | #if defined(CONFIG_NOINSTR_VALIDATION) && \ |
Breno Leitao | a033eec | 2023-11-21 08:07:36 -0800 | [diff] [blame] | 206 | (defined(CONFIG_MITIGATION_UNRET_ENTRY) || defined(CONFIG_MITIGATION_SRSO)) |
Peter Zijlstra | a09a6e2 | 2022-06-14 23:16:03 +0200 | [diff] [blame] | 207 | ANNOTATE_RETPOLINE_SAFE |
| 208 | nop |
| 209 | #endif |
| 210 | .endm |
| 211 | |
| 212 | /* |
Peter Zijlstra | 09d0953 | 2022-07-20 12:04:21 +0200 | [diff] [blame] | 213 | * Equivalent to -mindirect-branch-cs-prefix; emit the 5 byte jmp/call |
| 214 | * to the retpoline thunk with a CS prefix when the register requires |
| 215 | * a RAX prefix byte to encode. Also see apply_retpolines(). |
| 216 | */ |
| 217 | .macro __CS_PREFIX reg:req |
| 218 | .irp rs,r8,r9,r10,r11,r12,r13,r14,r15 |
| 219 | .ifc \reg,\rs |
| 220 | .byte 0x2e |
| 221 | .endif |
| 222 | .endr |
| 223 | .endm |
| 224 | |
| 225 | /* |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 226 | * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple |
| 227 | * indirect jmp/call which may be susceptible to the Spectre variant 2 |
| 228 | * attack. |
Peter Zijlstra | 0479a42 | 2023-06-22 16:27:13 +0200 | [diff] [blame] | 229 | * |
| 230 | * NOTE: these do not take kCFI into account and are thus not comparable to C |
| 231 | * indirect calls, take care when using. The target of these should be an ENDBR |
| 232 | * instruction irrespective of kCFI. |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 233 | */ |
| 234 | .macro JMP_NOSPEC reg:req |
Breno Leitao | aefb2f2 | 2023-11-21 08:07:32 -0800 | [diff] [blame] | 235 | #ifdef CONFIG_MITIGATION_RETPOLINE |
Peter Zijlstra | 09d0953 | 2022-07-20 12:04:21 +0200 | [diff] [blame] | 236 | __CS_PREFIX \reg |
| 237 | jmp __x86_indirect_thunk_\reg |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 238 | #else |
Peter Zijlstra | 34fdce6 | 2020-04-22 17:16:40 +0200 | [diff] [blame] | 239 | jmp *%\reg |
Peter Zijlstra | 09d0953 | 2022-07-20 12:04:21 +0200 | [diff] [blame] | 240 | int3 |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 241 | #endif |
| 242 | .endm |
| 243 | |
| 244 | .macro CALL_NOSPEC reg:req |
Breno Leitao | aefb2f2 | 2023-11-21 08:07:32 -0800 | [diff] [blame] | 245 | #ifdef CONFIG_MITIGATION_RETPOLINE |
Peter Zijlstra | 09d0953 | 2022-07-20 12:04:21 +0200 | [diff] [blame] | 246 | __CS_PREFIX \reg |
| 247 | call __x86_indirect_thunk_\reg |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 248 | #else |
Peter Zijlstra | 34fdce6 | 2020-04-22 17:16:40 +0200 | [diff] [blame] | 249 | call *%\reg |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 250 | #endif |
| 251 | .endm |
| 252 | |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 253 | /* |
| 254 | * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP |
| 255 | * monstrosity above, manually. |
| 256 | */ |
Peter Zijlstra | 4e3aa92 | 2022-08-16 14:28:36 +0200 | [diff] [blame] | 257 | .macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2=ALT_NOT(X86_FEATURE_ALWAYS) |
| 258 | ALTERNATIVE_2 "jmp .Lskip_rsb_\@", \ |
| 259 | __stringify(__FILL_RETURN_BUFFER(\reg,\nr)), \ftr, \ |
Peter Zijlstra | 6ea17e8 | 2023-02-08 18:18:04 +0100 | [diff] [blame] | 260 | __stringify(nop;nop;__FILL_ONE_RETURN), \ftr2 |
Peter Zijlstra | 4e3aa92 | 2022-08-16 14:28:36 +0200 | [diff] [blame] | 261 | |
David Woodhouse | d1c9910 | 2018-02-19 10:50:56 +0000 | [diff] [blame] | 262 | .Lskip_rsb_\@: |
David Woodhouse | 117cc7a | 2018-01-12 11:11:27 +0000 | [diff] [blame] | 263 | .endm |
| 264 | |
Borislav Petkov (AMD) | 4535e1a | 2024-03-28 13:59:05 +0100 | [diff] [blame] | 265 | /* |
| 266 | * The CALL to srso_alias_untrain_ret() must be patched in directly at |
| 267 | * the spot where untraining must be done, ie., srso_alias_untrain_ret() |
| 268 | * must be the target of a CALL instruction instead of indirectly |
| 269 | * jumping to a wrapper which then calls it. Therefore, this macro is |
| 270 | * called outside of __UNTRAIN_RET below, for the time being, before the |
| 271 | * kernel can support nested alternatives with arbitrary nesting. |
| 272 | */ |
| 273 | .macro CALL_UNTRAIN_RET |
Breno Leitao | a033eec | 2023-11-21 08:07:36 -0800 | [diff] [blame] | 274 | #if defined(CONFIG_MITIGATION_UNRET_ENTRY) || defined(CONFIG_MITIGATION_SRSO) |
Borislav Petkov (AMD) | 4535e1a | 2024-03-28 13:59:05 +0100 | [diff] [blame] | 275 | ALTERNATIVE_2 "", "call entry_untrain_ret", X86_FEATURE_UNRET, \ |
| 276 | "call srso_alias_untrain_ret", X86_FEATURE_SRSO_ALIAS |
Peter Zijlstra | f43b9876 | 2022-06-27 22:21:17 +0000 | [diff] [blame] | 277 | #endif |
Borislav Petkov (AMD) | 4535e1a | 2024-03-28 13:59:05 +0100 | [diff] [blame] | 278 | .endm |
Peter Zijlstra | f43b9876 | 2022-06-27 22:21:17 +0000 | [diff] [blame] | 279 | |
Peter Zijlstra | a149180 | 2022-06-14 23:15:48 +0200 | [diff] [blame] | 280 | /* |
| 281 | * Mitigate RETBleed for AMD/Hygon Zen uarch. Requires KERNEL CR3 because the |
| 282 | * return thunk isn't mapped into the userspace tables (then again, AMD |
| 283 | * typically has NO_MELTDOWN). |
| 284 | * |
Peter Zijlstra | d025b7b | 2023-08-14 13:44:32 +0200 | [diff] [blame] | 285 | * While retbleed_untrain_ret() doesn't clobber anything but requires stack, |
Peter Zijlstra | 3ebc170 | 2022-06-14 23:16:02 +0200 | [diff] [blame] | 286 | * entry_ibpb() will clobber AX, CX, DX. |
Peter Zijlstra | a149180 | 2022-06-14 23:15:48 +0200 | [diff] [blame] | 287 | * |
| 288 | * As such, this must be placed after every *SWITCH_TO_KERNEL_CR3 at a point |
| 289 | * where we have a stack but before any RET instruction. |
| 290 | */ |
Josh Poimboeuf | e8efc08 | 2023-09-04 22:05:03 -0700 | [diff] [blame] | 291 | .macro __UNTRAIN_RET ibpb_feature, call_depth_insns |
Breno Leitao | 0911b8c | 2023-11-21 08:07:37 -0800 | [diff] [blame] | 292 | #if defined(CONFIG_MITIGATION_RETHUNK) || defined(CONFIG_MITIGATION_IBPB_ENTRY) |
Josh Poimboeuf | 4708ea1 | 2023-03-01 07:13:11 -0800 | [diff] [blame] | 293 | VALIDATE_UNRET_END |
Borislav Petkov (AMD) | 4535e1a | 2024-03-28 13:59:05 +0100 | [diff] [blame] | 294 | CALL_UNTRAIN_RET |
| 295 | ALTERNATIVE_2 "", \ |
Josh Poimboeuf | e8efc08 | 2023-09-04 22:05:03 -0700 | [diff] [blame] | 296 | "call entry_ibpb", \ibpb_feature, \ |
| 297 | __stringify(\call_depth_insns), X86_FEATURE_CALL_DEPTH |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 298 | #endif |
| 299 | .endm |
| 300 | |
Josh Poimboeuf | e8efc08 | 2023-09-04 22:05:03 -0700 | [diff] [blame] | 301 | #define UNTRAIN_RET \ |
| 302 | __UNTRAIN_RET X86_FEATURE_ENTRY_IBPB, __stringify(RESET_CALL_DEPTH) |
Peter Zijlstra | 864bcaa | 2023-08-14 13:44:35 +0200 | [diff] [blame] | 303 | |
Josh Poimboeuf | e8efc08 | 2023-09-04 22:05:03 -0700 | [diff] [blame] | 304 | #define UNTRAIN_RET_VM \ |
| 305 | __UNTRAIN_RET X86_FEATURE_IBPB_ON_VMEXIT, __stringify(RESET_CALL_DEPTH) |
| 306 | |
| 307 | #define UNTRAIN_RET_FROM_CALL \ |
| 308 | __UNTRAIN_RET X86_FEATURE_ENTRY_IBPB, __stringify(RESET_CALL_DEPTH_FROM_CALL) |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 309 | |
| 310 | |
| 311 | .macro CALL_DEPTH_ACCOUNT |
Breno Leitao | 5fa31af | 2023-11-21 08:07:30 -0800 | [diff] [blame] | 312 | #ifdef CONFIG_MITIGATION_CALL_DEPTH_TRACKING |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 313 | ALTERNATIVE "", \ |
Uros Bizjak | 2adeed9 | 2023-11-05 22:34:37 +0100 | [diff] [blame] | 314 | __stringify(INCREMENT_CALL_DEPTH), X86_FEATURE_CALL_DEPTH |
Peter Zijlstra | a149180 | 2022-06-14 23:15:48 +0200 | [diff] [blame] | 315 | #endif |
| 316 | .endm |
| 317 | |
Pawan Gupta | baf8361 | 2024-02-13 18:21:35 -0800 | [diff] [blame] | 318 | /* |
| 319 | * Macro to execute VERW instruction that mitigate transient data sampling |
| 320 | * attacks such as MDS. On affected systems a microcode update overloaded VERW |
| 321 | * instruction to also clear the CPU buffers. VERW clobbers CFLAGS.ZF. |
| 322 | * |
| 323 | * Note: Only the memory operand variant of VERW clears the CPU buffers. |
| 324 | */ |
| 325 | .macro CLEAR_CPU_BUFFERS |
Dave Hansen | 532a0c5 | 2024-03-12 07:27:57 -0700 | [diff] [blame] | 326 | ALTERNATIVE "", __stringify(verw _ASM_RIP(mds_verw_sel)), X86_FEATURE_CLEAR_CPU_BUF |
Pawan Gupta | baf8361 | 2024-02-13 18:21:35 -0800 | [diff] [blame] | 327 | .endm |
| 328 | |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 329 | #else /* __ASSEMBLY__ */ |
| 330 | |
Peter Zijlstra | 9e0e3c5 | 2018-01-17 22:34:34 +0100 | [diff] [blame] | 331 | #define ANNOTATE_RETPOLINE_SAFE \ |
| 332 | "999:\n\t" \ |
| 333 | ".pushsection .discard.retpoline_safe\n\t" \ |
Fangrui Song | b8ec60e | 2023-09-19 17:17:28 -0700 | [diff] [blame] | 334 | ".long 999b\n\t" \ |
Peter Zijlstra | 9e0e3c5 | 2018-01-17 22:34:34 +0100 | [diff] [blame] | 335 | ".popsection\n\t" |
| 336 | |
Peter Zijlstra | 1a6f744 | 2021-10-26 14:01:41 +0200 | [diff] [blame] | 337 | typedef u8 retpoline_thunk_t[RETPOLINE_THUNK_SIZE]; |
Peter Zijlstra | 369ae6f | 2022-06-14 23:15:34 +0200 | [diff] [blame] | 338 | extern retpoline_thunk_t __x86_indirect_thunk_array[]; |
Peter Zijlstra | 3b6c174 | 2022-09-15 13:11:28 +0200 | [diff] [blame] | 339 | extern retpoline_thunk_t __x86_indirect_call_thunk_array[]; |
| 340 | extern retpoline_thunk_t __x86_indirect_jump_thunk_array[]; |
Peter Zijlstra | 369ae6f | 2022-06-14 23:15:34 +0200 | [diff] [blame] | 341 | |
Breno Leitao | 0911b8c | 2023-11-21 08:07:37 -0800 | [diff] [blame] | 342 | #ifdef CONFIG_MITIGATION_RETHUNK |
Peter Zijlstra | 0b53c37 | 2022-06-14 23:15:36 +0200 | [diff] [blame] | 343 | extern void __x86_return_thunk(void); |
Peter Zijlstra | 095b830 | 2023-08-14 13:44:30 +0200 | [diff] [blame] | 344 | #else |
| 345 | static inline void __x86_return_thunk(void) {} |
| 346 | #endif |
| 347 | |
Breno Leitao | ac61d43 | 2023-11-21 08:07:34 -0800 | [diff] [blame] | 348 | #ifdef CONFIG_MITIGATION_UNRET_ENTRY |
Josh Poimboeuf | 34a3cae | 2023-09-04 22:05:00 -0700 | [diff] [blame] | 349 | extern void retbleed_return_thunk(void); |
| 350 | #else |
| 351 | static inline void retbleed_return_thunk(void) {} |
| 352 | #endif |
| 353 | |
Borislav Petkov (AMD) | 4535e1a | 2024-03-28 13:59:05 +0100 | [diff] [blame] | 354 | extern void srso_alias_untrain_ret(void); |
| 355 | |
Breno Leitao | a033eec | 2023-11-21 08:07:36 -0800 | [diff] [blame] | 356 | #ifdef CONFIG_MITIGATION_SRSO |
Josh Poimboeuf | 34a3cae | 2023-09-04 22:05:00 -0700 | [diff] [blame] | 357 | extern void srso_return_thunk(void); |
| 358 | extern void srso_alias_return_thunk(void); |
| 359 | #else |
| 360 | static inline void srso_return_thunk(void) {} |
| 361 | static inline void srso_alias_return_thunk(void) {} |
| 362 | #endif |
| 363 | |
Peter Zijlstra | d025b7b | 2023-08-14 13:44:32 +0200 | [diff] [blame] | 364 | extern void retbleed_return_thunk(void); |
Peter Zijlstra | d43490d | 2023-08-14 13:44:31 +0200 | [diff] [blame] | 365 | extern void srso_return_thunk(void); |
| 366 | extern void srso_alias_return_thunk(void); |
| 367 | |
Peter Zijlstra | e7c25c4 | 2023-08-14 13:44:34 +0200 | [diff] [blame] | 368 | extern void entry_untrain_ret(void); |
Peter Zijlstra | 3ebc170 | 2022-06-14 23:16:02 +0200 | [diff] [blame] | 369 | extern void entry_ibpb(void); |
Peter Zijlstra | 0b53c37 | 2022-06-14 23:15:36 +0200 | [diff] [blame] | 370 | |
Peter Zijlstra | 770ae1b | 2022-09-15 13:11:25 +0200 | [diff] [blame] | 371 | extern void (*x86_return_thunk)(void); |
Peter Zijlstra | 770ae1b | 2022-09-15 13:11:25 +0200 | [diff] [blame] | 372 | |
Josh Poimboeuf | 4461438a | 2024-01-03 19:36:26 +0100 | [diff] [blame] | 373 | extern void __warn_thunk(void); |
| 374 | |
Breno Leitao | 5fa31af | 2023-11-21 08:07:30 -0800 | [diff] [blame] | 375 | #ifdef CONFIG_MITIGATION_CALL_DEPTH_TRACKING |
Josh Poimboeuf | 99ee56c | 2023-09-04 22:05:04 -0700 | [diff] [blame] | 376 | extern void call_depth_return_thunk(void); |
Peter Zijlstra | ee3e246 | 2022-09-15 13:11:37 +0200 | [diff] [blame] | 377 | |
| 378 | #define CALL_DEPTH_ACCOUNT \ |
| 379 | ALTERNATIVE("", \ |
| 380 | __stringify(INCREMENT_CALL_DEPTH), \ |
| 381 | X86_FEATURE_CALL_DEPTH) |
| 382 | |
Thomas Gleixner | f5c1bb2 | 2022-09-15 13:11:30 +0200 | [diff] [blame] | 383 | #ifdef CONFIG_CALL_THUNKS_DEBUG |
| 384 | DECLARE_PER_CPU(u64, __x86_call_count); |
| 385 | DECLARE_PER_CPU(u64, __x86_ret_count); |
| 386 | DECLARE_PER_CPU(u64, __x86_stuffs_count); |
| 387 | DECLARE_PER_CPU(u64, __x86_ctxsw_count); |
| 388 | #endif |
Breno Leitao | 5fa31af | 2023-11-21 08:07:30 -0800 | [diff] [blame] | 389 | #else /* !CONFIG_MITIGATION_CALL_DEPTH_TRACKING */ |
Peter Zijlstra | ee3e246 | 2022-09-15 13:11:37 +0200 | [diff] [blame] | 390 | |
Josh Poimboeuf | 99ee56c | 2023-09-04 22:05:04 -0700 | [diff] [blame] | 391 | static inline void call_depth_return_thunk(void) {} |
Peter Zijlstra | ee3e246 | 2022-09-15 13:11:37 +0200 | [diff] [blame] | 392 | #define CALL_DEPTH_ACCOUNT "" |
| 393 | |
Breno Leitao | 5fa31af | 2023-11-21 08:07:30 -0800 | [diff] [blame] | 394 | #endif /* CONFIG_MITIGATION_CALL_DEPTH_TRACKING */ |
Thomas Gleixner | 5d82138 | 2022-09-15 13:11:27 +0200 | [diff] [blame] | 395 | |
Breno Leitao | aefb2f2 | 2023-11-21 08:07:32 -0800 | [diff] [blame] | 396 | #ifdef CONFIG_MITIGATION_RETPOLINE |
Peter Zijlstra | 1a6f744 | 2021-10-26 14:01:41 +0200 | [diff] [blame] | 397 | |
Peter Zijlstra | 6fda8a3 | 2021-10-26 14:01:40 +0200 | [diff] [blame] | 398 | #define GEN(reg) \ |
Peter Zijlstra | 1a6f744 | 2021-10-26 14:01:41 +0200 | [diff] [blame] | 399 | extern retpoline_thunk_t __x86_indirect_thunk_ ## reg; |
Peter Zijlstra | 6fda8a3 | 2021-10-26 14:01:40 +0200 | [diff] [blame] | 400 | #include <asm/GEN-for-each-reg.h> |
| 401 | #undef GEN |
| 402 | |
Peter Zijlstra | 3b6c174 | 2022-09-15 13:11:28 +0200 | [diff] [blame] | 403 | #define GEN(reg) \ |
| 404 | extern retpoline_thunk_t __x86_indirect_call_thunk_ ## reg; |
| 405 | #include <asm/GEN-for-each-reg.h> |
| 406 | #undef GEN |
| 407 | |
| 408 | #define GEN(reg) \ |
| 409 | extern retpoline_thunk_t __x86_indirect_jump_thunk_ ## reg; |
| 410 | #include <asm/GEN-for-each-reg.h> |
| 411 | #undef GEN |
| 412 | |
Zhenzhong Duan | 4cd24de | 2018-11-02 01:45:41 -0700 | [diff] [blame] | 413 | #ifdef CONFIG_X86_64 |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 414 | |
| 415 | /* |
Zhenzhong Duan | 4cd24de | 2018-11-02 01:45:41 -0700 | [diff] [blame] | 416 | * Inline asm uses the %V modifier which is only in newer GCC |
Breno Leitao | aefb2f2 | 2023-11-21 08:07:32 -0800 | [diff] [blame] | 417 | * which is ensured when CONFIG_MITIGATION_RETPOLINE is defined. |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 418 | */ |
| 419 | # define CALL_NOSPEC \ |
Zhenzhong Duan | 0cbb76d | 2018-09-18 07:45:00 -0700 | [diff] [blame] | 420 | ALTERNATIVE_2( \ |
Peter Zijlstra | 9e0e3c5 | 2018-01-17 22:34:34 +0100 | [diff] [blame] | 421 | ANNOTATE_RETPOLINE_SAFE \ |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 422 | "call *%[thunk_target]\n", \ |
Peter Zijlstra | 11925185 | 2021-03-26 16:12:02 +0100 | [diff] [blame] | 423 | "call __x86_indirect_thunk_%V[thunk_target]\n", \ |
Zhenzhong Duan | 0cbb76d | 2018-09-18 07:45:00 -0700 | [diff] [blame] | 424 | X86_FEATURE_RETPOLINE, \ |
| 425 | "lfence;\n" \ |
| 426 | ANNOTATE_RETPOLINE_SAFE \ |
| 427 | "call *%[thunk_target]\n", \ |
Peter Zijlstra (Intel) | d45476d | 2022-02-16 20:57:00 +0100 | [diff] [blame] | 428 | X86_FEATURE_RETPOLINE_LFENCE) |
Peter Zijlstra | cc1ac9c | 2020-04-16 14:34:26 +0200 | [diff] [blame] | 429 | |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 430 | # define THUNK_TARGET(addr) [thunk_target] "r" (addr) |
| 431 | |
Zhenzhong Duan | 4cd24de | 2018-11-02 01:45:41 -0700 | [diff] [blame] | 432 | #else /* CONFIG_X86_32 */ |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 433 | /* |
| 434 | * For i386 we use the original ret-equivalent retpoline, because |
| 435 | * otherwise we'll run out of registers. We don't care about CET |
| 436 | * here, anyway. |
| 437 | */ |
Andy Whitcroft | a14bff1 | 2018-03-14 11:24:27 +0000 | [diff] [blame] | 438 | # define CALL_NOSPEC \ |
Zhenzhong Duan | 0cbb76d | 2018-09-18 07:45:00 -0700 | [diff] [blame] | 439 | ALTERNATIVE_2( \ |
Andy Whitcroft | a14bff1 | 2018-03-14 11:24:27 +0000 | [diff] [blame] | 440 | ANNOTATE_RETPOLINE_SAFE \ |
| 441 | "call *%[thunk_target]\n", \ |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 442 | " jmp 904f;\n" \ |
| 443 | " .align 16\n" \ |
| 444 | "901: call 903f;\n" \ |
| 445 | "902: pause;\n" \ |
Tom Lendacky | 28d437d | 2018-01-13 17:27:30 -0600 | [diff] [blame] | 446 | " lfence;\n" \ |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 447 | " jmp 902b;\n" \ |
| 448 | " .align 16\n" \ |
Sean Christopherson | b63f20a | 2019-08-22 14:11:22 -0700 | [diff] [blame] | 449 | "903: lea 4(%%esp), %%esp;\n" \ |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 450 | " pushl %[thunk_target];\n" \ |
| 451 | " ret;\n" \ |
| 452 | " .align 16\n" \ |
| 453 | "904: call 901b;\n", \ |
Zhenzhong Duan | 0cbb76d | 2018-09-18 07:45:00 -0700 | [diff] [blame] | 454 | X86_FEATURE_RETPOLINE, \ |
| 455 | "lfence;\n" \ |
| 456 | ANNOTATE_RETPOLINE_SAFE \ |
| 457 | "call *%[thunk_target]\n", \ |
Peter Zijlstra (Intel) | d45476d | 2022-02-16 20:57:00 +0100 | [diff] [blame] | 458 | X86_FEATURE_RETPOLINE_LFENCE) |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 459 | |
| 460 | # define THUNK_TARGET(addr) [thunk_target] "rm" (addr) |
Zhenzhong Duan | 4cd24de | 2018-11-02 01:45:41 -0700 | [diff] [blame] | 461 | #endif |
David Woodhouse | 117cc7a | 2018-01-12 11:11:27 +0000 | [diff] [blame] | 462 | #else /* No retpoline for C / inline asm */ |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 463 | # define CALL_NOSPEC "call *%[thunk_target]\n" |
| 464 | # define THUNK_TARGET(addr) [thunk_target] "rm" (addr) |
| 465 | #endif |
| 466 | |
David Woodhouse | da28512 | 2018-01-11 21:46:26 +0000 | [diff] [blame] | 467 | /* The Spectre V2 mitigation variants */ |
| 468 | enum spectre_v2_mitigation { |
| 469 | SPECTRE_V2_NONE, |
Peter Zijlstra (Intel) | d45476d | 2022-02-16 20:57:00 +0100 | [diff] [blame] | 470 | SPECTRE_V2_RETPOLINE, |
| 471 | SPECTRE_V2_LFENCE, |
Peter Zijlstra | 1e19da8 | 2022-02-16 20:57:01 +0100 | [diff] [blame] | 472 | SPECTRE_V2_EIBRS, |
| 473 | SPECTRE_V2_EIBRS_RETPOLINE, |
| 474 | SPECTRE_V2_EIBRS_LFENCE, |
Pawan Gupta | 7c693f5 | 2022-06-14 23:15:55 +0200 | [diff] [blame] | 475 | SPECTRE_V2_IBRS, |
David Woodhouse | da28512 | 2018-01-11 21:46:26 +0000 | [diff] [blame] | 476 | }; |
| 477 | |
Thomas Gleixner | fa1202ef | 2018-11-25 19:33:45 +0100 | [diff] [blame] | 478 | /* The indirect branch speculation control variants */ |
| 479 | enum spectre_v2_user_mitigation { |
| 480 | SPECTRE_V2_USER_NONE, |
| 481 | SPECTRE_V2_USER_STRICT, |
Thomas Lendacky | 20c3a2c | 2018-12-13 23:03:54 +0000 | [diff] [blame] | 482 | SPECTRE_V2_USER_STRICT_PREFERRED, |
Thomas Gleixner | 9137bb2 | 2018-11-25 19:33:53 +0100 | [diff] [blame] | 483 | SPECTRE_V2_USER_PRCTL, |
Thomas Gleixner | 6b3e64c | 2018-11-25 19:33:55 +0100 | [diff] [blame] | 484 | SPECTRE_V2_USER_SECCOMP, |
Thomas Gleixner | fa1202ef | 2018-11-25 19:33:45 +0100 | [diff] [blame] | 485 | }; |
| 486 | |
Konrad Rzeszutek Wilk | 24f7fc8 | 2018-04-25 22:04:21 -0400 | [diff] [blame] | 487 | /* The Speculative Store Bypass disable variants */ |
| 488 | enum ssb_mitigation { |
| 489 | SPEC_STORE_BYPASS_NONE, |
| 490 | SPEC_STORE_BYPASS_DISABLE, |
Thomas Gleixner | a73ec77 | 2018-04-29 15:26:40 +0200 | [diff] [blame] | 491 | SPEC_STORE_BYPASS_PRCTL, |
Kees Cook | f21b53b | 2018-05-03 14:37:54 -0700 | [diff] [blame] | 492 | SPEC_STORE_BYPASS_SECCOMP, |
Konrad Rzeszutek Wilk | 24f7fc8 | 2018-04-25 22:04:21 -0400 | [diff] [blame] | 493 | }; |
| 494 | |
Linus Torvalds | 1aa7a57 | 2018-05-01 15:55:51 +0200 | [diff] [blame] | 495 | static __always_inline |
| 496 | void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature) |
| 497 | { |
| 498 | asm volatile(ALTERNATIVE("", "wrmsr", %c[feature]) |
| 499 | : : "c" (msr), |
Jim Mattson | 5f2b745 | 2018-05-13 17:33:57 -0400 | [diff] [blame] | 500 | "a" ((u32)val), |
| 501 | "d" ((u32)(val >> 32)), |
Linus Torvalds | 1aa7a57 | 2018-05-01 15:55:51 +0200 | [diff] [blame] | 502 | [feature] "i" (feature) |
| 503 | : "memory"); |
| 504 | } |
David Woodhouse | dd84441 | 2018-02-19 10:50:54 +0000 | [diff] [blame] | 505 | |
Borislav Petkov (AMD) | 1b5277c | 2023-06-29 17:43:40 +0200 | [diff] [blame] | 506 | extern u64 x86_pred_cmd; |
| 507 | |
David Woodhouse | 20ffa1c | 2018-01-25 16:14:15 +0000 | [diff] [blame] | 508 | static inline void indirect_branch_prediction_barrier(void) |
| 509 | { |
Borislav Petkov (AMD) | 1b5277c | 2023-06-29 17:43:40 +0200 | [diff] [blame] | 510 | alternative_msr_write(MSR_IA32_PRED_CMD, x86_pred_cmd, X86_FEATURE_USE_IBPB); |
David Woodhouse | 20ffa1c | 2018-01-25 16:14:15 +0000 | [diff] [blame] | 511 | } |
| 512 | |
Thomas Gleixner | fa8ac49 | 2018-05-12 20:49:16 +0200 | [diff] [blame] | 513 | /* The Intel SPEC CTRL MSR base value cache */ |
| 514 | extern u64 x86_spec_ctrl_base; |
Nathan Chancellor | db88697 | 2022-07-13 08:24:37 -0700 | [diff] [blame] | 515 | DECLARE_PER_CPU(u64, x86_spec_ctrl_current); |
Pawan Gupta | 6606515 | 2022-11-30 07:25:51 -0800 | [diff] [blame] | 516 | extern void update_spec_ctrl_cond(u64 val); |
Peter Zijlstra | bf5835b | 2022-06-14 23:15:58 +0200 | [diff] [blame] | 517 | extern u64 spec_ctrl_current(void); |
Thomas Gleixner | fa8ac49 | 2018-05-12 20:49:16 +0200 | [diff] [blame] | 518 | |
David Woodhouse | dd84441 | 2018-02-19 10:50:54 +0000 | [diff] [blame] | 519 | /* |
| 520 | * With retpoline, we must use IBRS to restrict branch prediction |
| 521 | * before calling into firmware. |
Ingo Molnar | d72f4e2 | 2018-02-21 09:20:37 +0100 | [diff] [blame] | 522 | * |
| 523 | * (Implemented as CPP macros due to header hell.) |
David Woodhouse | dd84441 | 2018-02-19 10:50:54 +0000 | [diff] [blame] | 524 | */ |
Ingo Molnar | d72f4e2 | 2018-02-21 09:20:37 +0100 | [diff] [blame] | 525 | #define firmware_restrict_branch_speculation_start() \ |
| 526 | do { \ |
| 527 | preempt_disable(); \ |
Josh Poimboeuf | e6aa136 | 2022-06-14 23:16:06 +0200 | [diff] [blame] | 528 | alternative_msr_write(MSR_IA32_SPEC_CTRL, \ |
| 529 | spec_ctrl_current() | SPEC_CTRL_IBRS, \ |
Ingo Molnar | d72f4e2 | 2018-02-21 09:20:37 +0100 | [diff] [blame] | 530 | X86_FEATURE_USE_IBRS_FW); \ |
Peter Zijlstra | 28a99e9 | 2022-07-18 13:41:37 +0200 | [diff] [blame] | 531 | alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB, \ |
| 532 | X86_FEATURE_USE_IBPB_FW); \ |
Ingo Molnar | d72f4e2 | 2018-02-21 09:20:37 +0100 | [diff] [blame] | 533 | } while (0) |
David Woodhouse | dd84441 | 2018-02-19 10:50:54 +0000 | [diff] [blame] | 534 | |
Ingo Molnar | d72f4e2 | 2018-02-21 09:20:37 +0100 | [diff] [blame] | 535 | #define firmware_restrict_branch_speculation_end() \ |
| 536 | do { \ |
Josh Poimboeuf | e6aa136 | 2022-06-14 23:16:06 +0200 | [diff] [blame] | 537 | alternative_msr_write(MSR_IA32_SPEC_CTRL, \ |
| 538 | spec_ctrl_current(), \ |
Ingo Molnar | d72f4e2 | 2018-02-21 09:20:37 +0100 | [diff] [blame] | 539 | X86_FEATURE_USE_IBRS_FW); \ |
| 540 | preempt_enable(); \ |
| 541 | } while (0) |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 542 | |
Thomas Gleixner | fa1202ef | 2018-11-25 19:33:45 +0100 | [diff] [blame] | 543 | DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp); |
Thomas Gleixner | 4c71a2b6 | 2018-11-25 19:33:49 +0100 | [diff] [blame] | 544 | DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb); |
| 545 | DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb); |
Thomas Gleixner | fa1202ef | 2018-11-25 19:33:45 +0100 | [diff] [blame] | 546 | |
Thomas Gleixner | 07f07f5 | 2019-02-18 23:04:01 +0100 | [diff] [blame] | 547 | DECLARE_STATIC_KEY_FALSE(mds_idle_clear); |
Thomas Gleixner | 04dcbdb | 2019-02-18 23:42:51 +0100 | [diff] [blame] | 548 | |
Balbir Singh | b5f06f6 | 2021-04-26 21:42:30 +0200 | [diff] [blame] | 549 | DECLARE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush); |
| 550 | |
Pawan Gupta | 8cb861e | 2022-05-19 20:29:11 -0700 | [diff] [blame] | 551 | DECLARE_STATIC_KEY_FALSE(mmio_stale_data_clear); |
| 552 | |
Pawan Gupta | baf8361 | 2024-02-13 18:21:35 -0800 | [diff] [blame] | 553 | extern u16 mds_verw_sel; |
| 554 | |
Thomas Gleixner | 6a9e529 | 2019-02-18 23:13:06 +0100 | [diff] [blame] | 555 | #include <asm/segment.h> |
| 556 | |
| 557 | /** |
Pawan Gupta | 1b42f01 | 2019-10-23 11:30:45 +0200 | [diff] [blame] | 558 | * mds_clear_cpu_buffers - Mitigation for MDS and TAA vulnerability |
Thomas Gleixner | 6a9e529 | 2019-02-18 23:13:06 +0100 | [diff] [blame] | 559 | * |
| 560 | * This uses the otherwise unused and obsolete VERW instruction in |
| 561 | * combination with microcode which triggers a CPU buffer flush when the |
| 562 | * instruction is executed. |
| 563 | */ |
Thomas Gleixner | a7ef9ba | 2020-03-04 12:49:18 +0100 | [diff] [blame] | 564 | static __always_inline void mds_clear_cpu_buffers(void) |
Thomas Gleixner | 6a9e529 | 2019-02-18 23:13:06 +0100 | [diff] [blame] | 565 | { |
| 566 | static const u16 ds = __KERNEL_DS; |
| 567 | |
| 568 | /* |
| 569 | * Has to be the memory-operand variant because only that |
| 570 | * guarantees the CPU buffer flush functionality according to |
| 571 | * documentation. The register-operand variant does not. |
| 572 | * Works with any segment selector, but a valid writable |
| 573 | * data segment is the fastest variant. |
| 574 | * |
| 575 | * "cc" clobber is required because VERW modifies ZF. |
| 576 | */ |
| 577 | asm volatile("verw %[ds]" : : [ds] "m" (ds) : "cc"); |
| 578 | } |
| 579 | |
Thomas Gleixner | 04dcbdb | 2019-02-18 23:42:51 +0100 | [diff] [blame] | 580 | /** |
Thomas Gleixner | 07f07f5 | 2019-02-18 23:04:01 +0100 | [diff] [blame] | 581 | * mds_idle_clear_cpu_buffers - Mitigation for MDS vulnerability |
| 582 | * |
| 583 | * Clear CPU buffers if the corresponding static key is enabled |
| 584 | */ |
Peter Zijlstra | 10fdb38 | 2023-01-12 20:43:45 +0100 | [diff] [blame] | 585 | static __always_inline void mds_idle_clear_cpu_buffers(void) |
Thomas Gleixner | 07f07f5 | 2019-02-18 23:04:01 +0100 | [diff] [blame] | 586 | { |
| 587 | if (static_branch_likely(&mds_idle_clear)) |
| 588 | mds_clear_cpu_buffers(); |
| 589 | } |
| 590 | |
David Woodhouse | 76b0438 | 2018-01-11 21:46:25 +0000 | [diff] [blame] | 591 | #endif /* __ASSEMBLY__ */ |
Daniel Borkmann | a493a87 | 2018-02-22 15:12:53 +0100 | [diff] [blame] | 592 | |
Borislav Petkov | 7a32fc5 | 2018-01-26 13:11:37 +0100 | [diff] [blame] | 593 | #endif /* _ASM_X86_NOSPEC_BRANCH_H_ */ |