mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
Convert the repeated register save/restore sequences into macros, trading some level of implementation trickiness for conciseness (more than one register can be saved/restored with one invocation) and a smaller chance of cut and paste errors. This is particularly useful in preparation for extended GPR support; upcoming support for APX would need to add 32 lines to the VM entry/exit paths. No functional change intended. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com> Link: https://lore.kernel.org/6e67df0e-e5f0-43f5-aa86-22e8b01b75d2@redhat.com Link: https://patch.msgid.link/20260512011502.53072-2-chang.seok.bae@intel.com/ [Keep kvm_vcpu_regs.h and put the macros in there. -Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
112 lines
2.8 KiB
C
112 lines
2.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __KVM_X86_VMENTER_H
|
|
#define __KVM_X86_VMENTER_H
|
|
|
|
#include <asm/kvm_vcpu_regs.h>
|
|
|
|
#define KVM_ENTER_VMRESUME BIT(0)
|
|
#define KVM_ENTER_SAVE_SPEC_CTRL BIT(1)
|
|
#define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO BIT(2)
|
|
|
|
#ifdef __ASSEMBLER__
|
|
.macro RESTORE_GUEST_SPEC_CTRL_BODY guest_spec_ctrl:req, label:req
|
|
/*
|
|
* SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the
|
|
* host's, write the MSR. This is kept out-of-line so that the common
|
|
* case does not have to jump.
|
|
*
|
|
* IMPORTANT: To avoid RSB underflow attacks and any other nastiness,
|
|
* there must not be any returns or indirect branches between this code
|
|
* and vmentry.
|
|
*/
|
|
#ifdef CONFIG_X86_64
|
|
mov \guest_spec_ctrl, %rdx
|
|
cmp PER_CPU_VAR(x86_spec_ctrl_current), %rdx
|
|
je \label
|
|
movl %edx, %eax
|
|
shr $32, %rdx
|
|
#else
|
|
mov \guest_spec_ctrl, %eax
|
|
mov PER_CPU_VAR(x86_spec_ctrl_current), %ecx
|
|
xor %eax, %ecx
|
|
mov 4 + \guest_spec_ctrl, %edx
|
|
mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %esi
|
|
xor %edx, %esi
|
|
or %esi, %ecx
|
|
je \label
|
|
#endif
|
|
mov $MSR_IA32_SPEC_CTRL, %ecx
|
|
wrmsr
|
|
.endm
|
|
|
|
.macro RESTORE_HOST_SPEC_CTRL_BODY guest_spec_ctrl:req, enter_flags:req, label:req
|
|
/* Same for after vmexit. */
|
|
mov $MSR_IA32_SPEC_CTRL, %ecx
|
|
|
|
/*
|
|
* Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
|
|
* if it was not intercepted during guest execution.
|
|
*/
|
|
testl $KVM_ENTER_SAVE_SPEC_CTRL, \enter_flags
|
|
jz 998f
|
|
rdmsr
|
|
movl %eax, \guest_spec_ctrl
|
|
movl %edx, 4 + \guest_spec_ctrl
|
|
998:
|
|
/* Now restore the host value of the MSR if different from the guest's. */
|
|
#ifdef CONFIG_X86_64
|
|
mov PER_CPU_VAR(x86_spec_ctrl_current), %rdx
|
|
cmp \guest_spec_ctrl, %rdx
|
|
/*
|
|
* For legacy IBRS, the IBRS bit always needs to be written after
|
|
* transitioning from a less privileged predictor mode, regardless of
|
|
* whether the guest/host values differ.
|
|
*/
|
|
ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS
|
|
movl %edx, %eax
|
|
shr $32, %rdx
|
|
#else
|
|
mov PER_CPU_VAR(x86_spec_ctrl_current), %eax
|
|
mov \guest_spec_ctrl, %esi
|
|
xor %eax, %esi
|
|
mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %edx
|
|
mov 4 + \guest_spec_ctrl, %edi
|
|
xor %edx, %edi
|
|
or %edi, %esi
|
|
ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS
|
|
#endif
|
|
wrmsr
|
|
.endm
|
|
|
|
#define WORD_SIZE (BITS_PER_LONG / 8)
|
|
|
|
.macro LOAD_REGS src:req, regs_ofs:req, regs:vararg
|
|
.irp reg, \regs
|
|
REG_NUM reg_num \reg
|
|
mov (\regs_ofs + reg_num * WORD_SIZE)(\src), \reg
|
|
.endr
|
|
.endm
|
|
|
|
.macro STORE_REGS dst:req, regs_ofs:req, regs:vararg
|
|
.irp reg, \regs
|
|
REG_NUM reg_num \reg
|
|
mov \reg, (\regs_ofs + reg_num * WORD_SIZE)(\dst)
|
|
.endr
|
|
.endm
|
|
|
|
.macro POP_REGS dst:req, regs_ofs:req, regs:vararg
|
|
.irp reg, \regs
|
|
REG_NUM reg_num \reg
|
|
pop (\regs_ofs + reg_num * WORD_SIZE)(\dst)
|
|
.endr
|
|
.endm
|
|
|
|
.macro CLEAR_REGS regs:vararg
|
|
.irp reg, \regs
|
|
xorl \reg, \reg
|
|
.endr
|
|
.endm
|
|
|
|
#endif /* __ASSEMBLER__ */
|
|
#endif /* __KVM_X86_VMENTER_H */
|