The patch enables userspace to be notified about failed memeory accesses. This can be employed by userspace, say QEMU, to build the memory access tracker while userfaultfd doesn't support detection of protected memeory writes. In case of QEMU, it would allow to make a background snapshot mode. Signed-off-by: Denis Plotnikov <dplotnikov@xxxxxxxxxxxxx> --- arch/x86/kvm/vmx.c | 17 ++++++++++++++++- include/uapi/linux/kvm.h | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 1689f433f3a0..9c9b840537de 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7269,6 +7269,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) unsigned long exit_qualification; gpa_t gpa; u64 error_code; + int r; exit_qualification = vmcs_readl(EXIT_QUALIFICATION); @@ -7305,7 +7306,21 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; vcpu->arch.exit_qualification = exit_qualification; - return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0); + + r = kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0); + + if (r == -EFAULT) { + unsigned long hva; + + hva = kvm_vcpu_gfn_to_hva(vcpu, gpa >> PAGE_SHIFT); + + vcpu->run->exit_reason = KVM_EXIT_FAIL_MEM_ACCESS; + vcpu->run->hw.hardware_exit_reason = EXIT_REASON_EPT_VIOLATION; + vcpu->run->fail_mem_access.hva = hva | (gpa & (PAGE_SIZE-1)); + r = 0; + } + + return r; } static int handle_ept_misconfig(struct kvm_vcpu *vcpu) diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index b6270a3b38e9..6dee323d87a7 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -235,6 +235,7 @@ struct kvm_hyperv_exit { #define KVM_EXIT_S390_STSI 25 #define KVM_EXIT_IOAPIC_EOI 26 #define KVM_EXIT_HYPERV 27 +#define KVM_EXIT_FAIL_MEM_ACCESS 28 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -392,6 +393,11 @@ struct kvm_run { } eoi; /* KVM_EXIT_HYPERV */ struct kvm_hyperv_exit hyperv; + + /* KVM_EXIT_FAIL_MEM_ACCESS */ + struct { + __u64 hva; + } fail_mem_access; /* Fix the size of the union. */ char padding[256]; }; -- 2.17.0