]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
9849b777ebc6dd0855ab81dacb785a164a8b6b1f
[thirdparty/kernel/stable-queue.git] /
1 From 9a6e7c39810e4a8bc7fc95056cefb40583fe07ef Mon Sep 17 00:00:00 2001
2 From: Wanpeng Li <wanpeng.li@hotmail.com>
3 Date: Thu, 14 Sep 2017 03:54:16 -0700
4 Subject: KVM: async_pf: Fix #DF due to inject "Page not Present" and "Page Ready" exceptions simultaneously
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: Wanpeng Li <wanpeng.li@hotmail.com>
10
11 commit 9a6e7c39810e4a8bc7fc95056cefb40583fe07ef upstream.
12
13 qemu-system-x86-8600 [004] d..1 7205.687530: kvm_entry: vcpu 2
14 qemu-system-x86-8600 [004] .... 7205.687532: kvm_exit: reason EXCEPTION_NMI rip 0xffffffffa921297d info ffffeb2c0e44e018 80000b0e
15 qemu-system-x86-8600 [004] .... 7205.687532: kvm_page_fault: address ffffeb2c0e44e018 error_code 0
16 qemu-system-x86-8600 [004] .... 7205.687620: kvm_try_async_get_page: gva = 0xffffeb2c0e44e018, gfn = 0x427e4e
17 qemu-system-x86-8600 [004] .N.. 7205.687628: kvm_async_pf_not_present: token 0x8b002 gva 0xffffeb2c0e44e018
18 kworker/4:2-7814 [004] .... 7205.687655: kvm_async_pf_completed: gva 0xffffeb2c0e44e018 address 0x7fcc30c4e000
19 qemu-system-x86-8600 [004] .... 7205.687703: kvm_async_pf_ready: token 0x8b002 gva 0xffffeb2c0e44e018
20 qemu-system-x86-8600 [004] d..1 7205.687711: kvm_entry: vcpu 2
21
22 After running some memory intensive workload in guest, I catch the kworker
23 which completes the GUP too quickly, and queues an "Page Ready" #PF exception
24 after the "Page not Present" exception before the next vmentry as the above
25 trace which will result in #DF injected to guest.
26
27 This patch fixes it by clearing the queue for "Page not Present" if "Page Ready"
28 occurs before the next vmentry since the GUP has already got the required page
29 and shadow page table has already been fixed by "Page Ready" handler.
30
31 Cc: Paolo Bonzini <pbonzini@redhat.com>
32 Cc: Radim Krčmář <rkrcmar@redhat.com>
33 Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
34 Fixes: 7c90705bf2a3 ("KVM: Inject asynchronous page fault into a PV guest if page is swapped out.")
35 [Changed indentation and added clearing of injected. - Radim]
36 Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
37 [port from upstream v4.14-rc1, Don't assign to kvm_queued_exception::injected or
38 x86_exception::async_page_fault]
39 Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com>
40 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
41
42 ---
43 arch/x86/kvm/x86.c | 34 ++++++++++++++++++++++++++--------
44 1 file changed, 26 insertions(+), 8 deletions(-)
45
46 --- a/arch/x86/kvm/x86.c
47 +++ b/arch/x86/kvm/x86.c
48 @@ -8210,6 +8210,13 @@ static int apf_put_user(struct kvm_vcpu
49 sizeof(val));
50 }
51
52 +static int apf_get_user(struct kvm_vcpu *vcpu, u32 *val)
53 +{
54 +
55 + return kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apf.data, val,
56 + sizeof(u32));
57 +}
58 +
59 void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
60 struct kvm_async_pf *work)
61 {
62 @@ -8236,6 +8243,7 @@ void kvm_arch_async_page_present(struct
63 struct kvm_async_pf *work)
64 {
65 struct x86_exception fault;
66 + u32 val;
67
68 if (work->wakeup_all)
69 work->arch.token = ~0; /* broadcast wakeup */
70 @@ -8243,14 +8251,24 @@ void kvm_arch_async_page_present(struct
71 kvm_del_async_pf_gfn(vcpu, work->arch.gfn);
72 trace_kvm_async_pf_ready(work->arch.token, work->gva);
73
74 - if ((vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED) &&
75 - !apf_put_user(vcpu, KVM_PV_REASON_PAGE_READY)) {
76 - fault.vector = PF_VECTOR;
77 - fault.error_code_valid = true;
78 - fault.error_code = 0;
79 - fault.nested_page_fault = false;
80 - fault.address = work->arch.token;
81 - kvm_inject_page_fault(vcpu, &fault);
82 + if (vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED &&
83 + !apf_get_user(vcpu, &val)) {
84 + if (val == KVM_PV_REASON_PAGE_NOT_PRESENT &&
85 + vcpu->arch.exception.pending &&
86 + vcpu->arch.exception.nr == PF_VECTOR &&
87 + !apf_put_user(vcpu, 0)) {
88 + vcpu->arch.exception.pending = false;
89 + vcpu->arch.exception.nr = 0;
90 + vcpu->arch.exception.has_error_code = false;
91 + vcpu->arch.exception.error_code = 0;
92 + } else if (!apf_put_user(vcpu, KVM_PV_REASON_PAGE_READY)) {
93 + fault.vector = PF_VECTOR;
94 + fault.error_code_valid = true;
95 + fault.error_code = 0;
96 + fault.nested_page_fault = false;
97 + fault.address = work->arch.token;
98 + kvm_inject_page_fault(vcpu, &fault);
99 + }
100 }
101 vcpu->arch.apf.halted = false;
102 vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;