diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2013-03-05 07:14:42 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-03-07 14:21:20 -0500 |
commit | 59a1fa2d80c0d351755cb29273b2b256dc4b3a11 (patch) | |
tree | 45c45e881ca3806a5d4c859519e471348c0d4a2d /arch/s390 | |
parent | 9e0fdb4145205bea95c2888a195c3ead2652f120 (diff) |
s390/kvm,tprot: use new gmap_translate() function
When out-of-memory the tprot code incorrectly injected a program check
for the guest which reported an addressing exception even if the guest
address was valid.
Let's use the new gmap_translate() which translates a guest address to
a user space address whithout the chance of running into an out-of-memory
situation.
Also make it more explicit that for -EFAULT we won't find a vma.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kvm/priv.c | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 0ef9894606e5..75ad91e38e8a 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -575,20 +575,13 @@ static int handle_tprot(struct kvm_vcpu *vcpu) | |||
575 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT) | 575 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT) |
576 | return -EOPNOTSUPP; | 576 | return -EOPNOTSUPP; |
577 | 577 | ||
578 | |||
579 | /* we must resolve the address without holding the mmap semaphore. | ||
580 | * This is ok since the userspace hypervisor is not supposed to change | ||
581 | * the mapping while the guest queries the memory. Otherwise the guest | ||
582 | * might crash or get wrong info anyway. */ | ||
583 | user_address = (unsigned long) __guestaddr_to_user(vcpu, address1); | ||
584 | |||
585 | down_read(¤t->mm->mmap_sem); | 578 | down_read(¤t->mm->mmap_sem); |
579 | user_address = __gmap_translate(address1, vcpu->arch.gmap); | ||
580 | if (IS_ERR_VALUE(user_address)) | ||
581 | goto out_inject; | ||
586 | vma = find_vma(current->mm, user_address); | 582 | vma = find_vma(current->mm, user_address); |
587 | if (!vma) { | 583 | if (!vma) |
588 | up_read(¤t->mm->mmap_sem); | 584 | goto out_inject; |
589 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
590 | } | ||
591 | |||
592 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | 585 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); |
593 | if (!(vma->vm_flags & VM_WRITE) && (vma->vm_flags & VM_READ)) | 586 | if (!(vma->vm_flags & VM_WRITE) && (vma->vm_flags & VM_READ)) |
594 | vcpu->arch.sie_block->gpsw.mask |= (1ul << 44); | 587 | vcpu->arch.sie_block->gpsw.mask |= (1ul << 44); |
@@ -597,6 +590,10 @@ static int handle_tprot(struct kvm_vcpu *vcpu) | |||
597 | 590 | ||
598 | up_read(¤t->mm->mmap_sem); | 591 | up_read(¤t->mm->mmap_sem); |
599 | return 0; | 592 | return 0; |
593 | |||
594 | out_inject: | ||
595 | up_read(¤t->mm->mmap_sem); | ||
596 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
600 | } | 597 | } |
601 | 598 | ||
602 | int kvm_s390_handle_e5(struct kvm_vcpu *vcpu) | 599 | int kvm_s390_handle_e5(struct kvm_vcpu *vcpu) |