Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: use the correct RCU API for PROVE_RCU=y

The RCU/SRCU API have already changed for proving RCU usage.

I got the following dmesg when PROVE_RCU=y because we used incorrect API.
This patch coverts rcu_deference() to srcu_dereference() or family API.

===================================================
[ INFO: suspicious rcu_dereference_check() usage. ]
---------------------------------------------------
arch/x86/kvm/mmu.c:3020 invoked rcu_dereference_check() without protection!

other info that might help us debug this:

rcu_scheduler_active = 1, debug_locks = 0
2 locks held by qemu-system-x86/8550:
#0: (&kvm->slots_lock){+.+.+.}, at: [<ffffffffa011a6ac>] kvm_set_memory_region+0x29/0x50 [kvm]
#1: (&(&kvm->mmu_lock)->rlock){+.+...}, at: [<ffffffffa012262d>] kvm_arch_commit_memory_region+0xa6/0xe2 [kvm]

stack backtrace:
Pid: 8550, comm: qemu-system-x86 Not tainted 2.6.34-rc4-tip-01028-g939eab1 #27
Call Trace:
[<ffffffff8106c59e>] lockdep_rcu_dereference+0xaa/0xb3
[<ffffffffa012f6c1>] kvm_mmu_calculate_mmu_pages+0x44/0x7d [kvm]
[<ffffffffa012263e>] kvm_arch_commit_memory_region+0xb7/0xe2 [kvm]
[<ffffffffa011a5d7>] __kvm_set_memory_region+0x636/0x6e2 [kvm]
[<ffffffffa011a6ba>] kvm_set_memory_region+0x37/0x50 [kvm]
[<ffffffffa015e956>] vmx_set_tss_addr+0x46/0x5a [kvm_intel]
[<ffffffffa0126592>] kvm_arch_vm_ioctl+0x17a/0xcf8 [kvm]
[<ffffffff810a8692>] ? unlock_page+0x27/0x2c
[<ffffffff810bf879>] ? __do_fault+0x3a9/0x3e1
[<ffffffffa011b12f>] kvm_vm_ioctl+0x364/0x38d [kvm]
[<ffffffff81060cfa>] ? up_read+0x23/0x3d
[<ffffffff810f3587>] vfs_ioctl+0x32/0xa6
[<ffffffff810f3b19>] do_vfs_ioctl+0x495/0x4db
[<ffffffff810e6b2f>] ? fget_light+0xc2/0x241
[<ffffffff810e416c>] ? do_sys_open+0x104/0x116
[<ffffffff81382d6d>] ? retint_swapgs+0xe/0x13
[<ffffffff810f3ba6>] sys_ioctl+0x47/0x6a
[<ffffffff810021db>] system_call_fastpath+0x16/0x1b

Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>

authored by

Lai Jiangshan and committed by
Avi Kivity
90d83dc3 9beeaa2d

+33 -15
+1 -1
arch/ia64/kvm/kvm-ia64.c
··· 1381 1381 int i, j; 1382 1382 unsigned long base_gfn; 1383 1383 1384 - slots = rcu_dereference(kvm->memslots); 1384 + slots = kvm_memslots(kvm); 1385 1385 for (i = 0; i < slots->nmemslots; i++) { 1386 1386 memslot = &slots->memslots[i]; 1387 1387 base_gfn = memslot->base_gfn;
+1 -1
arch/s390/kvm/kvm-s390.h
··· 72 72 struct kvm_memslots *memslots; 73 73 74 74 idx = srcu_read_lock(&vcpu->kvm->srcu); 75 - memslots = rcu_dereference(vcpu->kvm->memslots); 75 + memslots = kvm_memslots(vcpu->kvm); 76 76 77 77 mem = &memslots->memslots[0]; 78 78
+4 -3
arch/x86/kvm/mmu.c
··· 787 787 int retval = 0; 788 788 struct kvm_memslots *slots; 789 789 790 - slots = rcu_dereference(kvm->memslots); 790 + slots = kvm_memslots(kvm); 791 791 792 792 for (i = 0; i < slots->nmemslots; i++) { 793 793 struct kvm_memory_slot *memslot = &slots->memslots[i]; ··· 3016 3016 unsigned int nr_pages = 0; 3017 3017 struct kvm_memslots *slots; 3018 3018 3019 - slots = rcu_dereference(kvm->memslots); 3019 + slots = kvm_memslots(kvm); 3020 + 3020 3021 for (i = 0; i < slots->nmemslots; i++) 3021 3022 nr_pages += slots->memslots[i].npages; 3022 3023 ··· 3293 3292 int i, j, k, idx; 3294 3293 3295 3294 idx = srcu_read_lock(&kvm->srcu); 3296 - slots = rcu_dereference(kvm->memslots); 3295 + slots = kvm_memslots(kvm); 3297 3296 for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { 3298 3297 struct kvm_memory_slot *m = &slots->memslots[i]; 3299 3298 struct kvm_rmap_desc *d;
+1 -1
arch/x86/kvm/vmx.c
··· 1558 1558 struct kvm_memslots *slots; 1559 1559 gfn_t base_gfn; 1560 1560 1561 - slots = rcu_dereference(kvm->memslots); 1561 + slots = kvm_memslots(kvm); 1562 1562 base_gfn = kvm->memslots->memslots[0].base_gfn + 1563 1563 kvm->memslots->memslots[0].npages - 3; 1564 1564 return base_gfn << PAGE_SHIFT;
+2 -2
arch/x86/kvm/x86.c
··· 2497 2497 struct kvm_mem_alias *alias; 2498 2498 struct kvm_mem_aliases *aliases; 2499 2499 2500 - aliases = rcu_dereference(kvm->arch.aliases); 2500 + aliases = kvm_aliases(kvm); 2501 2501 2502 2502 for (i = 0; i < aliases->naliases; ++i) { 2503 2503 alias = &aliases->aliases[i]; ··· 2516 2516 struct kvm_mem_alias *alias; 2517 2517 struct kvm_mem_aliases *aliases; 2518 2518 2519 - aliases = rcu_dereference(kvm->arch.aliases); 2519 + aliases = kvm_aliases(kvm); 2520 2520 2521 2521 for (i = 0; i < aliases->naliases; ++i) { 2522 2522 alias = &aliases->aliases[i];
+7
arch/x86/kvm/x86.h
··· 65 65 return kvm_read_cr0_bits(vcpu, X86_CR0_PG); 66 66 } 67 67 68 + static inline struct kvm_mem_aliases *kvm_aliases(struct kvm *kvm) 69 + { 70 + return rcu_dereference_check(kvm->arch.aliases, 71 + srcu_read_lock_held(&kvm->srcu) 72 + || lockdep_is_held(&kvm->slots_lock)); 73 + } 74 + 68 75 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); 69 76 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); 70 77
+7
include/linux/kvm_host.h
··· 250 250 void kvm_get_kvm(struct kvm *kvm); 251 251 void kvm_put_kvm(struct kvm *kvm); 252 252 253 + static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm) 254 + { 255 + return rcu_dereference_check(kvm->memslots, 256 + srcu_read_lock_held(&kvm->srcu) 257 + || lockdep_is_held(&kvm->slots_lock)); 258 + } 259 + 253 260 #define HPA_MSB ((sizeof(hpa_t) * 8) - 1) 254 261 #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB) 255 262 static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
+2 -2
virt/kvm/iommu.c
··· 78 78 int i, r = 0; 79 79 struct kvm_memslots *slots; 80 80 81 - slots = rcu_dereference(kvm->memslots); 81 + slots = kvm_memslots(kvm); 82 82 83 83 for (i = 0; i < slots->nmemslots; i++) { 84 84 r = kvm_iommu_map_pages(kvm, &slots->memslots[i]); ··· 217 217 int i; 218 218 struct kvm_memslots *slots; 219 219 220 - slots = rcu_dereference(kvm->memslots); 220 + slots = kvm_memslots(kvm); 221 221 222 222 for (i = 0; i < slots->nmemslots; i++) { 223 223 kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn,
+8 -5
virt/kvm/kvm_main.c
··· 834 834 struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn) 835 835 { 836 836 int i; 837 - struct kvm_memslots *slots = rcu_dereference(kvm->memslots); 837 + struct kvm_memslots *slots = kvm_memslots(kvm); 838 838 839 839 for (i = 0; i < slots->nmemslots; ++i) { 840 840 struct kvm_memory_slot *memslot = &slots->memslots[i]; ··· 856 856 int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) 857 857 { 858 858 int i; 859 - struct kvm_memslots *slots = rcu_dereference(kvm->memslots); 859 + struct kvm_memslots *slots = kvm_memslots(kvm); 860 860 861 861 gfn = unalias_gfn_instantiation(kvm, gfn); 862 862 for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { ··· 900 900 int memslot_id(struct kvm *kvm, gfn_t gfn) 901 901 { 902 902 int i; 903 - struct kvm_memslots *slots = rcu_dereference(kvm->memslots); 903 + struct kvm_memslots *slots = kvm_memslots(kvm); 904 904 struct kvm_memory_slot *memslot = NULL; 905 905 906 906 gfn = unalias_gfn(kvm, gfn); ··· 1994 1994 int len, const void *val) 1995 1995 { 1996 1996 int i; 1997 - struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]); 1997 + struct kvm_io_bus *bus; 1998 + 1999 + bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu); 1998 2000 for (i = 0; i < bus->dev_count; i++) 1999 2001 if (!kvm_iodevice_write(bus->devs[i], addr, len, val)) 2000 2002 return 0; ··· 2008 2006 int len, void *val) 2009 2007 { 2010 2008 int i; 2011 - struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]); 2009 + struct kvm_io_bus *bus; 2012 2010 2011 + bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu); 2013 2012 for (i = 0; i < bus->dev_count; i++) 2014 2013 if (!kvm_iodevice_read(bus->devs[i], addr, len, val)) 2015 2014 return 0;