kvm: x86: Allow to respond to generic signals during slow PF
authorPeter Xu <peterx@redhat.com>
Tue, 11 Oct 2022 19:59:47 +0000 (15:59 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 9 Nov 2022 17:31:28 +0000 (12:31 -0500)
Enable x86 slow page faults to be able to respond to non-fatal signals,
returning -EINTR properly when it happens.

Signed-off-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20221011195947.557281-1-peterx@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/mmu/mmu.c

index 0bbfb33..5d662b4 100644 (file)
@@ -3149,8 +3149,13 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *
        send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, PAGE_SHIFT, tsk);
 }
 
-static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)
+static int kvm_handle_error_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)
 {
+       if (is_sigpending_pfn(pfn)) {
+               kvm_handle_signal_exit(vcpu);
+               return -EINTR;
+       }
+
        /*
         * Do not cache the mmio info caused by writing the readonly gfn
         * into the spte otherwise read access on readonly gfn also can
@@ -3172,7 +3177,7 @@ static int handle_abnormal_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fau
 {
        /* The pfn is invalid, report the error! */
        if (unlikely(is_error_pfn(fault->pfn)))
-               return kvm_handle_bad_page(vcpu, fault->gfn, fault->pfn);
+               return kvm_handle_error_pfn(vcpu, fault->gfn, fault->pfn);
 
        if (unlikely(!fault->slot)) {
                gva_t gva = fault->is_tdp ? 0 : fault->addr;
@@ -4187,7 +4192,12 @@ static int kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
                }
        }
 
-       fault->pfn = __gfn_to_pfn_memslot(slot, fault->gfn, false, false, NULL,
+       /*
+        * Allow gup to bail on pending non-fatal signals when it's also allowed
+        * to wait for IO.  Note, gup always bails if it is unable to quickly
+        * get a page and a fatal signal, i.e. SIGKILL, is pending.
+        */
+       fault->pfn = __gfn_to_pfn_memslot(slot, fault->gfn, false, true, NULL,
                                          fault->write, &fault->map_writable,
                                          &fault->hva);
        return RET_PF_CONTINUE;