* [PATCH v2 1/3] KVM: fix rcu usage warning in kvm_arch_vcpu_ioctl_set_sregs() @ 2011-01-07 7:46 Xiao Guangrong 2011-01-07 7:47 ` [PATCH v2 2/3] KVM: send IPI to vcpu only when it's in guest mode Xiao Guangrong 2011-01-07 7:48 ` [PATCH v2 3/3] KVM: make make_all_cpus_request() lockless Xiao Guangrong 0 siblings, 2 replies; 5+ messages in thread From: Xiao Guangrong @ 2011-01-07 7:46 UTC (permalink / raw) To: Avi Kivity; +Cc: Marcelo Tosatti, LKML, KVM Fix: [ 1001.499596] =================================================== [ 1001.499599] [ INFO: suspicious rcu_dereference_check() usage. ] [ 1001.499601] --------------------------------------------------- [ 1001.499604] include/linux/kvm_host.h:301 invoked rcu_dereference_check() without protection! ...... [ 1001.499636] Pid: 6035, comm: qemu-system-x86 Not tainted 2.6.37-rc6+ #62 [ 1001.499638] Call Trace: [ 1001.499644] [<ffffffff81076cf6>] lockdep_rcu_dereference+0x9d/0xa5 [ 1001.499653] [<ffffffffa02567a6>] gfn_to_memslot+0x8d/0xc8 [kvm] [ 1001.499661] [<ffffffffa0256824>] gfn_to_hva+0x16/0x3f [kvm] [ 1001.499669] [<ffffffffa02568f5>] kvm_read_guest_page+0x1e/0x5e [kvm] [ 1001.499681] [<ffffffffa026c24a>] kvm_read_guest_page_mmu+0x53/0x5e [kvm] [ 1001.499699] [<ffffffffa026c294>] load_pdptrs+0x3f/0x9c [kvm] [ 1001.499705] [<ffffffffa00d825e>] ? vmx_set_cr0+0x507/0x517 [kvm_intel] [ 1001.499717] [<ffffffffa026ca56>] kvm_arch_vcpu_ioctl_set_sregs+0x1f3/0x3c0 [kvm] [ 1001.499727] [<ffffffffa025a410>] kvm_vcpu_ioctl+0x6a5/0xbc5 [kvm] Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> --- arch/x86/kvm/x86.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fa708c9..0b77e9c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5571,7 +5571,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) { int mmu_reset_needed = 0; - int pending_vec, max_bits; + int pending_vec, max_bits, idx; struct desc_ptr dt; dt.size = sregs->idt.limit; @@ -5600,10 +5600,13 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, kvm_x86_ops->set_cr4(vcpu, sregs->cr4); if (sregs->cr4 & X86_CR4_OSXSAVE) update_cpuid(vcpu); + + idx = srcu_read_lock(&vcpu->kvm->srcu); if (!is_long_mode(vcpu) && is_pae(vcpu)) { load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu)); mmu_reset_needed = 1; } + srcu_read_unlock(&vcpu->kvm->srcu, idx); if (mmu_reset_needed) kvm_mmu_reset_context(vcpu); -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] KVM: send IPI to vcpu only when it's in guest mode 2011-01-07 7:46 [PATCH v2 1/3] KVM: fix rcu usage warning in kvm_arch_vcpu_ioctl_set_sregs() Xiao Guangrong @ 2011-01-07 7:47 ` Xiao Guangrong 2011-01-07 11:55 ` Marcelo Tosatti 2011-01-07 7:48 ` [PATCH v2 3/3] KVM: make make_all_cpus_request() lockless Xiao Guangrong 1 sibling, 1 reply; 5+ messages in thread From: Xiao Guangrong @ 2011-01-07 7:47 UTC (permalink / raw) To: Avi Kivity; +Cc: Marcelo Tosatti, LKML, KVM We can interrupt the vcpu only when it's running in guest mode to reduce IPI It looks like only ia64 and x86 need to send IPI to other vcpus, so i only add the implementation of 'vcpu->guest_mode' in ia64, but i don't know ia64 well, please point out the right way for me if the implementation is incorrect Also reorganize struct kvm_vcpu to make ->guest_mode and ->requests in the same cache line explicitly. Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> --- arch/ia64/kvm/kvm-ia64.c | 2 ++ arch/x86/kvm/x86.c | 6 +++++- include/linux/kvm_host.h | 9 +++++---- virt/kvm/kvm_main.c | 7 ++++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 70d224d..15c11b2 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -662,6 +662,7 @@ again: goto vcpu_run_fail; srcu_read_unlock(&vcpu->kvm->srcu, idx); + atomic_set(&vcpu->guest_mode, 1); kvm_guest_enter(); /* @@ -683,6 +684,7 @@ again: */ barrier(); kvm_guest_exit(); + atomic_set(&vcpu->guest_mode, 0); preempt_enable(); idx = srcu_read_lock(&vcpu->kvm->srcu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0b77e9c..f882158 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5214,7 +5214,11 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) kvm_load_guest_xcr0(vcpu); atomic_set(&vcpu->guest_mode, 1); - smp_wmb(); + + /* We should set ->guest_mode before check ->requests, + * see the comment in make_all_cpus_request. + */ + smp_mb(); local_irq_disable(); diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index b5021db..5f5ef74 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -103,14 +103,15 @@ struct kvm_vcpu { #ifdef CONFIG_PREEMPT_NOTIFIERS struct preempt_notifier preempt_notifier; #endif + int cpu; int vcpu_id; - struct mutex mutex; - int cpu; + int srcu_idx; atomic_t guest_mode; - struct kvm_run *run; unsigned long requests; unsigned long guest_debug; - int srcu_idx; + + struct mutex mutex; + struct kvm_run *run; int fpu_active; int guest_fpu_loaded, guest_xcr0_loaded; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index b1b6cbb..a475264 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -153,7 +153,12 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) if (kvm_make_check_request(req, vcpu)) continue; cpu = vcpu->cpu; - if (cpus != NULL && cpu != -1 && cpu != me) + + /* Set ->requests bit before we read ->guest_mode */ + smp_mb(); + + if (cpus != NULL && cpu != -1 && cpu != me && + atomic_read(&vcpu->guest_mode)) cpumask_set_cpu(cpu, cpus); } if (unlikely(cpus == NULL)) -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/3] KVM: send IPI to vcpu only when it's in guest mode 2011-01-07 7:47 ` [PATCH v2 2/3] KVM: send IPI to vcpu only when it's in guest mode Xiao Guangrong @ 2011-01-07 11:55 ` Marcelo Tosatti 2011-01-09 10:00 ` Avi Kivity 0 siblings, 1 reply; 5+ messages in thread From: Marcelo Tosatti @ 2011-01-07 11:55 UTC (permalink / raw) To: Xiao Guangrong; +Cc: Avi Kivity, LKML, KVM On Fri, Jan 07, 2011 at 03:47:51PM +0800, Xiao Guangrong wrote: > We can interrupt the vcpu only when it's running in guest mode > to reduce IPI > > It looks like only ia64 and x86 need to send IPI to other vcpus, so > i only add the implementation of 'vcpu->guest_mode' in ia64, but i > don't know ia64 well, please point out the right way for me if the > implementation is incorrect > > Also reorganize struct kvm_vcpu to make ->guest_mode and ->requests > in the same cache line explicitly. > > Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> > --- > arch/ia64/kvm/kvm-ia64.c | 2 ++ > arch/x86/kvm/x86.c | 6 +++++- > include/linux/kvm_host.h | 9 +++++---- > virt/kvm/kvm_main.c | 7 ++++++- > 4 files changed, 18 insertions(+), 6 deletions(-) > > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index b1b6cbb..a475264 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -153,7 +153,12 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) > if (kvm_make_check_request(req, vcpu)) > continue; > cpu = vcpu->cpu; > - if (cpus != NULL && cpu != -1 && cpu != me) > + > + /* Set ->requests bit before we read ->guest_mode */ > + smp_mb(); > + > + if (cpus != NULL && cpu != -1 && cpu != me && > + atomic_read(&vcpu->guest_mode)) > cpumask_set_cpu(cpu, cpus); Don't think this is safe, since guest_mode does not imply that a vcpu has received the IPI, only that IPI has been sent (see kvm_vcpu_kick). And make_all_cpus_request must guarantee all target vcpus are out of guest mode before it returns. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/3] KVM: send IPI to vcpu only when it's in guest mode 2011-01-07 11:55 ` Marcelo Tosatti @ 2011-01-09 10:00 ` Avi Kivity 0 siblings, 0 replies; 5+ messages in thread From: Avi Kivity @ 2011-01-09 10:00 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Xiao Guangrong, LKML, KVM On 01/07/2011 01:55 PM, Marcelo Tosatti wrote: > On Fri, Jan 07, 2011 at 03:47:51PM +0800, Xiao Guangrong wrote: > > We can interrupt the vcpu only when it's running in guest mode > > to reduce IPI > > > > It looks like only ia64 and x86 need to send IPI to other vcpus, so > > i only add the implementation of 'vcpu->guest_mode' in ia64, but i > > don't know ia64 well, please point out the right way for me if the > > implementation is incorrect > > > > Also reorganize struct kvm_vcpu to make ->guest_mode and ->requests > > in the same cache line explicitly. > > > > Signed-off-by: Xiao Guangrong<xiaoguangrong@cn.fujitsu.com> > > --- > > arch/ia64/kvm/kvm-ia64.c | 2 ++ > > arch/x86/kvm/x86.c | 6 +++++- > > include/linux/kvm_host.h | 9 +++++---- > > virt/kvm/kvm_main.c | 7 ++++++- > > 4 files changed, 18 insertions(+), 6 deletions(-) > > > > > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > > index b1b6cbb..a475264 100644 > > --- a/virt/kvm/kvm_main.c > > +++ b/virt/kvm/kvm_main.c > > @@ -153,7 +153,12 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) > > if (kvm_make_check_request(req, vcpu)) > > continue; > > cpu = vcpu->cpu; > > - if (cpus != NULL&& cpu != -1&& cpu != me) > > + > > + /* Set ->requests bit before we read ->guest_mode */ > > + smp_mb(); > > + > > + if (cpus != NULL&& cpu != -1&& cpu != me&& > > + atomic_read(&vcpu->guest_mode)) > > cpumask_set_cpu(cpu, cpus); > > Don't think this is safe, since guest_mode does not imply that a vcpu > has received the IPI, only that IPI has been sent (see kvm_vcpu_kick). > > And make_all_cpus_request must guarantee all target vcpus are out of > guest mode before it returns. > Good catch. We could remove the atomic_xchg() in kvm_vcpu_kick(), but need to think of any drawbacks to that. Maybe we could replace guest_mode with a three value variable: in guest, outside guest, and transitioning out of guest. So kvm_vcpu_kick() avoids the IPI on the last two, while make_all_cpus_request() only avoids an IPI if outside guest mode. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] KVM: make make_all_cpus_request() lockless 2011-01-07 7:46 [PATCH v2 1/3] KVM: fix rcu usage warning in kvm_arch_vcpu_ioctl_set_sregs() Xiao Guangrong 2011-01-07 7:47 ` [PATCH v2 2/3] KVM: send IPI to vcpu only when it's in guest mode Xiao Guangrong @ 2011-01-07 7:48 ` Xiao Guangrong 1 sibling, 0 replies; 5+ messages in thread From: Xiao Guangrong @ 2011-01-07 7:48 UTC (permalink / raw) To: Avi Kivity; +Cc: Marcelo Tosatti, LKML, KVM Now, we have 'vcpu->guest_mode' to judge whether need to send ipi to other cpus, this way is very exact, so checking request bit is needless, then we can drop the spinlock let it's collateral Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> --- include/linux/kvm_host.h | 6 ------ virt/kvm/kvm_main.c | 11 ++++------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 5f5ef74..72b6dde 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -213,7 +213,6 @@ struct kvm_memslots { struct kvm { spinlock_t mmu_lock; - raw_spinlock_t requests_lock; struct mutex slots_lock; struct mm_struct *mm; /* userspace tied to this vm */ struct kvm_memslots *memslots; @@ -720,11 +719,6 @@ static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu) set_bit(req, &vcpu->requests); } -static inline bool kvm_make_check_request(int req, struct kvm_vcpu *vcpu) -{ - return test_and_set_bit(req, &vcpu->requests); -} - static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu) { if (test_bit(req, &vcpu->requests)) { diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index a475264..1afcdcd 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -147,16 +147,14 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) zalloc_cpumask_var(&cpus, GFP_ATOMIC); - raw_spin_lock(&kvm->requests_lock); - me = smp_processor_id(); + me = get_cpu(); kvm_for_each_vcpu(i, vcpu, kvm) { - if (kvm_make_check_request(req, vcpu)) - continue; - cpu = vcpu->cpu; + kvm_make_request(req, vcpu); /* Set ->requests bit before we read ->guest_mode */ smp_mb(); + cpu = vcpu->cpu; if (cpus != NULL && cpu != -1 && cpu != me && atomic_read(&vcpu->guest_mode)) cpumask_set_cpu(cpu, cpus); @@ -167,7 +165,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) smp_call_function_many(cpus, ack_flush, NULL, 1); else called = false; - raw_spin_unlock(&kvm->requests_lock); + put_cpu(); free_cpumask_var(cpus); return called; } @@ -433,7 +431,6 @@ static struct kvm *kvm_create_vm(void) kvm->mm = current->mm; atomic_inc(&kvm->mm->mm_count); spin_lock_init(&kvm->mmu_lock); - raw_spin_lock_init(&kvm->requests_lock); kvm_eventfd_init(kvm); mutex_init(&kvm->lock); mutex_init(&kvm->irq_lock); -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-01-09 10:00 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-01-07 7:46 [PATCH v2 1/3] KVM: fix rcu usage warning in kvm_arch_vcpu_ioctl_set_sregs() Xiao Guangrong 2011-01-07 7:47 ` [PATCH v2 2/3] KVM: send IPI to vcpu only when it's in guest mode Xiao Guangrong 2011-01-07 11:55 ` Marcelo Tosatti 2011-01-09 10:00 ` Avi Kivity 2011-01-07 7:48 ` [PATCH v2 3/3] KVM: make make_all_cpus_request() lockless Xiao Guangrong
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox