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

Commit 79a8059d authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

KVM: svm: do not call kvm_set_cr0 from init_vmcb



kvm_set_cr0 may want to call kvm_zap_gfn_range and thus access the
memslots array (SRCU protected).  Using a mini SRCU critical section
is ugly, and adding it to kvm_arch_vcpu_create doesn't work because
the VMX vcpu_create callback calls synchronize_srcu.

Fixes this lockdep splat:

===============================
[ INFO: suspicious RCU usage. ]
4.3.0-rc1+ #1 Not tainted
-------------------------------
include/linux/kvm_host.h:488 suspicious rcu_dereference_check() usage!

other info that might help us debug this:
rcu_scheduler_active = 1, debug_locks = 0
1 lock held by qemu-system-i38/17000:
 #0:  (&(&kvm->mmu_lock)->rlock){+.+...}, at: kvm_zap_gfn_range+0x24/0x1a0 [kvm]

[...]
Call Trace:
 dump_stack+0x4e/0x84
 lockdep_rcu_suspicious+0xfd/0x130
 kvm_zap_gfn_range+0x188/0x1a0 [kvm]
 kvm_set_cr0+0xde/0x1e0 [kvm]
 init_vmcb+0x760/0xad0 [kvm_amd]
 svm_create_vcpu+0x197/0x250 [kvm_amd]
 kvm_arch_vcpu_create+0x47/0x70 [kvm]
 kvm_vm_ioctl+0x302/0x7e0 [kvm]
 ? __lock_is_held+0x51/0x70
 ? __fget+0x101/0x210
 do_vfs_ioctl+0x2f4/0x560
 ? __fget_light+0x29/0x90
 SyS_ioctl+0x4c/0x90
 entry_SYSCALL_64_fastpath+0x16/0x73

Reported-by: default avatarBorislav Petkov <bp@alien8.de>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 5b6a7175
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -202,6 +202,7 @@ module_param(npt, int, S_IRUGO);
static int nested = true;
static int nested = true;
module_param(nested, int, S_IRUGO);
module_param(nested, int, S_IRUGO);


static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
static void svm_flush_tlb(struct kvm_vcpu *vcpu);
static void svm_flush_tlb(struct kvm_vcpu *vcpu);
static void svm_complete_interrupts(struct vcpu_svm *svm);
static void svm_complete_interrupts(struct vcpu_svm *svm);


@@ -1263,7 +1264,7 @@ static void init_vmcb(struct vcpu_svm *svm, bool init_event)
	 * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0.
	 * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0.
	 * It also updates the guest-visible cr0 value.
	 * It also updates the guest-visible cr0 value.
	 */
	 */
	(void)kvm_set_cr0(&svm->vcpu, X86_CR0_NW | X86_CR0_CD | X86_CR0_ET);
	svm_set_cr0(&svm->vcpu, X86_CR0_NW | X86_CR0_CD | X86_CR0_ET);
	kvm_mmu_reset_context(&svm->vcpu);
	kvm_mmu_reset_context(&svm->vcpu);


	save->cr4 = X86_CR4_PAE;
	save->cr4 = X86_CR4_PAE;