aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-05-03 09:54:48 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 03:35:37 -0400
commitd94e1dc9af60e3431a586c3edfbe42d8a0d3932b (patch)
treec9ae8e5e69241d51898ab657d0ff48004b5bd4dc
parent54b8486f469475d6c8e8aec917b91239a54eb8c8 (diff)
KVM: Get rid of KVM_REQ_KICK
KVM_REQ_KICK poisons vcpu->requests by having a bit set during normal operation. This causes the fast path check for a clear vcpu->requests to fail all the time, triggering tons of atomic operations. Fix by replacing KVM_REQ_KICK with a vcpu->guest_mode atomic. Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/x86/kvm/x86.c17
-rw-r--r--include/linux/kvm_host.h1
2 files changed, 11 insertions, 7 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 63c87adcec48..fc5611b4007f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4604,13 +4604,15 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
4604 if (vcpu->fpu_active) 4604 if (vcpu->fpu_active)
4605 kvm_load_guest_fpu(vcpu); 4605 kvm_load_guest_fpu(vcpu);
4606 4606
4607 local_irq_disable(); 4607 atomic_set(&vcpu->guest_mode, 1);
4608 smp_wmb();
4608 4609
4609 clear_bit(KVM_REQ_KICK, &vcpu->requests); 4610 local_irq_disable();
4610 smp_mb__after_clear_bit();
4611 4611
4612 if (vcpu->requests || need_resched() || signal_pending(current)) { 4612 if (!atomic_read(&vcpu->guest_mode) || vcpu->requests
4613 set_bit(KVM_REQ_KICK, &vcpu->requests); 4613 || need_resched() || signal_pending(current)) {
4614 atomic_set(&vcpu->guest_mode, 0);
4615 smp_wmb();
4614 local_irq_enable(); 4616 local_irq_enable();
4615 preempt_enable(); 4617 preempt_enable();
4616 r = 1; 4618 r = 1;
@@ -4655,7 +4657,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
4655 if (hw_breakpoint_active()) 4657 if (hw_breakpoint_active())
4656 hw_breakpoint_restore(); 4658 hw_breakpoint_restore();
4657 4659
4658 set_bit(KVM_REQ_KICK, &vcpu->requests); 4660 atomic_set(&vcpu->guest_mode, 0);
4661 smp_wmb();
4659 local_irq_enable(); 4662 local_irq_enable();
4660 4663
4661 ++vcpu->stat.exits; 4664 ++vcpu->stat.exits;
@@ -5580,7 +5583,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
5580 5583
5581 me = get_cpu(); 5584 me = get_cpu();
5582 if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) 5585 if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu))
5583 if (!test_and_set_bit(KVM_REQ_KICK, &vcpu->requests)) 5586 if (atomic_xchg(&vcpu->guest_mode, 0))
5584 smp_send_reschedule(cpu); 5587 smp_send_reschedule(cpu);
5585 put_cpu(); 5588 put_cpu();
5586} 5589}
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a0e019769f5d..2c62319727ef 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -81,6 +81,7 @@ struct kvm_vcpu {
81 int vcpu_id; 81 int vcpu_id;
82 struct mutex mutex; 82 struct mutex mutex;
83 int cpu; 83 int cpu;
84 atomic_t guest_mode;
84 struct kvm_run *run; 85 struct kvm_run *run;
85 unsigned long requests; 86 unsigned long requests;
86 unsigned long guest_debug; 87 unsigned long guest_debug;