All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL 0/5] rcu annotation fixes for KVM
@ 2017-07-10 10:49 Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 1/5] KVM: mark vcpu->pid pointer as rcu protected Christian Borntraeger
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Christian Borntraeger @ 2017-07-10 10:49 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: KVM, Christian Borntraeger

Paolo, Radim,

with these rcu annotations KVM is now almost sparse clean and the code
should also detect rcu misuses earlier.

FWIW, there is one one remaining sparse warning 

virt/kvm/irqchip.c:171:28: warning: symbol 'kvm_arch_irq_routing_update' was not declared. Should it be static?

which seems to be triggered by sparse thinking that the global  
declaration in include/linux/kvm_host.h
void kvm_arch_irq_routing_update(struct kvm *kvm);
is not compatible with the weak definition in virt/kvm/irqchip.c
void __attribute__((weak)) kvm_arch_irq_routing_update(struct kvm *kvm)

Not sure what to do about that.


The following changes since commit 1372324b328cd5dabaef5e345e37ad48c63df2a9:

  Update my email address (2017-07-04 14:03:02 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux.git  annotations

for you to fetch changes up to 7e988b103d0d52190244517edc76e649071284bb:

  KVM: use correct accessor function for __kvm_memslots (2017-07-10 12:28:46 +0200)

----------------------------------------------------------------
Christian Borntraeger (5):
      KVM: mark vcpu->pid pointer as rcu protected
      KVM: use rcu access function for irq routing
      KVM: mark kvm->busses as rcu protected
      KVM: mark memory slots as rcu
      KVM: use correct accessor function for __kvm_memslots

 include/linux/kvm_host.h | 17 +++++++++++------
 virt/kvm/eventfd.c       |  8 +++++---
 virt/kvm/irqchip.c       |  2 +-
 virt/kvm/kvm_main.c      | 38 +++++++++++++++++++++++++-------------
 4 files changed, 42 insertions(+), 23 deletions(-)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [GIT PULL 1/5] KVM: mark vcpu->pid pointer as rcu protected
  2017-07-10 10:49 [GIT PULL 0/5] rcu annotation fixes for KVM Christian Borntraeger
@ 2017-07-10 10:49 ` Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 2/5] KVM: use rcu access function for irq routing Christian Borntraeger
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Borntraeger @ 2017-07-10 10:49 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: KVM, Christian Borntraeger

We do use rcu to protect the pid pointer. Mark it as such and
adopt all code to use the proper access methods.

This was detected by sparse.
"virt/kvm/kvm_main.c:2248:15: error: incompatible types in comparison
expression (different address spaces)"

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/linux/kvm_host.h |  2 +-
 virt/kvm/kvm_main.c      | 15 +++++++++++----
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 0b50e7b..bcd37b8 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -234,7 +234,7 @@ struct kvm_vcpu {
 
 	int guest_fpu_loaded, guest_xcr0_loaded;
 	struct swait_queue_head wq;
-	struct pid *pid;
+	struct pid __rcu *pid;
 	int sigset_active;
 	sigset_t sigset;
 	struct kvm_vcpu_stat stat;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 19f0ecb..fc2d583 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -293,7 +293,12 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_init);
 
 void kvm_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
-	put_pid(vcpu->pid);
+	/*
+	 * no need for rcu_read_lock as VCPU_RUN is the only place that
+	 * will change the vcpu->pid pointer and on uninit all file
+	 * descriptors are already gone.
+	 */
+	put_pid(rcu_dereference_protected(vcpu->pid, 1));
 	kvm_arch_vcpu_uninit(vcpu);
 	free_page((unsigned long)vcpu->run);
 }
@@ -2551,13 +2556,14 @@ static long kvm_vcpu_ioctl(struct file *filp,
 	if (r)
 		return r;
 	switch (ioctl) {
-	case KVM_RUN:
+	case KVM_RUN: {
+		struct pid *oldpid;
 		r = -EINVAL;
 		if (arg)
 			goto out;
-		if (unlikely(vcpu->pid != current->pids[PIDTYPE_PID].pid)) {
+		oldpid = rcu_access_pointer(vcpu->pid);
+		if (unlikely(oldpid != current->pids[PIDTYPE_PID].pid)) {
 			/* The thread running this VCPU changed. */
-			struct pid *oldpid = vcpu->pid;
 			struct pid *newpid = get_task_pid(current, PIDTYPE_PID);
 
 			rcu_assign_pointer(vcpu->pid, newpid);
@@ -2568,6 +2574,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
 		r = kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);
 		trace_kvm_userspace_exit(vcpu->run->exit_reason, r);
 		break;
+	}
 	case KVM_GET_REGS: {
 		struct kvm_regs *kvm_regs;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [GIT PULL 2/5] KVM: use rcu access function for irq routing
  2017-07-10 10:49 [GIT PULL 0/5] rcu annotation fixes for KVM Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 1/5] KVM: mark vcpu->pid pointer as rcu protected Christian Borntraeger
@ 2017-07-10 10:49 ` Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 3/5] KVM: mark kvm->busses as rcu protected Christian Borntraeger
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Borntraeger @ 2017-07-10 10:49 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: KVM, Christian Borntraeger

irq routing is rcu protected. Use the proper access functions.
Found by sparse

virt/kvm/irqchip.c:233:13: warning: incorrect type in assignment (different address spaces)
virt/kvm/irqchip.c:233:13:    expected struct kvm_irq_routing_table *old
virt/kvm/irqchip.c:233:13:    got struct kvm_irq_routing_table [noderef] <asn:4>*irq_routing

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 virt/kvm/irqchip.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 31e40c9..b1286c4 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -230,7 +230,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
 	}
 
 	mutex_lock(&kvm->irq_lock);
-	old = kvm->irq_routing;
+	old = rcu_dereference_protected(kvm->irq_routing, 1);
 	rcu_assign_pointer(kvm->irq_routing, new);
 	kvm_irq_routing_update(kvm);
 	kvm_arch_irq_routing_update(kvm);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [GIT PULL 3/5] KVM: mark kvm->busses as rcu protected
  2017-07-10 10:49 [GIT PULL 0/5] rcu annotation fixes for KVM Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 1/5] KVM: mark vcpu->pid pointer as rcu protected Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 2/5] KVM: use rcu access function for irq routing Christian Borntraeger
@ 2017-07-10 10:49 ` Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 4/5] KVM: mark memory slots as rcu Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 5/5] KVM: use correct accessor function for __kvm_memslots Christian Borntraeger
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Borntraeger @ 2017-07-10 10:49 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: KVM, Christian Borntraeger

mark kvm->busses as rcu protected and use the correct access
function everywhere.

found by sparse
virt/kvm/kvm_main.c:3490:15: error: incompatible types in comparison expression (different address spaces)
virt/kvm/kvm_main.c:3509:15: error: incompatible types in comparison expression (different address spaces)
virt/kvm/kvm_main.c:3561:15: error: incompatible types in comparison expression (different address spaces)
virt/kvm/kvm_main.c:3644:15: error: incompatible types in comparison expression (different address spaces)

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 include/linux/kvm_host.h |  8 +++++++-
 virt/kvm/eventfd.c       |  8 +++++---
 virt/kvm/kvm_main.c      | 17 ++++++++++-------
 3 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index bcd37b8..6a164f9 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -404,7 +404,7 @@ struct kvm {
 	int last_boosted_vcpu;
 	struct list_head vm_list;
 	struct mutex lock;
-	struct kvm_io_bus *buses[KVM_NR_BUSES];
+	struct kvm_io_bus __rcu *buses[KVM_NR_BUSES];
 #ifdef CONFIG_HAVE_KVM_EVENTFD
 	struct {
 		spinlock_t        lock;
@@ -473,6 +473,12 @@ struct kvm {
 #define vcpu_err(vcpu, fmt, ...)					\
 	kvm_err("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
 
+static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, enum kvm_bus idx)
+{
+	return srcu_dereference_check(kvm->buses[idx], &kvm->srcu,
+				      lockdep_is_held(&kvm->slots_lock));
+}
+
 static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
 {
 	/* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu, in case
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index a8d5403..d016aad 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -825,7 +825,7 @@ static int kvm_assign_ioeventfd_idx(struct kvm *kvm,
 	if (ret < 0)
 		goto unlock_fail;
 
-	kvm->buses[bus_idx]->ioeventfd_count++;
+	kvm_get_bus(kvm, bus_idx)->ioeventfd_count++;
 	list_add_tail(&p->list, &kvm->ioeventfds);
 
 	mutex_unlock(&kvm->slots_lock);
@@ -848,6 +848,7 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
 {
 	struct _ioeventfd        *p, *tmp;
 	struct eventfd_ctx       *eventfd;
+	struct kvm_io_bus	 *bus;
 	int                       ret = -ENOENT;
 
 	eventfd = eventfd_ctx_fdget(args->fd);
@@ -870,8 +871,9 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
 			continue;
 
 		kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
-		if (kvm->buses[bus_idx])
-			kvm->buses[bus_idx]->ioeventfd_count--;
+		bus = kvm_get_bus(kvm, bus_idx);
+		if (bus)
+			bus->ioeventfd_count--;
 		ioeventfd_release(p);
 		ret = 0;
 		break;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index fc2d583..d76e822 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -679,8 +679,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
 	if (init_srcu_struct(&kvm->irq_srcu))
 		goto out_err_no_irq_srcu;
 	for (i = 0; i < KVM_NR_BUSES; i++) {
-		kvm->buses[i] = kzalloc(sizeof(struct kvm_io_bus),
-					GFP_KERNEL);
+		rcu_assign_pointer(kvm->buses[i],
+			kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL));
 		if (!kvm->buses[i])
 			goto out_err;
 	}
@@ -705,7 +705,7 @@ static struct kvm *kvm_create_vm(unsigned long type)
 	hardware_disable_all();
 out_err_no_disable:
 	for (i = 0; i < KVM_NR_BUSES; i++)
-		kfree(kvm->buses[i]);
+		kfree(rcu_access_pointer(kvm->buses[i]));
 	for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
 		kvm_free_memslots(kvm, kvm->memslots[i]);
 	kvm_arch_free_vm(kvm);
@@ -740,8 +740,11 @@ static void kvm_destroy_vm(struct kvm *kvm)
 	spin_unlock(&kvm_lock);
 	kvm_free_irq_routing(kvm);
 	for (i = 0; i < KVM_NR_BUSES; i++) {
-		if (kvm->buses[i])
-			kvm_io_bus_destroy(kvm->buses[i]);
+		struct kvm_io_bus *bus;
+
+		bus = rcu_dereference_protected(kvm->buses[i], 1);
+		if (bus)
+			kvm_io_bus_destroy(bus);
 		kvm->buses[i] = NULL;
 	}
 	kvm_coalesced_mmio_free(kvm);
@@ -3570,7 +3573,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 {
 	struct kvm_io_bus *new_bus, *bus;
 
-	bus = kvm->buses[bus_idx];
+	bus = kvm_get_bus(kvm, bus_idx);
 	if (!bus)
 		return -ENOMEM;
 
@@ -3599,7 +3602,7 @@ void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
 	int i;
 	struct kvm_io_bus *new_bus, *bus;
 
-	bus = kvm->buses[bus_idx];
+	bus = kvm_get_bus(kvm, bus_idx);
 	if (!bus)
 		return;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [GIT PULL 4/5] KVM: mark memory slots as rcu
  2017-07-10 10:49 [GIT PULL 0/5] rcu annotation fixes for KVM Christian Borntraeger
                   ` (2 preceding siblings ...)
  2017-07-10 10:49 ` [GIT PULL 3/5] KVM: mark kvm->busses as rcu protected Christian Borntraeger
@ 2017-07-10 10:49 ` Christian Borntraeger
  2017-07-10 10:49 ` [GIT PULL 5/5] KVM: use correct accessor function for __kvm_memslots Christian Borntraeger
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Borntraeger @ 2017-07-10 10:49 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: KVM, Christian Borntraeger

we access the memslots array via srcu. Mark it as such and
use the right access functions also for the freeing of
memory slots.

Found by sparse:
./include/linux/kvm_host.h:565:16: error: incompatible types in
comparison expression (different address spaces)

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/linux/kvm_host.h | 2 +-
 virt/kvm/kvm_main.c      | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 6a164f9..b3ca77a 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -390,7 +390,7 @@ struct kvm {
 	spinlock_t mmu_lock;
 	struct mutex slots_lock;
 	struct mm_struct *mm; /* userspace tied to this vm */
-	struct kvm_memslots *memslots[KVM_ADDRESS_SPACE_NUM];
+	struct kvm_memslots __rcu *memslots[KVM_ADDRESS_SPACE_NUM];
 	struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
 
 	/*
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index d76e822..6e6d4ed 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -707,7 +707,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
 	for (i = 0; i < KVM_NR_BUSES; i++)
 		kfree(rcu_access_pointer(kvm->buses[i]));
 	for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
-		kvm_free_memslots(kvm, kvm->memslots[i]);
+		kvm_free_memslots(kvm,
+			rcu_dereference_protected(kvm->memslots[i], 1));
 	kvm_arch_free_vm(kvm);
 	mmdrop(current->mm);
 	return ERR_PTR(r);
@@ -756,7 +757,8 @@ static void kvm_destroy_vm(struct kvm *kvm)
 	kvm_arch_destroy_vm(kvm);
 	kvm_destroy_devices(kvm);
 	for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
-		kvm_free_memslots(kvm, kvm->memslots[i]);
+		kvm_free_memslots(kvm,
+			rcu_dereference_protected(kvm->memslots[i], 1));
 	cleanup_srcu_struct(&kvm->irq_srcu);
 	cleanup_srcu_struct(&kvm->srcu);
 	kvm_arch_free_vm(kvm);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [GIT PULL 5/5] KVM: use correct accessor function for __kvm_memslots
  2017-07-10 10:49 [GIT PULL 0/5] rcu annotation fixes for KVM Christian Borntraeger
                   ` (3 preceding siblings ...)
  2017-07-10 10:49 ` [GIT PULL 4/5] KVM: mark memory slots as rcu Christian Borntraeger
@ 2017-07-10 10:49 ` Christian Borntraeger
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Borntraeger @ 2017-07-10 10:49 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář; +Cc: KVM, Christian Borntraeger

kvm memslots are protected by srcu and not by rcu. We must use
srcu_dereference_check instead of rcu_dereference_check.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/linux/kvm_host.h | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b3ca77a..648b34c 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -568,9 +568,8 @@ void kvm_put_kvm(struct kvm *kvm);
 
 static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id)
 {
-	return rcu_dereference_check(kvm->memslots[as_id],
-			srcu_read_lock_held(&kvm->srcu)
-			|| lockdep_is_held(&kvm->slots_lock));
+	return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu,
+			lockdep_is_held(&kvm->slots_lock));
 }
 
 static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-07-10 10:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-10 10:49 [GIT PULL 0/5] rcu annotation fixes for KVM Christian Borntraeger
2017-07-10 10:49 ` [GIT PULL 1/5] KVM: mark vcpu->pid pointer as rcu protected Christian Borntraeger
2017-07-10 10:49 ` [GIT PULL 2/5] KVM: use rcu access function for irq routing Christian Borntraeger
2017-07-10 10:49 ` [GIT PULL 3/5] KVM: mark kvm->busses as rcu protected Christian Borntraeger
2017-07-10 10:49 ` [GIT PULL 4/5] KVM: mark memory slots as rcu Christian Borntraeger
2017-07-10 10:49 ` [GIT PULL 5/5] KVM: use correct accessor function for __kvm_memslots Christian Borntraeger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.