Pull x86 core updates from Borislav Petkov: - Have invalid MSR accesses warnings appear only once after a pr_warn_once() change broke that - Simplify {JMP,CALL}_NOSPEC and let the objtool retpoline patching infra take care of them instead of having unreadable alternative macros there * tag 'x86_core_for_v6.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/extable: Fix ex_handler_msr() print condition x86,nospec: Simplify {JMP,CALL}_NOSPEC
Unified · Split
| @@ -93,6 +93,19 @@ · 92 unmodified lines | |||
| 93 | #endif | 93 | #endif |
| 94 | .endm | 94 | .endm |
| 95 | 95 | ||
| 96 | /* | ||
| 97 | * Equivalent to -mindirect-branch-cs-prefix; emit the 5 byte jmp/call | ||
| 98 | * to the retpoline thunk with a CS prefix when the register requires | ||
| 99 | * a RAX prefix byte to encode. Also see apply_retpolines(). | ||
| 100 | */ | ||
| 101 | .macro __CS_PREFIX reg:req | ||
| 102 | .irp rs,r8,r9,r10,r11,r12,r13,r14,r15 | ||
| 103 | .ifc \reg,\rs | ||
| 104 | .byte 0x2e | ||
| 105 | .endif | ||
| 106 | .endr | ||
| 107 | .endm | ||
| 108 | |||
| 96 | /* | 109 | /* |
| 97 | * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple | 110 | * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple |
| 98 | * indirect jmp/call which may be susceptible to the Spectre variant 2 | 111 | * indirect jmp/call which may be susceptible to the Spectre variant 2 |
| @@ -100,19 +113,18 @@ · 1 unmodified line | |||
| 100 | */ | 113 | */ |
| 101 | .macro JMP_NOSPEC reg:req | 114 | .macro JMP_NOSPEC reg:req |
| 102 | #ifdef CONFIG_RETPOLINE | 115 | #ifdef CONFIG_RETPOLINE |
| 103 | ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ | 116 | __CS_PREFIX \reg |
| 104 | __stringify(jmp __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ | 117 | jmp __x86_indirect_thunk_\reg |
| 105 | __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE | ||
| 106 | #else | 118 | #else |
| 107 | jmp *%\reg | 119 | jmp *%\reg |
| 120 | int3 | ||
| 108 | #endif | 121 | #endif |
| 109 | .endm | 122 | .endm |
| 110 | 123 | ||
| 111 | .macro CALL_NOSPEC reg:req | 124 | .macro CALL_NOSPEC reg:req |
| 112 | #ifdef CONFIG_RETPOLINE | 125 | #ifdef CONFIG_RETPOLINE |
| 113 | ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *%\reg), \ | 126 | __CS_PREFIX \reg |
| 114 | __stringify(call __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ | 127 | call __x86_indirect_thunk_\reg |
| 115 | __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *%\reg), X86_FEATURE_RETPOLINE_LFENCE | ||
| 116 | #else | 128 | #else |
| 117 | call *%\reg | 129 | call *%\reg |
| 118 | #endif | 130 | #endif |
| @@ -94,16 +94,18 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup, · 93 unmodified lines | |||
| 94 | static bool ex_handler_msr(const struct exception_table_entry *fixup, | 94 | static bool ex_handler_msr(const struct exception_table_entry *fixup, |
| 95 | struct pt_regs *regs, bool wrmsr, bool safe, int reg) | 95 | struct pt_regs *regs, bool wrmsr, bool safe, int reg) |
| 96 | { | 96 | { |
| 97 | if (!safe && wrmsr && | 97 | if (__ONCE_LITE_IF(!safe && wrmsr)) { |
| 98 | pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", | 98 | pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", |
| 99 | (unsigned int)regs->cx, (unsigned int)regs->dx, | 99 | (unsigned int)regs->cx, (unsigned int)regs->dx, |
| 100 | (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) | 100 | (unsigned int)regs->ax, regs->ip, (void *)regs->ip); |
| 101 | show_stack_regs(regs); | 101 | show_stack_regs(regs); |
| 102 | } | ||
| 102 | 103 | ||
| 103 | if (!safe && !wrmsr && | 104 | if (__ONCE_LITE_IF(!safe && !wrmsr)) { |
| 104 | pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", | 105 | pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", |
| 105 | (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) | 106 | (unsigned int)regs->cx, regs->ip, (void *)regs->ip); |
| 106 | show_stack_regs(regs); | 107 | show_stack_regs(regs); |
| 108 | } | ||
| 107 | 109 | ||
| 108 | if (!wrmsr) { | 110 | if (!wrmsr) { |
| 109 | /* Pretend that the read succeeded and returned 0. */ | 111 | /* Pretend that the read succeeded and returned 0. */ |
| @@ -9,15 +9,27 @@ · 8 unmodified lines | |||
| 9 | */ | 9 | */ |
| 10 | #define DO_ONCE_LITE(func, ...) \ | 10 | #define DO_ONCE_LITE(func, ...) \ |
| 11 | DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) | 11 | DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) |
| 12 | #define DO_ONCE_LITE_IF(condition, func, ...) \ | 12 | |
| 13 | #define __ONCE_LITE_IF(condition) \ | ||
| 13 | ({ \ | 14 | ({ \ |
| 14 | static bool __section(".data.once") __already_done; \ | 15 | static bool __section(".data.once") __already_done; \ |
| 15 | bool __ret_do_once = !!(condition); \ | 16 | bool __ret_cond = !!(condition); \ |
| 17 | bool __ret_once = false; \ | ||
| 16 | \ | 18 | \ |
| 17 | if (unlikely(__ret_do_once && !__already_done)) { \ | 19 | if (unlikely(__ret_cond && !__already_done)) { \ |
| 18 | __already_done = true; \ | 20 | __already_done = true; \ |
| 19 | func(__VA_ARGS__); \ | 21 | __ret_once = true; \ |
| 20 | } \ | 22 | } \ |
| 23 | unlikely(__ret_once); \ | ||
| 24 | }) | ||
| 25 | |||
| 26 | #define DO_ONCE_LITE_IF(condition, func, ...) \ | ||
| 27 | ({ \ | ||
| 28 | bool __ret_do_once = !!(condition); \ | ||
| 29 | \ | ||
| 30 | if (__ONCE_LITE_IF(__ret_do_once)) \ | ||
| 31 | func(__VA_ARGS__); \ | ||
| 32 | \ | ||
| 21 | unlikely(__ret_do_once); \ | 33 | unlikely(__ret_do_once); \ |
| 22 | }) | 34 | }) |
| 23 | 35 | ||