Commit 85a2d939 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Thomas Gleixner:
 "Yet another pile of melted spectrum related changes:

   - sanitize the array_index_nospec protection mechanism: Remove the
     overengineered array_index_nospec_mask_check() magic and allow
     const-qualified types as index to avoid temporary storage in a
     non-const local variable.

   - make the microcode loader more robust by properly propagating error
     codes. Provide information about new feature bits after micro code
     was updated so administrators can act upon.

   - optimizations of the entry ASM code which reduce code footprint and
     make the code simpler and faster.

   - fix the {pmd,pud}_{set,clear}_flags() implementations to work
     properly on paravirt kernels by removing the address translation
     operations.

   - revert the harmful vmexit_fill_RSB() optimization

   - use IBRS around firmware calls

   - teach objtool about retpolines and add...
parents d4858aaf 946fbbc1
...@@ -489,6 +489,11 @@ KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) ...@@ -489,6 +489,11 @@ KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
endif endif
RETPOLINE_CFLAGS_GCC := -mindirect-branch=thunk-extern -mindirect-branch-register
RETPOLINE_CFLAGS_CLANG := -mretpoline-external-thunk
RETPOLINE_CFLAGS := $(call cc-option,$(RETPOLINE_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_CFLAGS_CLANG)))
export RETPOLINE_CFLAGS
ifeq ($(config-targets),1) ifeq ($(config-targets),1)
# =========================================================================== # ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend # *config targets only - make sure prerequisites are updated, and descend
......
...@@ -430,6 +430,7 @@ config GOLDFISH ...@@ -430,6 +430,7 @@ config GOLDFISH
config RETPOLINE config RETPOLINE
bool "Avoid speculative indirect branches in kernel" bool "Avoid speculative indirect branches in kernel"
default y default y
select STACK_VALIDATION if HAVE_STACK_VALIDATION
help help
Compile kernel with the retpoline compiler options to guard against Compile kernel with the retpoline compiler options to guard against
kernel-to-user data leaks by avoiding speculative indirect kernel-to-user data leaks by avoiding speculative indirect
......
...@@ -232,10 +232,9 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables ...@@ -232,10 +232,9 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
# Avoid indirect branches in kernel to deal with Spectre # Avoid indirect branches in kernel to deal with Spectre
ifdef CONFIG_RETPOLINE ifdef CONFIG_RETPOLINE
RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) ifneq ($(RETPOLINE_CFLAGS),)
ifneq ($(RETPOLINE_CFLAGS),) KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE
KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE endif
endif
endif endif
archscripts: scripts_basic archscripts: scripts_basic
......
...@@ -97,7 +97,7 @@ For 32-bit we have the following conventions - kernel is built with ...@@ -97,7 +97,7 @@ For 32-bit we have the following conventions - kernel is built with
#define SIZEOF_PTREGS 21*8 #define SIZEOF_PTREGS 21*8
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax .macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
/* /*
* Push registers and sanitize registers of values that a * Push registers and sanitize registers of values that a
* speculation attack might otherwise want to exploit. The * speculation attack might otherwise want to exploit. The
...@@ -105,32 +105,41 @@ For 32-bit we have the following conventions - kernel is built with ...@@ -105,32 +105,41 @@ For 32-bit we have the following conventions - kernel is built with
* could be put to use in a speculative execution gadget. * could be put to use in a speculative execution gadget.
* Interleave XOR with PUSH for better uop scheduling: * Interleave XOR with PUSH for better uop scheduling:
*/ */
.if \save_ret
pushq %rsi /* pt_regs->si */
movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */
movq %rdi, 8(%rsp) /* pt_regs->di (overwriting original return address) */
.else
pushq %rdi /* pt_regs->di */ pushq %rdi /* pt_regs->di */
pushq %rsi /* pt_regs->si */ pushq %rsi /* pt_regs->si */
.endif
pushq \rdx /* pt_regs->dx */ pushq \rdx /* pt_regs->dx */
pushq %rcx /* pt_regs->cx */ pushq %rcx /* pt_regs->cx */
pushq \rax /* pt_regs->ax */ pushq \rax /* pt_regs->ax */
pushq %r8 /* pt_regs->r8 */ pushq %r8 /* pt_regs->r8 */
xorq %r8, %r8 /* nospec r8 */ xorl %r8d, %r8d /* nospec r8 */
pushq %r9 /* pt_regs->r9 */ pushq %r9 /* pt_regs->r9 */
xorq %r9, %r9 /* nospec r9 */ xorl %r9d, %r9d /* nospec r9 */
pushq %r10 /* pt_regs->r10 */ pushq %r10 /* pt_regs->r10 */
xorq %r10, %r10 /* nospec r10 */ xorl %r10d, %r10d /* nospec r10 */
pushq %r11 /* pt_regs->r11 */ pushq %r11 /* pt_regs->r11 */
xorq %r11, %r11 /* nospec r11*/ xorl %r11d, %r11d /* nospec r11*/
pushq %rbx /* pt_regs->rbx */ pushq %rbx /* pt_regs->rbx */
xorl %ebx, %ebx /* nospec rbx*/ xorl %ebx, %ebx /* nospec rbx*/
pushq %rbp /* pt_regs->rbp */ pushq %rbp /* pt_regs->rbp */
xorl %ebp, %ebp /* nospec rbp*/ xorl %ebp, %ebp /* nospec rbp*/
pushq %r12 /* pt_regs->r12 */ pushq %r12 /* pt_regs->r12 */
xorq %r12, %r12 /* nospec r12*/ xorl %r12d, %r12d /* nospec r12*/
pushq %r13 /* pt_regs->r13 */ pushq %r13 /* pt_regs->r13 */
xorq %r13, %r13 /* nospec r13*/ xorl %r13d, %r13d /* nospec r13*/
pushq %r14 /* pt_regs->r14 */ pushq %r14 /* pt_regs->r14 */
xorq %r14, %r14 /* nospec r14*/ xorl %r14d, %r14d /* nospec r14*/
pushq %r15 /* pt_regs->r15 */ pushq %r15 /* pt_regs->r15 */
xorq %r15, %r15 /* nospec r15*/ xorl %r15d, %r15d /* nospec r15*/
UNWIND_HINT_REGS UNWIND_HINT_REGS
.if \save_ret
pushq %rsi /* return address on top of stack */
.endif
.endm .endm
.macro POP_REGS pop_rdi=1 skip_r11rcx=0 .macro POP_REGS pop_rdi=1 skip_r11rcx=0
...@@ -172,12 +181,7 @@ For 32-bit we have the following conventions - kernel is built with ...@@ -172,12 +181,7 @@ For 32-bit we have the following conventions - kernel is built with
*/ */
.macro ENCODE_FRAME_POINTER ptregs_offset=0 .macro ENCODE_FRAME_POINTER ptregs_offset=0
#ifdef CONFIG_FRAME_POINTER #ifdef CONFIG_FRAME_POINTER
.if \ptregs_offset leaq 1+\ptregs_offset(%rsp), %rbp
leaq \ptregs_offset(%rsp), %rbp
.else
mov %rsp, %rbp
.endif
orq $0x1, %rbp
#endif #endif
.endm .endm
......
...@@ -252,8 +252,7 @@ ENTRY(__switch_to_asm) ...@@ -252,8 +252,7 @@ ENTRY(__switch_to_asm)
* exist, overwrite the RSB with entries which capture * exist, overwrite the RSB with entries which capture
* speculative execution to prevent attack. * speculative execution to prevent attack.
*/ */
/* Clobbers %ebx */ FILL_RETURN_BUFFER %ebx, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
FILL_RETURN_BUFFER RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
#endif #endif
/* restore callee-saved registers */ /* restore callee-saved registers */
......
...@@ -364,8 +364,7 @@ ENTRY(__switch_to_asm) ...@@ -364,8 +364,7 @@ ENTRY(__switch_to_asm)
* exist, overwrite the RSB with entries which capture * exist, overwrite the RSB with entries which capture
* speculative execution to prevent attack. * speculative execution to prevent attack.
*/ */
/* Clobbers %rbx */ FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
FILL_RETURN_BUFFER RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
#endif #endif
/* restore callee-saved registers */ /* restore callee-saved registers */
...@@ -449,9 +448,19 @@ END(irq_entries_start) ...@@ -449,9 +448,19 @@ END(irq_entries_start)
* *
* The invariant is that, if irq_count != -1, then the IRQ stack is in use. * The invariant is that, if irq_count != -1, then the IRQ stack is in use.
*/ */
.macro ENTER_IRQ_STACK regs=1 old_rsp .macro ENTER_IRQ_STACK regs=1 old_rsp save_ret=0
DEBUG_ENTRY_ASSERT_IRQS_OFF DEBUG_ENTRY_ASSERT_IRQS_OFF
.if \save_ret
/*
* If save_ret is set, the original stack contains one additional
* entry -- the return address. Therefore, move the address one
* entry below %rsp to \old_rsp.
*/
leaq 8(%rsp), \old_rsp
.else
movq %rsp, \old_rsp movq %rsp, \old_rsp
.endif
.if \regs .if \regs
UNWIND_HINT_REGS base=\old_rsp UNWIND_HINT_REGS base=\old_rsp
...@@ -497,6 +506,15 @@ END(irq_entries_start) ...@@ -497,6 +506,15 @@ END(irq_entries_start)
.if \regs .if \regs
UNWIND_HINT_REGS indirect=1 UNWIND_HINT_REGS indirect=1
.endif .endif
.if \save_ret
/*
* Push the return address to the stack. This return address can
* be found at the "real" original RSP, which was offset by 8 at
* the beginning of this macro.
*/
pushq -8(\old_rsp)
.endif
.endm .endm
/* /*
...@@ -520,27 +538,65 @@ END(irq_entries_start) ...@@ -520,27 +538,65 @@ END(irq_entries_start)
.endm .endm
/* /*
* Interrupt entry/exit. * Interrupt entry helper function.
*
* Interrupt entry points save only callee clobbered registers in fast path.
* *
* Entry runs with interrupts off. * Entry runs with interrupts off. Stack layout at entry:
* +----------------------------------------------------+
* | regs->ss |
* | regs->rsp |
* | regs->eflags |
* | regs->cs |
* | regs->ip |
* +----------------------------------------------------+
* | regs->orig_ax = ~(interrupt number) |
* +----------------------------------------------------+
* | return address |
* +----------------------------------------------------+
*/ */
ENTRY(interrupt_entry)
/* 0(%rsp): ~(interrupt number) */ UNWIND_HINT_FUNC
.macro interrupt func ASM_CLAC
cld cld
testb $3, CS-ORIG_RAX(%rsp) testb $3, CS-ORIG_RAX+8(%rsp)
jz 1f jz 1f
SWAPGS SWAPGS
call switch_to_thread_stack
/*
* Switch to the thread stack. The IRET frame and orig_ax are
* on the stack, as well as the return address. RDI..R12 are
* not (yet) on the stack and space has not (yet) been
* allocated for them.
*/
pushq %rdi
/* Need to switch before accessing the thread stack. */
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
movq %rsp, %rdi
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
/*
* We have RDI, return address, and orig_ax on the stack on
* top of the IRET frame. That means offset=24
*/
UNWIND_HINT_IRET_REGS base=%rdi offset=24
pushq 7*8(%rdi) /* regs->ss */
pushq 6*8(%rdi) /* regs->rsp */
pushq 5*8(%rdi) /* regs->eflags */
pushq 4*8(%rdi) /* regs->cs */
pushq 3*8(%rdi) /* regs->ip */
pushq 2*8(%rdi) /* regs->orig_ax */
pushq 8(%rdi) /* return address */
UNWIND_HINT_FUNC
movq (%rdi), %rdi
1: 1:
PUSH_AND_CLEAR_REGS PUSH_AND_CLEAR_REGS save_ret=1
ENCODE_FRAME_POINTER ENCODE_FRAME_POINTER 8
testb $3, CS(%rsp) testb $3, CS+8(%rsp)
jz 1f jz 1f
/* /*
...@@ -548,7 +604,7 @@ END(irq_entries_start) ...@@ -548,7 +604,7 @@ END(irq_entries_start)
* *
* We need to tell lockdep that IRQs are off. We can't do this until * We need to tell lockdep that IRQs are off. We can't do this until
* we fix gsbase, and we should do it before enter_from_user_mode * we fix gsbase, and we should do it before enter_from_user_mode
* (which can take locks). Since TRACE_IRQS_OFF idempotent, * (which can take locks). Since TRACE_IRQS_OFF is idempotent,
* the simplest way to handle it is to just call it twice if * the simplest way to handle it is to just call it twice if
* we enter from user mode. There's no reason to optimize this since * we enter from user mode. There's no reason to optimize this since
* TRACE_IRQS_OFF is a no-op if lockdep is off. * TRACE_IRQS_OFF is a no-op if lockdep is off.
...@@ -558,12 +614,15 @@ END(irq_entries_start) ...@@ -558,12 +614,15 @@ END(irq_entries_start)
CALL_enter_from_user_mode CALL_enter_from_user_mode
1: 1:
ENTER_IRQ_STACK old_rsp=%rdi ENTER_IRQ_STACK old_rsp=%rdi save_ret=1
/* We entered an interrupt context - irqs are off: */ /* We entered an interrupt context - irqs are off: */
TRACE_IRQS_OFF TRACE_IRQS_OFF
call \func /* rdi points to pt_regs */ ret
.endm END(interrupt_entry)
/* Interrupt entry/exit. */
/* /*
* The interrupt stubs push (~vector+0x80) onto the stack and * The interrupt stubs push (~vector+0x80) onto the stack and
...@@ -571,9 +630,10 @@ END(irq_entries_start) ...@@ -571,9 +630,10 @@ END(irq_entries_start)
*/ */
.p2align CONFIG_X86_L1_CACHE_SHIFT .p2align CONFIG_X86_L1_CACHE_SHIFT
common_interrupt: common_interrupt:
ASM_CLAC
addq $-0x80, (%rsp) /* Adjust vector to [-256, -1] range */ addq $-0x80, (%rsp) /* Adjust vector to [-256, -1] range */
interrupt do_IRQ call interrupt_entry
UNWIND_HINT_REGS indirect=1
call do_IRQ /* rdi points to pt_regs */
/* 0(%rsp): old RSP */ /* 0(%rsp): old RSP */
ret_from_intr: ret_from_intr:
DISABLE_INTERRUPTS(CLBR_ANY) DISABLE_INTERRUPTS(CLBR_ANY)
...@@ -766,10 +826,11 @@ END(common_interrupt) ...@@ -766,10 +826,11 @@ END(common_interrupt)
.macro apicinterrupt3 num sym do_sym .macro apicinterrupt3 num sym do_sym
ENTRY(\sym) ENTRY(\sym)
UNWIND_HINT_IRET_REGS UNWIND_HINT_IRET_REGS
ASM_CLAC
pushq $~(\num) pushq $~(\num)
.Lcommon_\sym: .Lcommon_\sym:
interrupt \do_sym call interrupt_entry
UNWIND_HINT_REGS indirect=1
call \do_sym /* rdi points to pt_regs */
jmp ret_from_intr jmp ret_from_intr
END(\sym) END(\sym)
.endm .endm
...@@ -832,34 +893,6 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt ...@@ -832,34 +893,6 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt
*/ */
#define CPU_TSS_IST(x) PER_CPU_VAR(cpu_tss_rw) + (TSS_ist + ((x) - 1) * 8) #define CPU_TSS_IST(x) PER_CPU_VAR(cpu_tss_rw) + (TSS_ist + ((x) - 1) * 8)
/*
* Switch to the thread stack. This is called with the IRET frame and
* orig_ax on the stack. (That is, RDI..R12 are not on the stack and
* space has not been allocated for them.)
*/
ENTRY(switch_to_thread_stack)
UNWIND_HINT_FUNC
pushq %rdi
/* Need to switch before accessing the thread stack. */
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
movq %rsp, %rdi
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
UNWIND_HINT sp_offset=16 sp_reg=ORC_REG_DI
pushq 7*8(%rdi) /* regs->ss */
pushq 6*8(%rdi) /* regs->rsp */
pushq 5*8(%rdi) /* regs->eflags */
pushq 4*8(%rdi) /* regs->cs */
pushq 3*8(%rdi) /* regs->ip */
pushq 2*8(%rdi) /* regs->orig_ax */
pushq 8(%rdi) /* return address */
UNWIND_HINT_FUNC
movq (%rdi), %rdi
ret
END(switch_to_thread_stack)
.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 .macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1
ENTRY(\sym) ENTRY(\sym)
UNWIND_HINT_IRET_REGS offset=\has_error_code*8 UNWIND_HINT_IRET_REGS offset=\has_error_code*8
...@@ -875,12 +908,8 @@ ENTRY(\sym) ...@@ -875,12 +908,8 @@ ENTRY(\sym)
pushq $-1 /* ORIG_RAX: no syscall to restart */ pushq $-1 /* ORIG_RAX: no syscall to restart */
.endif .endif
/* Save all registers in pt_regs */
PUSH_AND_CLEAR_REGS
ENCODE_FRAME_POINTER
.if \paranoid < 2 .if \paranoid < 2
testb $3, CS(%rsp) /* If coming from userspace, switch stacks */ testb $3, CS-ORIG_RAX(%rsp) /* If coming from userspace, switch stacks */
jnz .Lfrom_usermode_switch_stack_\@ jnz .Lfrom_usermode_switch_stack_\@
.endif .endif
...@@ -1130,13 +1159,15 @@ idtentry machine_check do_mce has_error_code=0 paranoid=1 ...@@ -1130,13 +1159,15 @@ idtentry machine_check do_mce has_error_code=0 paranoid=1
#endif #endif
/* /*
* Switch gs if needed. * Save all registers in pt_regs, and switch gs if needed.
* Use slow, but surefire "are we in kernel?" check. * Use slow, but surefire "are we in kernel?" check.
* Return: ebx=0: need swapgs on exit, ebx=1: otherwise * Return: ebx=0: need swapgs on exit, ebx=1: otherwise
*/ */
ENTRY(paranoid_entry) ENTRY(paranoid_entry)
UNWIND_HINT_FUNC UNWIND_HINT_FUNC
cld cld
PUSH_AND_CLEAR_REGS save_ret=1
ENCODE_FRAME_POINTER 8
movl $1, %ebx movl $1, %ebx
movl $MSR_GS_BASE, %ecx movl $MSR_GS_BASE, %ecx
rdmsr rdmsr
...@@ -1181,12 +1212,14 @@ ENTRY(paranoid_exit) ...@@ -1181,12 +1212,14 @@ ENTRY(paranoid_exit)
END(paranoid_exit) END(paranoid_exit)
/* /*
* Switch gs if needed. * Save all registers in pt_regs, and switch GS if needed.
* Return: EBX=0: came from user mode; EBX=1: otherwise * Return: EBX=0: came from user mode; EBX=1: otherwise
*/ */
ENTRY(error_entry) ENTRY(error_entry)
UNWIND_HINT_REGS offset=8 UNWIND_HINT_FUNC
cld cld
PUSH_AND_CLEAR_REGS save_ret=1
ENCODE_FRAME_POINTER 8
testb $3, CS+8(%rsp) testb $3, CS+8(%rsp)
jz .Lerror_kernelspace jz .Lerror_kernelspace
...@@ -1577,8 +1610,6 @@ end_repeat_nmi: ...@@ -1577,8 +1610,6 @@ end_repeat_nmi:
* frame to point back to repeat_nmi. * frame to point back to repeat_nmi.
*/ */
pushq $-1 /* ORIG_RAX: no syscall to restart */ pushq $-1 /* ORIG_RAX: no syscall to restart */
PUSH_AND_CLEAR_REGS
ENCODE_FRAME_POINTER
/* /*
* Use paranoid_entry to handle SWAPGS, but no need to use paranoid_exit * Use paranoid_entry to handle SWAPGS, but no need to use paranoid_exit
......
...@@ -85,25 +85,25 @@ ENTRY(entry_SYSENTER_compat) ...@@ -85,25 +85,25 @@ ENTRY(entry_SYSENTER_compat)
pushq %rcx /* pt_regs->cx */ pushq %rcx /* pt_regs->cx */
pushq $-ENOSYS /* pt_regs->ax */ pushq $-ENOSYS /* pt_regs->ax */
pushq $0 /* pt_regs->r8 = 0 */ pushq $0 /* pt_regs->r8 = 0 */
xorq %r8, %r8 /* nospec r8 */ xorl %r8d, %r8d /* nospec r8 */
pushq $0 /* pt_regs->r9 = 0 */ pushq $0 /* pt_regs->r9 = 0 */
xorq %r9, %r9 /* nospec r9 */ xorl %r9d, %r9d /* nospec r9 */
pushq $0 /* pt_regs->r10 = 0 */ pushq $0 /* pt_regs->r10 = 0 */
xorq %r10, %r10 /* nospec r10 */ xorl %r10d, %r10d /* nospec r10 */
pushq $0 /* pt_regs->r11 = 0 */ pushq $0 /* pt_regs->r11 = 0 */
xorq %r11, %r11 /* nospec r11 */ xorl %r11d, %r11d /* nospec r11 */
pushq %rbx /* pt_regs->rbx */ pushq %rbx /* pt_regs->rbx */
xorl %ebx, %ebx /* nospec rbx */ xorl %ebx, %ebx /* nospec rbx */
pushq %rbp /* pt_regs->rbp (will be overwritten) */ pushq %rbp /* pt_regs->rbp (will be overwritten) */
xorl %ebp, %ebp /* nospec rbp */ xorl %ebp, %ebp /* nospec rbp */
pushq $0 /* pt_regs->r12 = 0 */ pushq $0 /* pt_regs->r12 = 0 */
xorq %r12, %r12 /* nospec r12 */ xorl %r12d, %r12d /* nospec r12 */
pushq $0 /* pt_regs->r13 = 0 */ pushq $0 /* pt_regs->r13 = 0 */
xorq %r13, %r13 /* nospec r13 */ xorl %r13d, %r13d /* nospec r13 */
pushq $0 /* pt_regs->r14 = 0 */ pushq $0 /* pt_regs->r14 = 0 */
xorq %r14, %r14 /* nospec r14 */ xorl %r14d, %r14d /* nospec r14 */
pushq $0 /* pt_regs->r15 = 0 */ pushq $0 /* pt_regs->r15 = 0 */
xorq %r15, %r15 /* nospec r15 */ xorl %r15d, %r15d /* nospec r15 */
cld cld
/* /*
...@@ -224,25 +224,25 @@ GLOBAL(entry_SYSCALL_compat_after_hwframe) ...@@ -224,25 +224,25 @@ GLOBAL(entry_SYSCALL_compat_after_hwframe)
pushq %rbp /* pt_regs->cx (stashed in bp) */ pushq %rbp /* pt_regs->cx (stashed in bp) */
pushq $-ENOSYS /* pt_regs->ax */ pushq $-ENOSYS /* pt_regs->ax */
pushq $0 /* pt_regs->r8 = 0 */ pushq $0 /* pt_regs->r8 = 0 */
xorq %r8, %r8 /* nospec r8 */ xorl %r8d, %r8d /* nospec r8 */
pushq $0 /* pt_regs->r9 = 0 */ pushq $0 /* pt_regs->r9 = 0 */
xorq %r9, %r9 /* nospec r9 */ xorl %r9d, %r9d /* nospec r9 */
pushq $0 /* pt_regs->r10 = 0 */ pushq $0 /* pt_regs->r10 = 0 */
xorq %r10, %r10 /* nospec r10 */ xorl %r10d, %r10d /* nospec r10 */
pushq $0 /* pt_regs->r11 = 0 */ pushq $0 /* pt_regs->r11 = 0 */
xorq %r11, %r11 /* nospec r11 */ xorl %r11d, %r11d /* nospec r11 */
pushq %rbx /* pt_regs->rbx */ pushq %rbx /* pt_regs->rbx */
xorl %ebx, %ebx /* nospec rbx */ xorl %ebx, %ebx /* nospec rbx */
pushq %rbp /* pt_regs->rbp (will be overwritten) */ pushq %rbp /* pt_regs->rbp (will be overwritten) */
xorl %ebp, %ebp /* nospec rbp */ xorl %ebp, %ebp /* nospec rbp */
pushq $0 /* pt_regs->r12 = 0 */ pushq $0 /* pt_regs->r12 = 0 */
xorq %r12, %r12 /* nospec r12 */ xorl %r12d, %r12d /* nospec r12 */
pushq $0 /* pt_regs->r13 = 0 */ pushq $0 /* pt_regs->r13 = 0 */
xorq %r13, %r13 /* nospec r13 */ xorl %r13d, %r13d /* nospec r13 */
pushq $0 /* pt_regs->r14 = 0 */ pushq $0 /* pt_regs->r14 = 0 */
xorq %r14, %r14 /* nospec r14 */ xorl %r14d, %r14d /* nospec r14 */
pushq $0 /* pt_regs->r15 = 0 */ pushq $0 /* pt_regs->r15 = 0 */
xorq %r15, %r15 /* nospec r15 */ xorl %r15d, %r15d /* nospec r15 */
/* /*
* User mode is traced as though IRQs are on, and SYSENTER * User mode is traced as though IRQs are on, and SYSENTER
...@@ -298,9 +298,9 @@ sysret32_from_system_call: ...@@ -298,9 +298,9 @@ sysret32_from_system_call:
*/ */
SWITCH_TO_USER_CR3_NOSTACK scratch_reg=%r8 scratch_reg2=%r9 SWITCH_TO_USER_CR3_NOSTACK scratch_reg=%r8 scratch_reg2=%r9
xorq %r8, %r8 xorl %r8d, %r8d
xorq %r9, %r9 xorl %r9d, %r9d
xorq %r10, %r10 xorl %r10d, %r10d
swapgs swapgs
sysretl sysretl
END(entry_SYSCALL_compat) END(entry_SYSCALL_compat)
...@@ -347,10 +347,23 @@ ENTRY(entry_INT80_compat) ...@@ -347,10 +347,23 @@ ENTRY(entry_INT80_compat)
*/ */
movl %eax, %eax movl %eax, %eax
/* switch to thread stack expects orig_ax and rdi to be pushed */
pushq %rax /* pt_regs->orig_ax */ pushq %rax /* pt_regs->orig_ax */
pushq %rdi /* pt_regs->di */
/* Need to switch before accessing the thread stack. */
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
movq %rsp, %rdi
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
pushq 6*8(%rdi) /* regs->ss */
pushq 5*8(%rdi) /* regs->rsp */
pushq 4*8(%rdi) /* regs->eflags */
pushq 3*8(%rdi) /* regs->cs */
pushq 2*8(%rdi) /* regs->ip */
pushq 1*8(%rdi) /* regs->orig_ax */
/* switch to thread stack expects orig_ax to be pushed */ movq (%rdi), %rdi /* restore %rdi */
call switch_to_thread_stack
pushq %rdi /* pt_regs->di */ pushq %rdi /* pt_regs->di */
pushq %rsi /* pt_regs->si */ pushq %rsi /* pt_regs->si */
...@@ -358,25 +371,25 @@ ENTRY(entry_INT80_compat) ...@@ -358,25 +371,25 @@ ENTRY(entry_INT80_compat)
pushq %rcx /* pt_regs->cx */ pushq %rcx /* pt_regs->cx */
pushq $-ENOSYS /* pt_regs->ax */ pushq $-ENOSYS /* pt_regs->ax */
pushq $0 /* pt_regs->r8 = 0 */ pushq $0 /* pt_regs->r8 = 0 */
xorq %r8, %r8 /* nospec r8 */ xorl %r8d, %r8d /* nospec r8 */
pushq $0 /* pt_regs->r9 = 0 */ pushq $0 /* pt_regs->r9 = 0 */
xorq %r9, %r9 /* nospec r9 */ xorl %r9d, %r9d /* nospec r9 */
pushq $0 /* pt_regs->r10 = 0 */ pushq $0 /* pt_regs->r10 = 0 */
xorq %r10, %r10 /* nospec r10 */ xorl %r10d, %r10d /* nospec r10 */
pushq $0 /* pt_regs->r11 = 0 */ pushq $0 /* pt_regs->r11 = 0 */
xorq %r11, %r11 /* nospec r11 */ xorl %r11d, %r11d /* nospec r11 */
pushq %rbx /* pt_regs->rbx */ pushq %rbx /* pt_regs->rbx */
xorl %ebx, %ebx /* nospec rbx */ xorl %ebx, %ebx /* nospec rbx */
pushq %rbp /* pt_regs->rbp */ pushq %rbp /* pt_regs->rbp */
xorl %ebp, %ebp /* nospec rbp */ xorl %ebp, %ebp /* nospec rbp */
pushq %r12 /* pt_regs->r12 */ pushq %r12 /* pt_regs->r12 */
xorq %r12, %r12 /* nospec r12 */ xorl %r12d, %r12d /* nospec r12 */
pushq %r13 /* pt_regs->r13 */ pushq %r13 /* pt_regs->r13 */
xorq %r13, %r13 /* nospec r13 */ xorl %r13d, %r13d /* nospec r13 */
pushq %r14 /* pt_regs->r14 */ pushq %r14 /* pt_regs->r14 */
xorq %r14, %r14 /* nospec r14 */ xorl %r14d, %r14d /* nospec r14 */
pushq %r15 /* pt_regs->r15 */ pushq %r15 /* pt_regs->r15 */
xorq %r15, %r15 /* nospec r15 */ xorl %r15d, %r15d /* nospec r15 */
cld cld
/* /*
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#ifndef _ASM_X86_MACH_DEFAULT_APM_H #ifndef _ASM_X86_MACH_DEFAULT_APM_H
#define _ASM_X86_MACH_DEFAULT_APM_H #define _ASM_X86_MACH_DEFAULT_APM_H
#include <asm/nospec-branch.h>
#ifdef APM_ZERO_SEGS #ifdef APM_ZERO_SEGS
# define APM_DO_ZERO_SEGS \ # define APM_DO_ZERO_SEGS \
"pushl %%ds\n\t" \ "pushl %%ds\n\t" \
...@@ -32,6 +34,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, ...@@ -32,6 +34,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
* N.B. We do NOT need a cld after the BIOS call * N.B. We do NOT need a cld after the BIOS call
* because we always save and restore the flags. * because we always save and restore the flags.
*/ */
firmware_restrict_branch_speculation_start();
__asm__ __volatile__(APM_DO_ZERO_SEGS __asm__ __volatile__(APM_DO_ZERO_SEGS
"pushl %%edi\n\t" "pushl %%edi\n\t"
"pushl %%ebp\n\t" "pushl %%ebp\n\t"
...@@ -44,6 +47,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, ...@@ -44,6 +47,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
"=S" (*esi) "=S" (*esi)
: "a" (func), "b" (ebx_in), "c" (ecx_in) : "a" (func), "b" (ebx_in), "c" (ecx_in)
: "memory", "cc"); : "memory", "cc");
firmware_restrict_branch_speculation_end();
} }
static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
...@@ -56,6 +60,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, ...@@ -56,6 +60,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
* N.B. We do NOT need a cld after the BIOS call * N.B. We do NOT need a cld after the BIOS call
* because we always save and restore the flags. * because we always save and restore the flags.
*/ */
firmware_restrict_branch_speculation_start();
__asm__ __volatile__(APM_DO_ZERO_SEGS __asm__ __volatile__(APM_DO_ZERO_SEGS
"pushl %%edi\n\t" "pushl %%edi\n\t"
"pushl %%ebp\n\t" "pushl %%ebp\n\t"
...@@ -68,6 +73,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, ...@@ -68,6 +73,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
"=S" (si) "=S" (si)
: "a" (func), "b" (ebx_in), "c" (ecx_in) : "a" (func), "b" (ebx_in), "c" (ecx_in)
: "memory", "cc"); : "memory", "cc");
firmware_restrict_branch_speculation_end();
return error; return error;
} }
......
...@@ -38,7 +38,4 @@ INDIRECT_THUNK(dx) ...@@ -38,7 +38,4 @@ INDIRECT_THUNK(dx)
INDIRECT_THUNK(si) INDIRECT_THUNK(si)
INDIRECT_THUNK(di) INDIRECT_THUNK(di)
INDIRECT_THUNK(bp) INDIRECT_THUNK(bp)
asmlinkage void __fill_rsb(void);
asmlinkage void __clear_rsb(void);
#endif /* CONFIG_RETPOLINE */ #endif /* CONFIG_RETPOLINE */
...@@ -213,6 +213,7 @@ ...@@ -213,6 +213,7 @@
#define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */ #define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */
#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */ #define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */
/* Virtualization flags: Linux defined, word 8 */ /* Virtualization flags: Linux defined, word 8 */
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/processor-flags.h> #include <asm/processor-flags.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/nospec-branch.h>
/* /*
* We map the EFI regions needed for runtime services non-contiguously, * We map the EFI regions needed for runtime services non-contiguously,
...@@ -36,8 +37,18 @@ ...@@ -36,8 +37,18 @@
extern asmlinkage unsigned long efi_call_phys(void *, ...); extern asmlinkage unsigned long efi_call_phys(void *, ...);
#define arch_efi_call_virt_setup() kernel_fpu_begin() #define arch_efi_call_virt_setup() \
#define arch_efi_call_virt_teardown() kernel_fpu_end() ({ \
kernel_fpu_begin(); \
firmware_restrict_branch_speculation_start(); \
})
#define arch_efi_call_virt_teardown() \
({ \
firmware_restrict_branch_speculation_end(); \
kernel_fpu_end(); \
})
/* /*
* Wrap all the virtual calls in a way that forces the parameters on the stack. * Wrap all the virtual calls in a way that forces the parameters on the stack.
...@@ -73,6 +84,7 @@ struct efi_scratch { ...@@ -73,6 +84,7 @@ struct efi_scratch {
efi_sync_low_kernel_mappings(); \ efi_sync_low_kernel_mappings(); \
preempt_disable(); \ preempt_disable(); \
__kernel_fpu_begin(); \ __kernel_fpu_begin(); \
firmware_restrict_branch_speculation_start(); \
\ \
if (efi_scratch.use_pgd) { \ if (efi_scratch.use_pgd) { \
efi_scratch.prev_cr3 = __read_cr3(); \ efi_scratch.prev_cr3 = __read_cr3(); \
...@@ -91,6 +103,7 @@ struct efi_scratch { ...@@ -91,6 +103,7 @@ struct efi_scratch {
__flush_tlb_all(); \ __flush_tlb_all(); \
} \ } \
\ \
firmware_restrict_branch_speculation_end(); \
__kernel_fpu_end(); \ __kernel_fpu_end(); \
preempt_enable(); \ preempt_enable(); \
}) })
......
...@@ -37,7 +37,12 @@ struct cpu_signature { ...@@ -37,7 +37,12 @@ struct cpu_signature {
struct device; struct device;
enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND }; enum ucode_state {
UCODE_OK = 0,
UCODE_UPDATED,
UCODE_NFOUND,
UCODE_ERROR,
};
struct microcode_ops { struct microcode_ops {
enum ucode_state (*request_microcode_user) (int cpu, enum ucode_state (*request_microcode_user) (int cpu,
...@@ -54,7 +59,7 @@ struct microcode_ops { ...@@ -54,7 +59,7 @@ struct microcode_ops {
* are being called. * are being called.
* See also the "Synchronization" section in microcode_core.c. * See also the "Synchronization" section in microcode_core.c.
*/ */
int (*apply_microcode) (int cpu); enum ucode_state (*apply_microcode) (int cpu);
int (*collect_cpu_info) (int cpu, struct cpu_signature *csig); int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
}; };
......
...@@ -74,6 +74,7 @@ static inline void *ldt_slot_va(int slot) ...@@ -74,6 +74,7 @@ static inline void *ldt_slot_va(int slot)
return (void *)(LDT_BASE_ADDR + LDT_SLOT_STRIDE * slot); return (void *)(LDT_BASE_ADDR + LDT_SLOT_STRIDE * slot);
#else #else
BUG(); BUG();
return (void *)fix_to_virt(FIX_HOLE);
#endif #endif
} }
......
...@@ -8,6 +8,50 @@ ...@@ -8,6 +8,50 @@
#include <asm/cpufeatures.h> #include <asm/cpufeatures.h>
#include <asm/msr-index.h> #include <asm/msr-index.h>
/*
* Fill the CPU return stack buffer.
*
* Each entry in the RSB, if used for a speculative 'ret', contains an
* infinite 'pause; lfence; jmp' loop to capture speculative execution.
*
* This is required in various cases for retpoline and IBRS-based
* mitigations for the Spectre variant 2 vulnerability. Sometimes to
* eliminate potentially bogus entries from the RSB, and sometimes
* purely to ensure that it doesn't get empty, which on some CPUs would
* allow predictions from other (unwanted!) sources to be used.
*
* We define a CPP macro such that it can be used from both .S files and
* inline assembly. It's possible to do a .macro and then include that
* from C via asm(".include <asm/nospec-branch.h>") but let's not go there.
*/
#define RSB_CLEAR_LOOPS 32 /* To forcibly overwrite all entries */
#define RSB_FILL_LOOPS 16 /* To avoid underflow */
/*
* Google experimented with loop-unrolling and this turned out to be
* the optimal version — two calls, each with their own speculation
* trap should their return address end up getting used, in a loop.
*/
#define __FILL_RETURN_BUFFER(reg, nr, sp) \
mov $(nr/2), reg; \
771: \
call 772f; \
773: /* speculation trap */ \
pause; \
lfence; \
jmp 773b; \
772: \
call 774f; \
775: /* speculation trap */ \
pause; \
lfence; \
jmp 775b; \
774: \
dec reg; \
jnz 771b; \
add $(BITS_PER_LONG/8) * nr, sp;
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
/* /*
...@@ -23,6 +67,18 @@ ...@@ -23,6 +67,18 @@
.popsection .popsection
.endm .endm
/*
* This should be used immediately before an indirect jump/call. It tells
* objtool the subsequent indirect jump/call is vouched safe for retpoline
* builds.
*/
.macro ANNOTATE_RETPOLINE_SAFE
.Lannotate_\@:
.pushsection .discard.retpoline_safe
_ASM_PTR .Lannotate_\@
.popsection
.endm
/* /*
* These are the bare retpoline primitives for indirect jmp and call. * These are the bare retpoline primitives for indirect jmp and call.
* Do not use these directly; they only exist to make the ALTERNATIVE * Do not use these directly; they only exist to make the ALTERNATIVE
...@@ -59,9 +115,9 @@ ...@@ -59,9 +115,9 @@
.macro JMP_NOSPEC reg:req .macro JMP_NOSPEC reg:req
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
ANNOTATE_NOSPEC_ALTERNATIVE ANNOTATE_NOSPEC_ALTERNATIVE
ALTERNATIVE_2 __stringify(jmp *\reg), \ ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *\reg), \
__stringify(RETPOLINE_JMP \reg), X86_FEATURE_RETPOLINE, \ __stringify(RETPOLINE_JMP \reg), X86_FEATURE_RETPOLINE, \
__stringify(lfence; jmp *\reg), X86_FEATURE_RETPOLINE_AMD __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *\reg), X86_FEATURE_RETPOLINE_AMD
#else #else
jmp *\reg jmp *\reg
#endif #endif
...@@ -70,18 +126,25 @@ ...@@ -70,18 +126,25 @@
.macro CALL_NOSPEC reg:req .macro CALL_NOSPEC reg:req
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
ANNOTATE_NOSPEC_ALTERNATIVE ANNOTATE_NOSPEC_ALTERNATIVE
ALTERNATIVE_2 __stringify(call *\reg), \ ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *\reg), \
__stringify(RETPOLINE_CALL \reg), X86_FEATURE_RETPOLINE,\ __stringify(RETPOLINE_CALL \reg), X86_FEATURE_RETPOLINE,\
__stringify(lfence; call *\reg), X86_FEATURE_RETPOLINE_AMD __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *\reg), X86_FEATURE_RETPOLINE_AMD
#else #else
call *\reg call *\reg
#endif #endif
.endm .endm
/* This clobbers the BX register */ /*
.macro FILL_RETURN_BUFFER nr:req ftr:req * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP
* monstrosity above, manually.
*/
.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
ALTERNATIVE "", "call __clear_rsb", \ftr ANNOTATE_NOSPEC_ALTERNATIVE
ALTERNATIVE "jmp .Lskip_rsb_\@", \
__stringify(__FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP)) \
\ftr
.Lskip_rsb_\@:
#endif #endif
.endm .endm
...@@ -93,6 +156,12 @@ ...@@ -93,6 +156,12 @@
".long 999b - .\n\t" \ ".long 999b - .\n\t" \
".popsection\n\t" ".popsection\n\t"
#define ANNOTATE_RETPOLINE_SAFE \
"999:\n\t" \
".pushsection .discard.retpoline_safe\n\t" \
_ASM_PTR " 999b\n\t" \
".popsection\n\t"
#if defined(CONFIG_X86_64) && defined(RETPOLINE) #if defined(CONFIG_X86_64) && defined(RETPOLINE)
/* /*
...@@ -102,6 +171,7 @@ ...@@ -102,6 +171,7 @@
# define CALL_NOSPEC \ # define CALL_NOSPEC \
ANNOTATE_NOSPEC_ALTERNATIVE \ ANNOTATE_NOSPEC_ALTERNATIVE \
ALTERNATIVE( \ ALTERNATIVE( \
ANNOTATE_RETPOLINE_SAFE \
"call *%[thunk_target]\n", \ "call *%[thunk_target]\n", \
"call __x86_indirect_thunk_%V[thunk_target]\n", \ "call __x86_indirect_thunk_%V[thunk_target]\n", \
X86_FEATURE_RETPOLINE) X86_FEATURE_RETPOLINE)
...@@ -156,26 +226,54 @@ extern char __indirect_thunk_end[]; ...@@ -156,26 +226,54 @@ extern char __indirect_thunk_end[];
static inline void vmexit_fill_RSB(void) static inline void vmexit_fill_RSB(void)
{ {
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
alternative_input("", unsigned long loops;
"call __fill_rsb",
X86_FEATURE_RETPOLINE, asm volatile (ANNOTATE_NOSPEC_ALTERNATIVE
ASM_NO_INPUT_CLOBBER(_ASM_BX, "memory")); ALTERNATIVE("jmp 910f",
__stringify(__FILL_RETURN_BUFFER(%0, RSB_CLEAR_LOOPS, %1)),
X86_FEATURE_RETPOLINE)
"910:"
: "=r" (loops), ASM_CALL_CONSTRAINT
: : "memory" );
#endif #endif
} }
#define alternative_msr_write(_msr, _val, _feature) \
asm volatile(ALTERNATIVE("", \
"movl %[msr], %%ecx\n\t" \
"movl %[val], %%eax\n\t" \
"movl $0, %%edx\n\t" \
"wrmsr", \
_feature) \
: : [msr] "i" (_msr), [val] "i" (_val) \
: "eax", "ecx", "edx", "memory")
static inline void indirect_branch_prediction_barrier(void) static inline void indirect_branch_prediction_barrier(void)
{ {
asm volatile(ALTERNATIVE("", alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB,
"movl %[msr], %%ecx\n\t" X86_FEATURE_USE_IBPB);
"movl %[val], %%eax\n\t"
"movl $0, %%edx\n\t"
"wrmsr",
X86_FEATURE_USE_IBPB)
: : [msr] "i" (MSR_IA32_PRED_CMD),
[val] "i" (PRED_CMD_IBPB)
: "eax", "ecx", "edx", "memory");
} }
/*
* With retpoline, we must use IBRS to restrict branch prediction
* before calling into firmware.
*
* (Implemented as CPP macros due to header hell.)
*/
#define firmware_restrict_branch_speculation_start() \
do { \
preempt_disable(); \
alternative_msr_write(MSR_IA32_SPEC_CTRL, SPEC_CTRL_IBRS, \
X86_FEATURE_USE_IBRS_FW); \
} while (0)
#define firmware_restrict_branch_speculation_end() \
do { \
alternative_msr_write(MSR_IA32_SPEC_CTRL, 0, \
X86_FEATURE_USE_IBRS_FW); \
preempt_enable(); \
} while (0)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* /*
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#ifdef CONFIG_PARAVIRT #ifdef CONFIG_PARAVIRT
#include <asm/pgtable_types.h> #include <asm/pgtable_types.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/nospec-branch.h>
#include <asm/paravirt_types.h> #include <asm/paravirt_types.h>
...@@ -879,23 +880,27 @@ extern void default_banner(void); ...@@ -879,23 +880,27 @@ extern void default_banner(void);
#define INTERRUPT_RETURN \ #define INTERRUPT_RETURN \
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE, \ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE, \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret)) ANNOTATE_RETPOLINE_SAFE; \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret);)
#define DISABLE_INTERRUPTS(clobbers) \ #define DISABLE_INTERRUPTS(clobbers) \
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \
PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \
ANNOTATE_RETPOLINE_SAFE; \
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \
PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
#define ENABLE_INTERRUPTS(clobbers) \ #define ENABLE_INTERRUPTS(clobbers) \
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \
PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \
ANNOTATE_RETPOLINE_SAFE; \
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \
PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
#define GET_CR0_INTO_EAX \ #define GET_CR0_INTO_EAX \
push %ecx; push %edx; \ push %ecx; push %edx; \
ANNOTATE_RETPOLINE_SAFE; \
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \ call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \
pop %edx; pop %ecx pop %edx; pop %ecx
#else /* !CONFIG_X86_32 */ #else /* !CONFIG_X86_32 */
...@@ -917,21 +922,25 @@ extern void default_banner(void); ...@@ -917,21 +922,25 @@ extern void default_banner(void);
*/ */
#define SWAPGS \ #define SWAPGS \
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \ ANNOTATE_RETPOLINE_SAFE; \
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs); \
) )
#define GET_CR2_INTO_RAX \ #define GET_CR2_INTO_RAX \
call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2) ANNOTATE_RETPOLINE_SAFE; \
call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2);
#define USERGS_SYSRET64 \ #define USERGS_SYSRET64 \
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \
CLBR_NONE, \ CLBR_NONE, \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64)) ANNOTATE_RETPOLINE_SAFE; \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64);)
#ifdef CONFIG_DEBUG_ENTRY #ifdef CONFIG_DEBUG_ENTRY
#define SAVE_FLAGS(clobbers) \ #define SAVE_FLAGS(clobbers) \
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_save_fl), clobbers, \ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_save_fl), clobbers, \
PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \
ANNOTATE_RETPOLINE_SAFE; \
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_save_fl); \ call PARA_INDIRECT(pv_irq_ops+PV_IRQ_save_fl); \
PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
#endif #endif
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <asm/desc_defs.h> #include <asm/desc_defs.h>
#include <asm/kmap_types.h> #include <asm/kmap_types.h>
#include <asm/pgtable_types.h> #include <asm/pgtable_types.h>
#include <asm/nospec-branch.h>
struct page; struct page;
struct thread_struct; struct thread_struct;
...@@ -392,7 +393,9 @@ int paravirt_disable_iospace(void); ...@@ -392,7 +393,9 @@ int paravirt_disable_iospace(void);
* offset into the paravirt_patch_template structure, and can therefore be * offset into the paravirt_patch_template structure, and can therefore be
* freely converted back into a structure offset. * freely converted back into a structure offset.
*/ */
#define PARAVIRT_CALL "call *%c[paravirt_opptr];" #define PARAVIRT_CALL \
ANNOTATE_RETPOLINE_SAFE \
"call *%c[paravirt_opptr];"
/* /*
* These macros are intended to wrap calls through one of the paravirt * These macros are intended to wrap calls through one of the paravirt
......
...@@ -350,14 +350,14 @@ static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set) ...@@ -350,14 +350,14 @@ static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set)
{ {
pmdval_t v = native_pmd_val(pmd); pmdval_t v = native_pmd_val(pmd);
return __pmd(v | set); return native_make_pmd(v | set);
} }
static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear) static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear)
{ {
pmdval_t v = native_pmd_val(pmd); pmdval_t v = native_pmd_val(pmd);
return __pmd(v & ~clear); return native_make_pmd(v & ~clear);
} }
static inline pmd_t pmd_mkold(pmd_t pmd) static inline pmd_t pmd_mkold(pmd_t pmd)
...@@ -409,14 +409,14 @@ static inline pud_t pud_set_flags(pud_t pud, pudval_t set) ...@@ -409,14 +409,14 @@ static inline pud_t pud_set_flags(pud_t pud, pudval_t set)
{ {
pudval_t v = native_pud_val(pud); pudval_t v = native_pud_val(pud);
return __pud(v | set); return native_make_pud(v | set);
} }
static inline pud_t pud_clear_flags(pud_t pud, pudval_t clear) static inline pud_t pud_clear_flags(pud_t pud, pudval_t clear)
{ {
pudval_t v = native_pud_val(pud); pudval_t v = native_pud_val(pud);
return __pud(v & ~clear); return native_make_pud(v & ~clear);
} }
static inline pud_t pud_mkold(pud_t pud) static inline pud_t pud_mkold(pud_t pud)
......
...@@ -323,6 +323,11 @@ static inline pudval_t native_pud_val(pud_t pud) ...@@ -323,6 +323,11 @@ static inline pudval_t native_pud_val(pud_t pud)
#else #else
#include <asm-generic/pgtable-nopud.h> #include <asm-generic/pgtable-nopud.h>
static inline pud_t native_make_pud(pudval_t val)
{
return (pud_t) { .p4d.pgd = native_make_pgd(val) };
}
static inline pudval_t native_pud_val(pud_t pud) static inline pudval_t native_pud_val(pud_t pud)
{ {
return native_pgd_val(pud.p4d.pgd); return native_pgd_val(pud.p4d.pgd);
...@@ -344,6 +349,11 @@ static inline pmdval_t native_pmd_val(pmd_t pmd) ...@@ -344,6 +349,11 @@ static inline pmdval_t native_pmd_val(pmd_t pmd)
#else #else
#include <asm-generic/pgtable-nopmd.h> #include <asm-generic/pgtable-nopmd.h>
static inline pmd_t native_make_pmd(pmdval_t val)
{
return (pmd_t) { .pud.p4d.pgd = native_make_pgd(val) };
}
static inline pmdval_t native_pmd_val(pmd_t pmd) static inline pmdval_t native_pmd_val(pmd_t pmd)
{ {
return native_pgd_val(pmd.pud.p4d.pgd); return native_pgd_val(pmd.pud.p4d.pgd);
......
...@@ -977,4 +977,5 @@ bool xen_set_default_idle(void); ...@@ -977,4 +977,5 @@ bool xen_set_default_idle(void);
void stop_this_cpu(void *dummy); void stop_this_cpu(void *dummy);
void df_debug(struct pt_regs *regs, long error_code); void df_debug(struct pt_regs *regs, long error_code);
void microcode_check(void);
#endif /* _ASM_X86_PROCESSOR_H */ #endif /* _ASM_X86_PROCESSOR_H */
...@@ -67,13 +67,13 @@ static __always_inline __must_check ...@@ -67,13 +67,13 @@ static __always_inline __must_check
bool refcount_sub_and_test(unsigned int i, refcount_t *r) bool refcount_sub_and_test(unsigned int i, refcount_t *r)
{ {
GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl", REFCOUNT_CHECK_LT_ZERO, GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl", REFCOUNT_CHECK_LT_ZERO,
r->refs.counter, "er", i, "%0", e); r->refs.counter, "er", i, "%0", e, "cx");
} }
static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r) static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r)
{ {
GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl", REFCOUNT_CHECK_LT_ZERO, GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl", REFCOUNT_CHECK_LT_ZERO,
r->refs.counter, "%0", e); r->refs.counter, "%0", e, "cx");
} }
static __always_inline __must_check static __always_inline __must_check
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment