Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84261923 authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Avi Kivity
Browse files

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: default avatarAndrea Arcangeli <aarcange@redhat.com>
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 29a4b933
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ struct kvm_kernel_irq_routing_entry {
struct kvm {
	struct mutex lock; /* protects the vcpus array and APIC accesses */
	spinlock_t mmu_lock;
	spinlock_t requests_lock;
	struct rw_semaphore slots_lock;
	struct mm_struct *mm; /* userspace tied to this vm */
	int nmemslots;
+3 −0
Original line number Diff line number Diff line
@@ -746,6 +746,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
		cpumask_clear(cpus);

	me = get_cpu();
	spin_lock(&kvm->requests_lock);
	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
		vcpu = kvm->vcpus[i];
		if (!vcpu)
@@ -762,6 +763,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;
	spin_unlock(&kvm->requests_lock);
	put_cpu();
	free_cpumask_var(cpus);
	return called;
@@ -982,6 +984,7 @@ static struct kvm *kvm_create_vm(void)
	kvm->mm = current->mm;
	atomic_inc(&kvm->mm->mm_count);
	spin_lock_init(&kvm->mmu_lock);
	spin_lock_init(&kvm->requests_lock);
	kvm_io_bus_init(&kvm->pio_bus);
	mutex_init(&kvm->lock);
	kvm_io_bus_init(&kvm->mmio_bus);