mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 20:30:53 +07:00
KVM: nVMX: Plumb L2 GPA through to PML emulation
Explicitly pass the L2 GPA to kvm_arch_write_log_dirty(), which for all
intents and purposes is vmx_write_pml_buffer(), instead of having the
latter pull the GPA from vmcs.GUEST_PHYSICAL_ADDRESS. If the dirty bit
update is the result of KVM emulation (rare for L2), then the GPA in the
VMCS may be stale and/or hold a completely unrelated GPA.
Fixes: c5f983f6e8
("nVMX: Implement emulated Page Modification Logging")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Message-Id: <20200622215832.22090-2-sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
312d16c7c0
commit
2dbebf7ae1
@ -1220,7 +1220,7 @@ struct kvm_x86_ops {
|
|||||||
void (*enable_log_dirty_pt_masked)(struct kvm *kvm,
|
void (*enable_log_dirty_pt_masked)(struct kvm *kvm,
|
||||||
struct kvm_memory_slot *slot,
|
struct kvm_memory_slot *slot,
|
||||||
gfn_t offset, unsigned long mask);
|
gfn_t offset, unsigned long mask);
|
||||||
int (*write_log_dirty)(struct kvm_vcpu *vcpu);
|
int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
|
||||||
|
|
||||||
/* pmu operations of sub-arch */
|
/* pmu operations of sub-arch */
|
||||||
const struct kvm_pmu_ops *pmu_ops;
|
const struct kvm_pmu_ops *pmu_ops;
|
||||||
|
@ -222,7 +222,7 @@ void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
|
|||||||
void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
|
void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
|
||||||
bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
|
bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
|
||||||
struct kvm_memory_slot *slot, u64 gfn);
|
struct kvm_memory_slot *slot, u64 gfn);
|
||||||
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
|
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
|
||||||
|
|
||||||
int kvm_mmu_post_init_vm(struct kvm *kvm);
|
int kvm_mmu_post_init_vm(struct kvm *kvm);
|
||||||
void kvm_mmu_pre_destroy_vm(struct kvm *kvm);
|
void kvm_mmu_pre_destroy_vm(struct kvm *kvm);
|
||||||
|
@ -1745,10 +1745,10 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
|
|||||||
* Emulate arch specific page modification logging for the
|
* Emulate arch specific page modification logging for the
|
||||||
* nested hypervisor
|
* nested hypervisor
|
||||||
*/
|
*/
|
||||||
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu)
|
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa)
|
||||||
{
|
{
|
||||||
if (kvm_x86_ops.write_log_dirty)
|
if (kvm_x86_ops.write_log_dirty)
|
||||||
return kvm_x86_ops.write_log_dirty(vcpu);
|
return kvm_x86_ops.write_log_dirty(vcpu, l2_gpa);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ static inline unsigned FNAME(gpte_access)(u64 gpte)
|
|||||||
static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
|
static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
|
||||||
struct kvm_mmu *mmu,
|
struct kvm_mmu *mmu,
|
||||||
struct guest_walker *walker,
|
struct guest_walker *walker,
|
||||||
int write_fault)
|
gpa_t addr, int write_fault)
|
||||||
{
|
{
|
||||||
unsigned level, index;
|
unsigned level, index;
|
||||||
pt_element_t pte, orig_pte;
|
pt_element_t pte, orig_pte;
|
||||||
@ -260,7 +260,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
|
|||||||
!(pte & PT_GUEST_DIRTY_MASK)) {
|
!(pte & PT_GUEST_DIRTY_MASK)) {
|
||||||
trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
|
trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
|
||||||
#if PTTYPE == PTTYPE_EPT
|
#if PTTYPE == PTTYPE_EPT
|
||||||
if (kvm_arch_write_log_dirty(vcpu))
|
if (kvm_arch_write_log_dirty(vcpu, addr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
#endif
|
#endif
|
||||||
pte |= PT_GUEST_DIRTY_MASK;
|
pte |= PT_GUEST_DIRTY_MASK;
|
||||||
@ -454,7 +454,8 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
|
|||||||
(PT_GUEST_DIRTY_SHIFT - PT_GUEST_ACCESSED_SHIFT);
|
(PT_GUEST_DIRTY_SHIFT - PT_GUEST_ACCESSED_SHIFT);
|
||||||
|
|
||||||
if (unlikely(!accessed_dirty)) {
|
if (unlikely(!accessed_dirty)) {
|
||||||
ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, write_fault);
|
ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker,
|
||||||
|
addr, write_fault);
|
||||||
if (unlikely(ret < 0))
|
if (unlikely(ret < 0))
|
||||||
goto error;
|
goto error;
|
||||||
else if (ret)
|
else if (ret)
|
||||||
|
@ -7500,11 +7500,11 @@ static void vmx_flush_log_dirty(struct kvm *kvm)
|
|||||||
kvm_flush_pml_buffers(kvm);
|
kvm_flush_pml_buffers(kvm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
|
static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
|
||||||
{
|
{
|
||||||
struct vmcs12 *vmcs12;
|
struct vmcs12 *vmcs12;
|
||||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||||
gpa_t gpa, dst;
|
gpa_t dst;
|
||||||
|
|
||||||
if (is_guest_mode(vcpu)) {
|
if (is_guest_mode(vcpu)) {
|
||||||
WARN_ON_ONCE(vmx->nested.pml_full);
|
WARN_ON_ONCE(vmx->nested.pml_full);
|
||||||
@ -7523,7 +7523,7 @@ static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull;
|
gpa &= ~0xFFFull;
|
||||||
dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index;
|
dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index;
|
||||||
|
|
||||||
if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa,
|
if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa,
|
||||||
|
Loading…
Reference in New Issue
Block a user