| From 337c017ccdf2653d0040099433fc1a2b1beb5926 Mon Sep 17 00:00:00 2001 |
| From: Wanpeng Li <wanpeng.li@hotmail.com> |
| Date: Tue, 1 Aug 2017 05:20:03 -0700 |
| Subject: KVM: async_pf: make rcu irq exit if not triggered from idle task |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Wanpeng Li <wanpeng.li@hotmail.com> |
| |
| commit 337c017ccdf2653d0040099433fc1a2b1beb5926 upstream. |
| |
| WARNING: CPU: 5 PID: 1242 at kernel/rcu/tree_plugin.h:323 rcu_note_context_switch+0x207/0x6b0 |
| CPU: 5 PID: 1242 Comm: unity-settings- Not tainted 4.13.0-rc2+ #1 |
| RIP: 0010:rcu_note_context_switch+0x207/0x6b0 |
| Call Trace: |
| __schedule+0xda/0xba0 |
| ? kvm_async_pf_task_wait+0x1b2/0x270 |
| schedule+0x40/0x90 |
| kvm_async_pf_task_wait+0x1cc/0x270 |
| ? prepare_to_swait+0x22/0x70 |
| do_async_page_fault+0x77/0xb0 |
| ? do_async_page_fault+0x77/0xb0 |
| async_page_fault+0x28/0x30 |
| RIP: 0010:__d_lookup_rcu+0x90/0x1e0 |
| |
| I encounter this when trying to stress the async page fault in L1 guest w/ |
| L2 guests running. |
| |
| Commit 9b132fbe5419 (Add rcu user eqs exception hooks for async page |
| fault) adds rcu_irq_enter/exit() to kvm_async_pf_task_wait() to exit cpu |
| idle eqs when needed, to protect the code that needs use rcu. However, |
| we need to call the pair even if the function calls schedule(), as seen |
| from the above backtrace. |
| |
| This patch fixes it by informing the RCU subsystem exit/enter the irq |
| towards/away from idle for both n.halted and !n.halted. |
| |
| Cc: Paolo Bonzini <pbonzini@redhat.com> |
| Cc: Radim Krčmář <rkrcmar@redhat.com> |
| Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> |
| Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com> |
| Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kernel/kvm.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/arch/x86/kernel/kvm.c |
| +++ b/arch/x86/kernel/kvm.c |
| @@ -151,6 +151,8 @@ void kvm_async_pf_task_wait(u32 token) |
| if (hlist_unhashed(&n.link)) |
| break; |
| |
| + rcu_irq_exit(); |
| + |
| if (!n.halted) { |
| local_irq_enable(); |
| schedule(); |
| @@ -159,11 +161,11 @@ void kvm_async_pf_task_wait(u32 token) |
| /* |
| * We cannot reschedule. So halt. |
| */ |
| - rcu_irq_exit(); |
| native_safe_halt(); |
| local_irq_disable(); |
| - rcu_irq_enter(); |
| } |
| + |
| + rcu_irq_enter(); |
| } |
| if (!n.halted) |
| finish_wait(&n.wq, &wait); |