aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/priv.c
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2011-11-17 05:00:43 -0500
committerAvi Kivity <avi@redhat.com>2011-11-17 09:25:48 -0500
commit1eddb85f889a5a9fe59ec184e06844716a00aded (patch)
treec789c7cd507f3e5fa5150dc8f6e44efc1e2ab866 /arch/s390/kvm/priv.c
parentbd59d3a4444e5f941c863db1a7715edf7289e29a (diff)
KVM: s390: Fix tprot locking
There is a potential host deadlock in the tprot intercept handling. We must not hold the mmap semaphore while resolving the guest address. If userspace is remapping, then the memory detection in the guest is broken anyway so we can safely separate the address translation from walking the vmas. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Carsten Otte <cotte@de.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/s390/kvm/priv.c')
-rw-r--r--arch/s390/kvm/priv.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 391626361084..d02638959922 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -336,6 +336,7 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
336 u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0; 336 u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
337 u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0; 337 u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
338 struct vm_area_struct *vma; 338 struct vm_area_struct *vma;
339 unsigned long user_address;
339 340
340 vcpu->stat.instruction_tprot++; 341 vcpu->stat.instruction_tprot++;
341 342
@@ -349,9 +350,14 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
349 return -EOPNOTSUPP; 350 return -EOPNOTSUPP;
350 351
351 352
353 /* we must resolve the address without holding the mmap semaphore.
354 * This is ok since the userspace hypervisor is not supposed to change
355 * the mapping while the guest queries the memory. Otherwise the guest
356 * might crash or get wrong info anyway. */
357 user_address = (unsigned long) __guestaddr_to_user(vcpu, address1);
358
352 down_read(&current->mm->mmap_sem); 359 down_read(&current->mm->mmap_sem);
353 vma = find_vma(current->mm, 360 vma = find_vma(current->mm, user_address);
354 (unsigned long) __guestaddr_to_user(vcpu, address1));
355 if (!vma) { 361 if (!vma) {
356 up_read(&current->mm->mmap_sem); 362 up_read(&current->mm->mmap_sem);
357 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 363 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);