diff options
Diffstat (limited to 'arch/x86/entry/calling.h')
| -rw-r--r-- | arch/x86/entry/calling.h | 62 | 
1 files changed, 62 insertions, 0 deletions
diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h index 29b36e9e4e74..f6907627172b 100644 --- a/arch/x86/entry/calling.h +++ b/arch/x86/entry/calling.h @@ -7,6 +7,8 @@  #include <asm/asm-offsets.h>  #include <asm/processor-flags.h>  #include <asm/ptrace-abi.h> +#include <asm/msr.h> +#include <asm/nospec-branch.h>  /* @@ -283,6 +285,66 @@ For 32-bit we have the following conventions - kernel is built with  #endif  /* + * IBRS kernel mitigation for Spectre_v2. + * + * Assumes full context is established (PUSH_REGS, CR3 and GS) and it clobbers + * the regs it uses (AX, CX, DX). Must be called before the first RET + * instruction (NOTE! UNTRAIN_RET includes a RET instruction) + * + * The optional argument is used to save/restore the current value, + * which is used on the paranoid paths. + * + * Assumes x86_spec_ctrl_{base,current} to have SPEC_CTRL_IBRS set. + */ +.macro IBRS_ENTER save_reg +#ifdef CONFIG_CPU_IBRS_ENTRY +	ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS +	movl	$MSR_IA32_SPEC_CTRL, %ecx + +.ifnb \save_reg +	rdmsr +	shl	$32, %rdx +	or	%rdx, %rax +	mov	%rax, \save_reg +	test	$SPEC_CTRL_IBRS, %eax +	jz	.Ldo_wrmsr_\@ +	lfence +	jmp	.Lend_\@ +.Ldo_wrmsr_\@: +.endif + +	movq	PER_CPU_VAR(x86_spec_ctrl_current), %rdx +	movl	%edx, %eax +	shr	$32, %rdx +	wrmsr +.Lend_\@: +#endif +.endm + +/* + * Similar to IBRS_ENTER, requires KERNEL GS,CR3 and clobbers (AX, CX, DX) + * regs. Must be called after the last RET. + */ +.macro IBRS_EXIT save_reg +#ifdef CONFIG_CPU_IBRS_ENTRY +	ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS +	movl	$MSR_IA32_SPEC_CTRL, %ecx + +.ifnb \save_reg +	mov	\save_reg, %rdx +.else +	movq	PER_CPU_VAR(x86_spec_ctrl_current), %rdx +	andl	$(~SPEC_CTRL_IBRS), %edx +.endif + +	movl	%edx, %eax +	shr	$32, %rdx +	wrmsr +.Lend_\@: +#endif +.endm + +/*   * Mitigate Spectre v1 for conditional swapgs code paths.   *   * FENCE_SWAPGS_USER_ENTRY is used in the user entry swapgs code path, to  | 
