diff options
| author | Marcelo Tosatti <mtosatti@redhat.com> | 2009-06-17 09:53:47 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@redhat.com> | 2009-06-28 07:10:29 -0400 |
| commit | 84261923d3dddb766736023bead6fa07b7e218d5 (patch) | |
| tree | 23a0c4af14dd9c548c5bcb457c74fdd980e2312e | |
| parent | 29a4b9333bf9ffef12b3dd7cbf2e3dbe01152968 (diff) | |
KVM: protect concurrent make_all_cpus_request
make_all_cpus_request contains a race condition which can
trigger false request completed status, as follows:
CPU0 CPU1
if (test_and_set_bit(req,&vcpu->requests))
.... if (test_and_set_bit(req,&vcpu->requests))
.. return
proceed to smp_call_function_many(wait=1)
Use a spinlock to serialize concurrent CPUs.
Cc: stable@kernel.org
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
| -rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
| -rw-r--r-- | virt/kvm/kvm_main.c | 3 |
2 files changed, 4 insertions, 0 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index aacc5449f586..16713dc672e4 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
| @@ -125,6 +125,7 @@ struct kvm_kernel_irq_routing_entry { | |||
| 125 | struct kvm { | 125 | struct kvm { |
| 126 | struct mutex lock; /* protects the vcpus array and APIC accesses */ | 126 | struct mutex lock; /* protects the vcpus array and APIC accesses */ |
| 127 | spinlock_t mmu_lock; | 127 | spinlock_t mmu_lock; |
| 128 | spinlock_t requests_lock; | ||
| 128 | struct rw_semaphore slots_lock; | 129 | struct rw_semaphore slots_lock; |
| 129 | struct mm_struct *mm; /* userspace tied to this vm */ | 130 | struct mm_struct *mm; /* userspace tied to this vm */ |
| 130 | int nmemslots; | 131 | int nmemslots; |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 013a5b3e9f75..2884baf1d5f9 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -746,6 +746,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) | |||
| 746 | cpumask_clear(cpus); | 746 | cpumask_clear(cpus); |
| 747 | 747 | ||
| 748 | me = get_cpu(); | 748 | me = get_cpu(); |
| 749 | spin_lock(&kvm->requests_lock); | ||
| 749 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | 750 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { |
| 750 | vcpu = kvm->vcpus[i]; | 751 | vcpu = kvm->vcpus[i]; |
| 751 | if (!vcpu) | 752 | if (!vcpu) |
| @@ -762,6 +763,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) | |||
| 762 | smp_call_function_many(cpus, ack_flush, NULL, 1); | 763 | smp_call_function_many(cpus, ack_flush, NULL, 1); |
| 763 | else | 764 | else |
| 764 | called = false; | 765 | called = false; |
| 766 | spin_unlock(&kvm->requests_lock); | ||
| 765 | put_cpu(); | 767 | put_cpu(); |
| 766 | free_cpumask_var(cpus); | 768 | free_cpumask_var(cpus); |
| 767 | return called; | 769 | return called; |
| @@ -982,6 +984,7 @@ static struct kvm *kvm_create_vm(void) | |||
| 982 | kvm->mm = current->mm; | 984 | kvm->mm = current->mm; |
| 983 | atomic_inc(&kvm->mm->mm_count); | 985 | atomic_inc(&kvm->mm->mm_count); |
| 984 | spin_lock_init(&kvm->mmu_lock); | 986 | spin_lock_init(&kvm->mmu_lock); |
| 987 | spin_lock_init(&kvm->requests_lock); | ||
| 985 | kvm_io_bus_init(&kvm->pio_bus); | 988 | kvm_io_bus_init(&kvm->pio_bus); |
| 986 | mutex_init(&kvm->lock); | 989 | mutex_init(&kvm->lock); |
| 987 | kvm_io_bus_init(&kvm->mmio_bus); | 990 | kvm_io_bus_init(&kvm->mmio_bus); |
