mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'kvm-single-pdptrs' into HEAD
The non-MMU changes/preliminary cleanups from the "split kvm_mmu in three" series[1]. The final outcome is to have a single copy of the PDPTRs (in vcpu->arch) instead of two (in root_mmu and nested_mmu). [1] https://lore.kernel.org/kvm/20260603105814.10236-1-pbonzini@redhat.com/T/#t
This commit is contained in:
commit
4e6df93968
|
|
@ -525,10 +525,7 @@ struct kvm_mmu {
|
|||
* the bits spte never used.
|
||||
*/
|
||||
struct rsvd_bits_validate shadow_zero_check;
|
||||
|
||||
struct rsvd_bits_validate guest_rsvd_check;
|
||||
|
||||
u64 pdptrs[4]; /* pae */
|
||||
};
|
||||
|
||||
enum pmc_type {
|
||||
|
|
@ -888,6 +885,8 @@ struct kvm_vcpu_arch {
|
|||
*/
|
||||
struct kvm_mmu *walk_mmu;
|
||||
|
||||
u64 pdptrs[4]; /* pae */
|
||||
|
||||
struct kvm_mmu_memory_cache mmu_pte_list_desc_cache;
|
||||
struct kvm_mmu_memory_cache mmu_shadow_page_cache;
|
||||
struct kvm_mmu_memory_cache mmu_shadowed_info_cache;
|
||||
|
|
|
|||
|
|
@ -136,6 +136,14 @@ static inline bool kvm_register_is_dirty(struct kvm_vcpu *vcpu,
|
|||
return test_bit(reg, vcpu->arch.regs_dirty);
|
||||
}
|
||||
|
||||
static inline void kvm_register_mark_for_reload(struct kvm_vcpu *vcpu,
|
||||
enum kvm_reg reg)
|
||||
{
|
||||
kvm_assert_register_caching_allowed(vcpu);
|
||||
__clear_bit(reg, vcpu->arch.regs_avail);
|
||||
__clear_bit(reg, vcpu->arch.regs_dirty);
|
||||
}
|
||||
|
||||
static inline void kvm_register_mark_available(struct kvm_vcpu *vcpu,
|
||||
enum kvm_reg reg)
|
||||
{
|
||||
|
|
@ -259,12 +267,12 @@ static inline u64 kvm_pdptr_read(struct kvm_vcpu *vcpu, int index)
|
|||
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];
|
||||
return vcpu->arch.pdptrs[index];
|
||||
}
|
||||
|
||||
static inline void kvm_pdptr_write(struct kvm_vcpu *vcpu, int index, u64 value)
|
||||
{
|
||||
vcpu->arch.walk_mmu->pdptrs[index] = value;
|
||||
vcpu->arch.pdptrs[index] = value;
|
||||
}
|
||||
|
||||
static inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
|
||||
|
|
|
|||
|
|
@ -717,9 +717,12 @@ static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
|
|||
if (CC(!kvm_vcpu_is_legal_cr3(vcpu, cr3)))
|
||||
return -EINVAL;
|
||||
|
||||
if (reload_pdptrs && !nested_npt && is_pae_paging(vcpu) &&
|
||||
CC(!load_pdptrs(vcpu, cr3)))
|
||||
return -EINVAL;
|
||||
if (reload_pdptrs && is_pae_paging(vcpu)) {
|
||||
if (nested_npt)
|
||||
kvm_register_mark_for_reload(vcpu, VCPU_REG_PDPTR);
|
||||
else if (CC(!load_pdptrs(vcpu, cr3)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vcpu->arch.cr3 = cr3;
|
||||
|
||||
|
|
@ -2111,15 +2114,21 @@ static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu)
|
|||
if (WARN_ON(!is_guest_mode(vcpu)))
|
||||
return true;
|
||||
|
||||
if (!vcpu->arch.pdptrs_from_userspace &&
|
||||
!nested_npt_enabled(to_svm(vcpu)) && is_pae_paging(vcpu))
|
||||
if (is_pae_paging(vcpu)) {
|
||||
/*
|
||||
* Reload the guest's PDPTRs since after a migration
|
||||
* the guest CR3 might be restored prior to setting the nested
|
||||
* state which can lead to a load of wrong PDPTRs.
|
||||
* After migration, CR3 may have been restored before
|
||||
* KVM_SET_NESTED_STATE, so the PDPTR load into mmu->pdptrs[]
|
||||
* may have treated CR3 as an L1 GPA. For nNPT, drop the
|
||||
* cache so the next access reloads them with the proper
|
||||
* nGPA translation. For !nNPT, reload eagerly unless userspace
|
||||
* already supplied authoritative PDPTRs via KVM_SET_SREGS2.
|
||||
*/
|
||||
if (CC(!load_pdptrs(vcpu, vcpu->arch.cr3)))
|
||||
if (nested_npt_enabled(to_svm(vcpu)))
|
||||
kvm_register_mark_for_reload(vcpu, VCPU_REG_PDPTR);
|
||||
else if (!vcpu->arch.pdptrs_from_userspace &&
|
||||
CC(!load_pdptrs(vcpu, vcpu->arch.cr3)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nested_svm_merge_msrpm(vcpu)) {
|
||||
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
||||
|
|
|
|||
|
|
@ -1538,7 +1538,7 @@ static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
|
|||
switch (reg) {
|
||||
case VCPU_REG_PDPTR:
|
||||
/*
|
||||
* When !npt_enabled, mmu->pdptrs[] is already available since
|
||||
* When !npt_enabled, vcpu->pdptrs[] is already available since
|
||||
* it is always updated per SDM when moving to CRs.
|
||||
*/
|
||||
if (npt_enabled)
|
||||
|
|
|
|||
|
|
@ -2640,17 +2640,6 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
|
|||
vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp);
|
||||
vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip);
|
||||
|
||||
/*
|
||||
* L1 may access the L2's PDPTR, so save them to construct
|
||||
* vmcs12
|
||||
*/
|
||||
if (enable_ept) {
|
||||
vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0);
|
||||
vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
|
||||
vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
|
||||
vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
|
||||
}
|
||||
|
||||
if (kvm_mpx_supported() && vmx->vcpu.arch.nested_run_pending &&
|
||||
(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
|
||||
vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
|
||||
|
|
|
|||
|
|
@ -3384,30 +3384,26 @@ void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu)
|
|||
|
||||
void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
|
||||
if (!kvm_register_is_dirty(vcpu, VCPU_REG_PDPTR))
|
||||
return;
|
||||
|
||||
if (is_pae_paging(vcpu)) {
|
||||
vmcs_write64(GUEST_PDPTR0, mmu->pdptrs[0]);
|
||||
vmcs_write64(GUEST_PDPTR1, mmu->pdptrs[1]);
|
||||
vmcs_write64(GUEST_PDPTR2, mmu->pdptrs[2]);
|
||||
vmcs_write64(GUEST_PDPTR3, mmu->pdptrs[3]);
|
||||
vmcs_write64(GUEST_PDPTR0, vcpu->arch.pdptrs[0]);
|
||||
vmcs_write64(GUEST_PDPTR1, vcpu->arch.pdptrs[1]);
|
||||
vmcs_write64(GUEST_PDPTR2, vcpu->arch.pdptrs[2]);
|
||||
vmcs_write64(GUEST_PDPTR3, vcpu->arch.pdptrs[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void ept_save_pdptrs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
|
||||
if (WARN_ON_ONCE(!is_pae_paging(vcpu)))
|
||||
return;
|
||||
|
||||
mmu->pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
|
||||
mmu->pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
|
||||
mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
|
||||
mmu->pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
|
||||
vcpu->arch.pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
|
||||
vcpu->arch.pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
|
||||
vcpu->arch.pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
|
||||
vcpu->arch.pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
|
||||
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_PDPTR);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1031,7 +1031,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
|
|||
gpa_t real_gpa;
|
||||
int i;
|
||||
int ret;
|
||||
u64 pdpte[ARRAY_SIZE(mmu->pdptrs)];
|
||||
u64 pdpte[ARRAY_SIZE(vcpu->arch.pdptrs)];
|
||||
|
||||
/*
|
||||
* If the MMU is nested, CR3 holds an L2 GPA and needs to be translated
|
||||
|
|
@ -1060,10 +1060,10 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
|
|||
* 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)))
|
||||
if (!tdp_enabled && memcmp(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs)))
|
||||
kvm_mmu_free_roots(vcpu->kvm, mmu, KVM_MMU_ROOT_CURRENT);
|
||||
|
||||
memcpy(mmu->pdptrs, pdpte, sizeof(mmu->pdptrs));
|
||||
memcpy(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs));
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_PDPTR);
|
||||
kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu);
|
||||
vcpu->arch.pdptrs_from_userspace = false;
|
||||
|
|
@ -14240,6 +14240,9 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(tdp_enabled))
|
||||
return 0;
|
||||
|
||||
pcid_enabled = kvm_is_cr4_bit_set(vcpu, X86_CR4_PCIDE);
|
||||
|
||||
switch (type) {
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ static inline bool x86_exception_has_error_code(unsigned int vector)
|
|||
|
||||
static inline bool mmu_is_nested(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu;
|
||||
return vcpu->arch.mmu == &vcpu->arch.guest_mmu;
|
||||
}
|
||||
|
||||
static inline u8 vcpu_virt_addr_bits(struct kvm_vcpu *vcpu)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user