mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
Merge branch 'kvm-apx-prepare' into HEAD
Clean up KVM's register tracking and storage, primarily to prepare for APX support, which expands the maximum number of GPRs from 16 to 32.
This commit is contained in:
commit
b7fbe9a1bf
|
|
@ -191,11 +191,12 @@ enum kvm_reg {
|
|||
VCPU_REGS_R14 = __VCPU_REGS_R14,
|
||||
VCPU_REGS_R15 = __VCPU_REGS_R15,
|
||||
#endif
|
||||
VCPU_REGS_RIP,
|
||||
NR_VCPU_REGS,
|
||||
NR_VCPU_GENERAL_PURPOSE_REGS,
|
||||
|
||||
VCPU_EXREG_PDPTR = NR_VCPU_REGS,
|
||||
VCPU_EXREG_CR0,
|
||||
VCPU_REG_RIP = NR_VCPU_GENERAL_PURPOSE_REGS,
|
||||
|
||||
VCPU_REG_PDPTR,
|
||||
VCPU_REG_CR0,
|
||||
/*
|
||||
* Alias AMD's ERAPS (not a real register) to CR3 so that common code
|
||||
* can trigger emulation of the RAP (Return Address Predictor) with
|
||||
|
|
@ -203,13 +204,15 @@ enum kvm_reg {
|
|||
* is cleared on writes to CR3, i.e. marking CR3 dirty will naturally
|
||||
* mark ERAPS dirty as well.
|
||||
*/
|
||||
VCPU_EXREG_CR3,
|
||||
VCPU_EXREG_ERAPS = VCPU_EXREG_CR3,
|
||||
VCPU_EXREG_CR4,
|
||||
VCPU_EXREG_RFLAGS,
|
||||
VCPU_EXREG_SEGMENTS,
|
||||
VCPU_EXREG_EXIT_INFO_1,
|
||||
VCPU_EXREG_EXIT_INFO_2,
|
||||
VCPU_REG_CR3,
|
||||
VCPU_REG_ERAPS = VCPU_REG_CR3,
|
||||
VCPU_REG_CR4,
|
||||
VCPU_REG_RFLAGS,
|
||||
VCPU_REG_SEGMENTS,
|
||||
VCPU_REG_EXIT_INFO_1,
|
||||
VCPU_REG_EXIT_INFO_2,
|
||||
|
||||
NR_VCPU_TOTAL_REGS,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -814,9 +817,10 @@ struct kvm_vcpu_arch {
|
|||
* rip and regs accesses must go through
|
||||
* kvm_{register,rip}_{read,write} functions.
|
||||
*/
|
||||
unsigned long regs[NR_VCPU_REGS];
|
||||
u32 regs_avail;
|
||||
u32 regs_dirty;
|
||||
unsigned long regs[NR_VCPU_GENERAL_PURPOSE_REGS];
|
||||
unsigned long rip;
|
||||
DECLARE_BITMAP(regs_avail, NR_VCPU_TOTAL_REGS);
|
||||
DECLARE_BITMAP(regs_dirty, NR_VCPU_TOTAL_REGS);
|
||||
|
||||
unsigned long cr0;
|
||||
unsigned long cr0_guest_owned_bits;
|
||||
|
|
|
|||
|
|
@ -67,29 +67,29 @@ static inline bool kvm_register_is_available(struct kvm_vcpu *vcpu,
|
|||
enum kvm_reg reg)
|
||||
{
|
||||
kvm_assert_register_caching_allowed(vcpu);
|
||||
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
|
||||
return test_bit(reg, vcpu->arch.regs_avail);
|
||||
}
|
||||
|
||||
static inline bool kvm_register_is_dirty(struct kvm_vcpu *vcpu,
|
||||
enum kvm_reg reg)
|
||||
{
|
||||
kvm_assert_register_caching_allowed(vcpu);
|
||||
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
|
||||
return test_bit(reg, vcpu->arch.regs_dirty);
|
||||
}
|
||||
|
||||
static inline void kvm_register_mark_available(struct kvm_vcpu *vcpu,
|
||||
enum kvm_reg reg)
|
||||
{
|
||||
kvm_assert_register_caching_allowed(vcpu);
|
||||
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
|
||||
__set_bit(reg, vcpu->arch.regs_avail);
|
||||
}
|
||||
|
||||
static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
|
||||
enum kvm_reg reg)
|
||||
{
|
||||
kvm_assert_register_caching_allowed(vcpu);
|
||||
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
|
||||
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
|
||||
__set_bit(reg, vcpu->arch.regs_avail);
|
||||
__set_bit(reg, vcpu->arch.regs_dirty);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -102,7 +102,29 @@ static __always_inline bool kvm_register_test_and_mark_available(struct kvm_vcpu
|
|||
enum kvm_reg reg)
|
||||
{
|
||||
kvm_assert_register_caching_allowed(vcpu);
|
||||
return arch___test_and_set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
|
||||
return arch___test_and_set_bit(reg, vcpu->arch.regs_avail);
|
||||
}
|
||||
|
||||
static __always_inline void kvm_clear_available_registers(struct kvm_vcpu *vcpu,
|
||||
unsigned long clear_mask)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(clear_mask) != sizeof(vcpu->arch.regs_avail[0]));
|
||||
BUILD_BUG_ON(ARRAY_SIZE(vcpu->arch.regs_avail) != 1);
|
||||
|
||||
/*
|
||||
* Note the bitwise-AND! In practice, a straight write would also work
|
||||
* as KVM initializes the mask to all ones and never clears registers
|
||||
* that are eagerly synchronized. Using a bitwise-AND adds a bit of
|
||||
* sanity checking as incorrectly marking an eagerly sync'd register
|
||||
* unavailable will generate a WARN due to an unexpected cache request.
|
||||
*/
|
||||
vcpu->arch.regs_avail[0] &= ~clear_mask;
|
||||
}
|
||||
|
||||
static __always_inline void kvm_reset_dirty_registers(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
BUILD_BUG_ON(ARRAY_SIZE(vcpu->arch.regs_dirty) != 1);
|
||||
vcpu->arch.regs_dirty[0] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -112,7 +134,7 @@ static __always_inline bool kvm_register_test_and_mark_available(struct kvm_vcpu
|
|||
*/
|
||||
static inline unsigned long kvm_register_read_raw(struct kvm_vcpu *vcpu, int reg)
|
||||
{
|
||||
if (WARN_ON_ONCE((unsigned int)reg >= NR_VCPU_REGS))
|
||||
if (WARN_ON_ONCE((unsigned int)reg >= NR_VCPU_GENERAL_PURPOSE_REGS))
|
||||
return 0;
|
||||
|
||||
if (!kvm_register_is_available(vcpu, reg))
|
||||
|
|
@ -124,7 +146,7 @@ static inline unsigned long kvm_register_read_raw(struct kvm_vcpu *vcpu, int reg
|
|||
static inline void kvm_register_write_raw(struct kvm_vcpu *vcpu, int reg,
|
||||
unsigned long val)
|
||||
{
|
||||
if (WARN_ON_ONCE((unsigned int)reg >= NR_VCPU_REGS))
|
||||
if (WARN_ON_ONCE((unsigned int)reg >= NR_VCPU_GENERAL_PURPOSE_REGS))
|
||||
return;
|
||||
|
||||
vcpu->arch.regs[reg] = val;
|
||||
|
|
@ -133,12 +155,16 @@ static inline void kvm_register_write_raw(struct kvm_vcpu *vcpu, int reg,
|
|||
|
||||
static inline unsigned long kvm_rip_read(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return kvm_register_read_raw(vcpu, VCPU_REGS_RIP);
|
||||
if (!kvm_register_is_available(vcpu, VCPU_REG_RIP))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_REG_RIP);
|
||||
|
||||
return vcpu->arch.rip;
|
||||
}
|
||||
|
||||
static inline void kvm_rip_write(struct kvm_vcpu *vcpu, unsigned long val)
|
||||
{
|
||||
kvm_register_write_raw(vcpu, VCPU_REGS_RIP, val);
|
||||
vcpu->arch.rip = val;
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_RIP);
|
||||
}
|
||||
|
||||
static inline unsigned long kvm_rsp_read(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -155,8 +181,8 @@ static inline u64 kvm_pdptr_read(struct kvm_vcpu *vcpu, int index)
|
|||
{
|
||||
might_sleep(); /* on svm */
|
||||
|
||||
if (!kvm_register_is_available(vcpu, VCPU_EXREG_PDPTR))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_EXREG_PDPTR);
|
||||
if (!kvm_register_is_available(vcpu, VCPU_REG_PDPTR))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_REG_PDPTR);
|
||||
|
||||
return vcpu->arch.walk_mmu->pdptrs[index];
|
||||
}
|
||||
|
|
@ -170,8 +196,8 @@ static inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
|
|||
{
|
||||
ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
|
||||
if ((tmask & vcpu->arch.cr0_guest_owned_bits) &&
|
||||
!kvm_register_is_available(vcpu, VCPU_EXREG_CR0))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_EXREG_CR0);
|
||||
!kvm_register_is_available(vcpu, VCPU_REG_CR0))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_REG_CR0);
|
||||
return vcpu->arch.cr0 & mask;
|
||||
}
|
||||
|
||||
|
|
@ -192,8 +218,8 @@ static inline ulong kvm_read_cr4_bits(struct kvm_vcpu *vcpu, ulong mask)
|
|||
{
|
||||
ulong tmask = mask & KVM_POSSIBLE_CR4_GUEST_BITS;
|
||||
if ((tmask & vcpu->arch.cr4_guest_owned_bits) &&
|
||||
!kvm_register_is_available(vcpu, VCPU_EXREG_CR4))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_EXREG_CR4);
|
||||
!kvm_register_is_available(vcpu, VCPU_REG_CR4))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_REG_CR4);
|
||||
return vcpu->arch.cr4 & mask;
|
||||
}
|
||||
|
||||
|
|
@ -207,8 +233,8 @@ static __always_inline bool kvm_is_cr4_bit_set(struct kvm_vcpu *vcpu,
|
|||
|
||||
static inline ulong kvm_read_cr3(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (!kvm_register_is_available(vcpu, VCPU_EXREG_CR3))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_EXREG_CR3);
|
||||
if (!kvm_register_is_available(vcpu, VCPU_REG_CR3))
|
||||
kvm_x86_call(cache_reg)(vcpu, VCPU_REG_CR3);
|
||||
return vcpu->arch.cr3;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -967,7 +967,7 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
|
|||
save->r14 = svm->vcpu.arch.regs[VCPU_REGS_R14];
|
||||
save->r15 = svm->vcpu.arch.regs[VCPU_REGS_R15];
|
||||
#endif
|
||||
save->rip = svm->vcpu.arch.regs[VCPU_REGS_RIP];
|
||||
save->rip = svm->vcpu.arch.rip;
|
||||
|
||||
/* Sync some non-GPR registers before encrypting */
|
||||
save->xcr0 = svm->vcpu.arch.xcr0;
|
||||
|
|
|
|||
|
|
@ -1524,7 +1524,7 @@ static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
|
|||
kvm_register_mark_available(vcpu, reg);
|
||||
|
||||
switch (reg) {
|
||||
case VCPU_EXREG_PDPTR:
|
||||
case VCPU_REG_PDPTR:
|
||||
/*
|
||||
* When !npt_enabled, mmu->pdptrs[] is already available since
|
||||
* it is always updated per SDM when moving to CRs.
|
||||
|
|
@ -4198,7 +4198,7 @@ static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
|
|||
|
||||
static void svm_flush_tlb_guest(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_ERAPS);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_ERAPS);
|
||||
|
||||
svm_flush_tlb_asid(vcpu);
|
||||
}
|
||||
|
|
@ -4442,7 +4442,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
|
||||
svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
|
||||
svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
|
||||
svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
|
||||
svm->vmcb->save.rip = vcpu->arch.rip;
|
||||
|
||||
/*
|
||||
* Disable singlestep if we're injecting an interrupt/exception.
|
||||
|
|
@ -4479,7 +4479,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
svm->vmcb->save.cr2 = vcpu->arch.cr2;
|
||||
|
||||
if (guest_cpu_cap_has(vcpu, X86_FEATURE_ERAPS) &&
|
||||
kvm_register_is_dirty(vcpu, VCPU_EXREG_ERAPS))
|
||||
kvm_register_is_dirty(vcpu, VCPU_REG_ERAPS))
|
||||
svm->vmcb->control.erap_ctl |= ERAP_CONTROL_CLEAR_RAP;
|
||||
|
||||
svm_fixup_nested_rips(vcpu);
|
||||
|
|
@ -4528,9 +4528,9 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
vcpu->arch.cr2 = svm->vmcb->save.cr2;
|
||||
vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
|
||||
vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
|
||||
vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
|
||||
vcpu->arch.rip = svm->vmcb->save.rip;
|
||||
}
|
||||
vcpu->arch.regs_dirty = 0;
|
||||
kvm_reset_dirty_registers(vcpu);
|
||||
|
||||
if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
|
||||
kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
|
||||
|
|
@ -4576,7 +4576,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
vcpu->arch.apf.host_apf_flags =
|
||||
kvm_read_and_reset_apf_flags();
|
||||
|
||||
vcpu->arch.regs_avail &= ~SVM_REGS_LAZY_LOAD_SET;
|
||||
kvm_clear_available_registers(vcpu, SVM_REGS_LAZY_LOAD_SET);
|
||||
|
||||
if (!msr_write_intercepted(svm, MSR_AMD64_PERF_CNTR_GLOBAL_CTL))
|
||||
rdmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, vcpu_to_pmu(vcpu)->global_ctrl);
|
||||
|
|
@ -4973,7 +4973,7 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram)
|
|||
|
||||
svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
|
||||
svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
|
||||
svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
|
||||
svm->vmcb->save.rip = vcpu->arch.rip;
|
||||
|
||||
nested_svm_simple_vmexit(svm, SVM_EXIT_SW);
|
||||
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ static inline bool svm_is_vmrun_failure(u64 exit_code)
|
|||
* KVM_REQ_LOAD_MMU_PGD is always requested when the cached vcpu->arch.cr3
|
||||
* is changed. svm_load_mmu_pgd() then syncs the new CR3 value into the VMCB.
|
||||
*/
|
||||
#define SVM_REGS_LAZY_LOAD_SET (1 << VCPU_EXREG_PDPTR)
|
||||
#define SVM_REGS_LAZY_LOAD_SET (BIT(VCPU_REG_PDPTR))
|
||||
|
||||
static inline void __vmcb_set_intercept(unsigned long *intercepts, u32 bit)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -310,13 +310,13 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
|
|||
vmx_sync_vmcs_host_state(vmx, prev);
|
||||
put_cpu();
|
||||
|
||||
vcpu->arch.regs_avail = ~VMX_REGS_LAZY_LOAD_SET;
|
||||
kvm_clear_available_registers(vcpu, VMX_REGS_LAZY_LOAD_SET);
|
||||
|
||||
/*
|
||||
* All lazily updated registers will be reloaded from VMCS12 on both
|
||||
* vmentry and vmexit.
|
||||
*/
|
||||
vcpu->arch.regs_dirty = 0;
|
||||
kvm_reset_dirty_registers(vcpu);
|
||||
}
|
||||
|
||||
static void nested_put_vmcs12_pages(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -1201,7 +1201,7 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
|
|||
}
|
||||
|
||||
vcpu->arch.cr3 = cr3;
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_CR3);
|
||||
|
||||
/* Re-initialize the MMU, e.g. to pick up CR4 MMU role changes. */
|
||||
kvm_init_mmu(vcpu);
|
||||
|
|
@ -4985,7 +4985,7 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
|
|||
|
||||
nested_ept_uninit_mmu_context(vcpu);
|
||||
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_CR3);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_CR3);
|
||||
|
||||
/*
|
||||
* Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs
|
||||
|
|
@ -5087,7 +5087,7 @@ void __nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
|
|||
kvm_service_local_tlb_flush_requests(vcpu);
|
||||
|
||||
/*
|
||||
* VCPU_EXREG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between
|
||||
* VCPU_REG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between
|
||||
* now and the new vmentry. Ensure that the VMCS02 PDPTR fields are
|
||||
* up-to-date before switching to L1.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1013,23 +1013,23 @@ static fastpath_t tdx_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
|
|||
return EXIT_FASTPATH_NONE;
|
||||
}
|
||||
|
||||
#define TDX_REGS_AVAIL_SET (BIT_ULL(VCPU_EXREG_EXIT_INFO_1) | \
|
||||
BIT_ULL(VCPU_EXREG_EXIT_INFO_2) | \
|
||||
BIT_ULL(VCPU_REGS_RAX) | \
|
||||
BIT_ULL(VCPU_REGS_RBX) | \
|
||||
BIT_ULL(VCPU_REGS_RCX) | \
|
||||
BIT_ULL(VCPU_REGS_RDX) | \
|
||||
BIT_ULL(VCPU_REGS_RBP) | \
|
||||
BIT_ULL(VCPU_REGS_RSI) | \
|
||||
BIT_ULL(VCPU_REGS_RDI) | \
|
||||
BIT_ULL(VCPU_REGS_R8) | \
|
||||
BIT_ULL(VCPU_REGS_R9) | \
|
||||
BIT_ULL(VCPU_REGS_R10) | \
|
||||
BIT_ULL(VCPU_REGS_R11) | \
|
||||
BIT_ULL(VCPU_REGS_R12) | \
|
||||
BIT_ULL(VCPU_REGS_R13) | \
|
||||
BIT_ULL(VCPU_REGS_R14) | \
|
||||
BIT_ULL(VCPU_REGS_R15))
|
||||
#define TDX_REGS_AVAIL_SET (BIT(VCPU_REG_EXIT_INFO_1) | \
|
||||
BIT(VCPU_REG_EXIT_INFO_2) | \
|
||||
BIT(VCPU_REGS_RAX) | \
|
||||
BIT(VCPU_REGS_RBX) | \
|
||||
BIT(VCPU_REGS_RCX) | \
|
||||
BIT(VCPU_REGS_RDX) | \
|
||||
BIT(VCPU_REGS_RBP) | \
|
||||
BIT(VCPU_REGS_RSI) | \
|
||||
BIT(VCPU_REGS_RDI) | \
|
||||
BIT(VCPU_REGS_R8) | \
|
||||
BIT(VCPU_REGS_R9) | \
|
||||
BIT(VCPU_REGS_R10) | \
|
||||
BIT(VCPU_REGS_R11) | \
|
||||
BIT(VCPU_REGS_R12) | \
|
||||
BIT(VCPU_REGS_R13) | \
|
||||
BIT(VCPU_REGS_R14) | \
|
||||
BIT(VCPU_REGS_R15))
|
||||
|
||||
static void tdx_load_host_xsave_state(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
|
|
@ -1098,7 +1098,7 @@ fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
|
||||
tdx_load_host_xsave_state(vcpu);
|
||||
|
||||
vcpu->arch.regs_avail &= TDX_REGS_AVAIL_SET;
|
||||
kvm_clear_available_registers(vcpu, ~TDX_REGS_AVAIL_SET);
|
||||
|
||||
if (unlikely(tdx->vp_enter_ret == EXIT_REASON_EPT_MISCONFIG))
|
||||
return EXIT_FASTPATH_NONE;
|
||||
|
|
|
|||
|
|
@ -847,8 +847,8 @@ static bool vmx_segment_cache_test_set(struct vcpu_vmx *vmx, unsigned seg,
|
|||
bool ret;
|
||||
u32 mask = 1 << (seg * SEG_FIELD_NR + field);
|
||||
|
||||
if (!kvm_register_is_available(&vmx->vcpu, VCPU_EXREG_SEGMENTS)) {
|
||||
kvm_register_mark_available(&vmx->vcpu, VCPU_EXREG_SEGMENTS);
|
||||
if (!kvm_register_is_available(&vmx->vcpu, VCPU_REG_SEGMENTS)) {
|
||||
kvm_register_mark_available(&vmx->vcpu, VCPU_REG_SEGMENTS);
|
||||
vmx->segment_cache.bitmask = 0;
|
||||
}
|
||||
ret = vmx->segment_cache.bitmask & mask;
|
||||
|
|
@ -1613,8 +1613,8 @@ unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
|
|||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
unsigned long rflags, save_rflags;
|
||||
|
||||
if (!kvm_register_is_available(vcpu, VCPU_EXREG_RFLAGS)) {
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_RFLAGS);
|
||||
if (!kvm_register_is_available(vcpu, VCPU_REG_RFLAGS)) {
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_RFLAGS);
|
||||
rflags = vmcs_readl(GUEST_RFLAGS);
|
||||
if (vmx->rmode.vm86_active) {
|
||||
rflags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
|
||||
|
|
@ -1637,7 +1637,7 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
|
|||
* if L1 runs L2 as a restricted guest.
|
||||
*/
|
||||
if (is_unrestricted_guest(vcpu)) {
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_RFLAGS);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_RFLAGS);
|
||||
vmx->rflags = rflags;
|
||||
vmcs_writel(GUEST_RFLAGS, rflags);
|
||||
return;
|
||||
|
|
@ -2608,20 +2608,20 @@ void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
|
|||
case VCPU_REGS_RSP:
|
||||
vcpu->arch.regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP);
|
||||
break;
|
||||
case VCPU_REGS_RIP:
|
||||
vcpu->arch.regs[VCPU_REGS_RIP] = vmcs_readl(GUEST_RIP);
|
||||
case VCPU_REG_RIP:
|
||||
vcpu->arch.rip = vmcs_readl(GUEST_RIP);
|
||||
break;
|
||||
case VCPU_EXREG_PDPTR:
|
||||
case VCPU_REG_PDPTR:
|
||||
if (enable_ept)
|
||||
ept_save_pdptrs(vcpu);
|
||||
break;
|
||||
case VCPU_EXREG_CR0:
|
||||
case VCPU_REG_CR0:
|
||||
guest_owned_bits = vcpu->arch.cr0_guest_owned_bits;
|
||||
|
||||
vcpu->arch.cr0 &= ~guest_owned_bits;
|
||||
vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & guest_owned_bits;
|
||||
break;
|
||||
case VCPU_EXREG_CR3:
|
||||
case VCPU_REG_CR3:
|
||||
/*
|
||||
* When intercepting CR3 loads, e.g. for shadowing paging, KVM's
|
||||
* CR3 is loaded into hardware, not the guest's CR3.
|
||||
|
|
@ -2629,7 +2629,7 @@ void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
|
|||
if (!(exec_controls_get(to_vmx(vcpu)) & CPU_BASED_CR3_LOAD_EXITING))
|
||||
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
|
||||
break;
|
||||
case VCPU_EXREG_CR4:
|
||||
case VCPU_REG_CR4:
|
||||
guest_owned_bits = vcpu->arch.cr4_guest_owned_bits;
|
||||
|
||||
vcpu->arch.cr4 &= ~guest_owned_bits;
|
||||
|
|
@ -3365,7 +3365,7 @@ void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
|
||||
if (!kvm_register_is_dirty(vcpu, VCPU_EXREG_PDPTR))
|
||||
if (!kvm_register_is_dirty(vcpu, VCPU_REG_PDPTR))
|
||||
return;
|
||||
|
||||
if (is_pae_paging(vcpu)) {
|
||||
|
|
@ -3388,7 +3388,7 @@ void ept_save_pdptrs(struct kvm_vcpu *vcpu)
|
|||
mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
|
||||
mmu->pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
|
||||
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_PDPTR);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_PDPTR);
|
||||
}
|
||||
|
||||
#define CR3_EXITING_BITS (CPU_BASED_CR3_LOAD_EXITING | \
|
||||
|
|
@ -3431,7 +3431,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
|
|||
vmcs_writel(CR0_READ_SHADOW, cr0);
|
||||
vmcs_writel(GUEST_CR0, hw_cr0);
|
||||
vcpu->arch.cr0 = cr0;
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_CR0);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_CR0);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
if (vcpu->arch.efer & EFER_LME) {
|
||||
|
|
@ -3449,8 +3449,8 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
|
|||
* (correctly) stop reading vmcs.GUEST_CR3 because it thinks
|
||||
* KVM's CR3 is installed.
|
||||
*/
|
||||
if (!kvm_register_is_available(vcpu, VCPU_EXREG_CR3))
|
||||
vmx_cache_reg(vcpu, VCPU_EXREG_CR3);
|
||||
if (!kvm_register_is_available(vcpu, VCPU_REG_CR3))
|
||||
vmx_cache_reg(vcpu, VCPU_REG_CR3);
|
||||
|
||||
/*
|
||||
* When running with EPT but not unrestricted guest, KVM must
|
||||
|
|
@ -3487,7 +3487,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
|
|||
* GUEST_CR3 is still vmx->ept_identity_map_addr if EPT + !URG.
|
||||
*/
|
||||
if (!(old_cr0_pg & X86_CR0_PG) && (cr0 & X86_CR0_PG))
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_CR3);
|
||||
}
|
||||
|
||||
/* depends on vcpu->arch.cr0 to be set to a new value */
|
||||
|
|
@ -3516,7 +3516,7 @@ void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, hpa_t root_hpa, int root_level)
|
|||
|
||||
if (!enable_unrestricted_guest && !is_paging(vcpu))
|
||||
guest_cr3 = to_kvm_vmx(kvm)->ept_identity_map_addr;
|
||||
else if (kvm_register_is_dirty(vcpu, VCPU_EXREG_CR3))
|
||||
else if (kvm_register_is_dirty(vcpu, VCPU_REG_CR3))
|
||||
guest_cr3 = vcpu->arch.cr3;
|
||||
else /* vmcs.GUEST_CR3 is already up-to-date. */
|
||||
update_guest_cr3 = false;
|
||||
|
|
@ -3576,7 +3576,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
|||
}
|
||||
|
||||
vcpu->arch.cr4 = cr4;
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_CR4);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_CR4);
|
||||
|
||||
if (!enable_unrestricted_guest) {
|
||||
if (enable_ept) {
|
||||
|
|
@ -5039,7 +5039,7 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||
vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
|
||||
|
||||
vmx_segment_cache_clear(vmx);
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_SEGMENTS);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_SEGMENTS);
|
||||
|
||||
vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
|
||||
vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
|
||||
|
|
@ -7488,7 +7488,7 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
|
|||
vmx->fail = __vmx_vcpu_run(vmx, flags);
|
||||
|
||||
vcpu->arch.cr2 = native_read_cr2();
|
||||
vcpu->arch.regs_avail &= ~VMX_REGS_LAZY_LOAD_SET;
|
||||
kvm_clear_available_registers(vcpu, VMX_REGS_LAZY_LOAD_SET);
|
||||
|
||||
vmx->idt_vectoring_info = 0;
|
||||
|
||||
|
|
@ -7530,9 +7530,9 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
|
||||
vmx->vt.exit_reason.full = EXIT_REASON_INVALID_STATE;
|
||||
vmx->vt.exit_reason.failed_vmentry = 1;
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_1);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_EXIT_INFO_1);
|
||||
vmx->vt.exit_qualification = ENTRY_FAIL_DEFAULT;
|
||||
kvm_register_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_2);
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_EXIT_INFO_2);
|
||||
vmx->vt.exit_intr_info = 0;
|
||||
return EXIT_FASTPATH_NONE;
|
||||
}
|
||||
|
|
@ -7552,9 +7552,9 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
|
||||
if (kvm_register_is_dirty(vcpu, VCPU_REGS_RSP))
|
||||
vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
|
||||
if (kvm_register_is_dirty(vcpu, VCPU_REGS_RIP))
|
||||
vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
|
||||
vcpu->arch.regs_dirty = 0;
|
||||
if (kvm_register_is_dirty(vcpu, VCPU_REG_RIP))
|
||||
vmcs_writel(GUEST_RIP, vcpu->arch.rip);
|
||||
kvm_reset_dirty_registers(vcpu);
|
||||
|
||||
if (run_flags & KVM_RUN_LOAD_GUEST_DR6)
|
||||
set_debugreg(vcpu->arch.dr6, 6);
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ static __always_inline unsigned long vmx_get_exit_qual(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
struct vcpu_vt *vt = to_vt(vcpu);
|
||||
|
||||
if (!kvm_register_test_and_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_1) &&
|
||||
if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_1) &&
|
||||
!WARN_ON_ONCE(is_td_vcpu(vcpu)))
|
||||
vt->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
|
||||
|
||||
|
|
@ -327,7 +327,7 @@ static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
struct vcpu_vt *vt = to_vt(vcpu);
|
||||
|
||||
if (!kvm_register_test_and_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_2) &&
|
||||
if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_2) &&
|
||||
!WARN_ON_ONCE(is_td_vcpu(vcpu)))
|
||||
vt->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
|
||||
|
||||
|
|
@ -618,16 +618,16 @@ BUILD_CONTROLS_SHADOW(tertiary_exec, TERTIARY_VM_EXEC_CONTROL, 64)
|
|||
* cache on demand. Other registers not listed here are synced to
|
||||
* the cache immediately after VM-Exit.
|
||||
*/
|
||||
#define VMX_REGS_LAZY_LOAD_SET ((1 << VCPU_REGS_RIP) | \
|
||||
(1 << VCPU_REGS_RSP) | \
|
||||
(1 << VCPU_EXREG_RFLAGS) | \
|
||||
(1 << VCPU_EXREG_PDPTR) | \
|
||||
(1 << VCPU_EXREG_SEGMENTS) | \
|
||||
(1 << VCPU_EXREG_CR0) | \
|
||||
(1 << VCPU_EXREG_CR3) | \
|
||||
(1 << VCPU_EXREG_CR4) | \
|
||||
(1 << VCPU_EXREG_EXIT_INFO_1) | \
|
||||
(1 << VCPU_EXREG_EXIT_INFO_2))
|
||||
#define VMX_REGS_LAZY_LOAD_SET (BIT(VCPU_REGS_RSP) | \
|
||||
BIT(VCPU_REG_RIP) | \
|
||||
BIT(VCPU_REG_RFLAGS) | \
|
||||
BIT(VCPU_REG_PDPTR) | \
|
||||
BIT(VCPU_REG_SEGMENTS) | \
|
||||
BIT(VCPU_REG_CR0) | \
|
||||
BIT(VCPU_REG_CR3) | \
|
||||
BIT(VCPU_REG_CR4) | \
|
||||
BIT(VCPU_REG_EXIT_INFO_1) | \
|
||||
BIT(VCPU_REG_EXIT_INFO_2))
|
||||
|
||||
static inline unsigned long vmx_l1_guest_owned_cr0_bits(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1091,14 +1091,14 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
|
|||
}
|
||||
|
||||
/*
|
||||
* Marking VCPU_EXREG_PDPTR dirty doesn't work for !tdp_enabled.
|
||||
* Marking VCPU_REG_PDPTR dirty doesn't work for !tdp_enabled.
|
||||
* Shadow page roots need to be reconstructed instead.
|
||||
*/
|
||||
if (!tdp_enabled && memcmp(mmu->pdptrs, pdpte, sizeof(mmu->pdptrs)))
|
||||
kvm_mmu_free_roots(vcpu->kvm, mmu, KVM_MMU_ROOT_CURRENT);
|
||||
|
||||
memcpy(mmu->pdptrs, pdpte, sizeof(mmu->pdptrs));
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_PDPTR);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_PDPTR);
|
||||
kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu);
|
||||
vcpu->arch.pdptrs_from_userspace = false;
|
||||
|
||||
|
|
@ -1479,7 +1479,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
|
|||
kvm_mmu_new_pgd(vcpu, cr3);
|
||||
|
||||
vcpu->arch.cr3 = cr3;
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_CR3);
|
||||
/* Do not call post_set_cr3, we do not get here for confidential guests. */
|
||||
|
||||
handle_tlb_flush:
|
||||
|
|
@ -12459,7 +12459,7 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
|
|||
vcpu->arch.cr2 = sregs->cr2;
|
||||
*mmu_reset_needed |= kvm_read_cr3(vcpu) != sregs->cr3;
|
||||
vcpu->arch.cr3 = sregs->cr3;
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_CR3);
|
||||
kvm_x86_call(post_set_cr3)(vcpu, sregs->cr3);
|
||||
|
||||
kvm_set_cr8(vcpu, sregs->cr8);
|
||||
|
|
@ -12552,7 +12552,7 @@ static int __set_sregs2(struct kvm_vcpu *vcpu, struct kvm_sregs2 *sregs2)
|
|||
for (i = 0; i < 4 ; i++)
|
||||
kvm_pdptr_write(vcpu, i, sregs2->pdptrs[i]);
|
||||
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_PDPTR);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_PDPTR);
|
||||
mmu_reset_needed = 1;
|
||||
vcpu->arch.pdptrs_from_userspace = true;
|
||||
}
|
||||
|
|
@ -12822,8 +12822,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
|
|||
int r;
|
||||
|
||||
vcpu->arch.last_vmentry_cpu = -1;
|
||||
vcpu->arch.regs_avail = ~0;
|
||||
vcpu->arch.regs_dirty = ~0;
|
||||
bitmap_fill(vcpu->arch.regs_avail, NR_VCPU_TOTAL_REGS);
|
||||
bitmap_fill(vcpu->arch.regs_dirty, NR_VCPU_TOTAL_REGS);
|
||||
|
||||
kvm_gpc_init(&vcpu->arch.pv_time, vcpu->kvm);
|
||||
|
||||
|
|
@ -13097,7 +13097,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||
kvm_rip_write(vcpu, 0xfff0);
|
||||
|
||||
vcpu->arch.cr3 = 0;
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3);
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_CR3);
|
||||
|
||||
/*
|
||||
* CR0.CD/NW are set on RESET, preserved on INIT. Note, some versions
|
||||
|
|
@ -14309,7 +14309,7 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva)
|
|||
* the RAP (Return Address Predicator).
|
||||
*/
|
||||
if (guest_cpu_cap_has(vcpu, X86_FEATURE_ERAPS))
|
||||
kvm_register_is_dirty(vcpu, VCPU_EXREG_ERAPS);
|
||||
kvm_register_is_dirty(vcpu, VCPU_REG_ERAPS);
|
||||
|
||||
kvm_invalidate_pcid(vcpu, operand.pcid);
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
|
|
@ -14325,7 +14325,7 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva)
|
|||
fallthrough;
|
||||
case INVPCID_TYPE_ALL_INCL_GLOBAL:
|
||||
/*
|
||||
* Don't bother marking VCPU_EXREG_ERAPS dirty, SVM will take
|
||||
* Don't bother marking VCPU_REG_ERAPS dirty, SVM will take
|
||||
* care of doing so when emulating the full guest TLB flush
|
||||
* (the RAP is cleared on all implicit TLB flushes).
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user