Beispiel #1
0
static int handle_tprot(struct kvm_vcpu *vcpu)
{
	u64 address1, address2;
	struct vm_area_struct *vma;
	unsigned long user_address;

	vcpu->stat.instruction_tprot++;

	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);

	kvm_s390_get_base_disp_sse(vcpu, &address1, &address2);

	/* we only handle the Linux memory detection case:
	 * access key == 0
	 * guest DAT == off
	 * everything else goes to userspace. */
	if (address2 & 0xf0)
		return -EOPNOTSUPP;
	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
		return -EOPNOTSUPP;

	down_read(&current->mm->mmap_sem);
	user_address = __gmap_translate(address1, vcpu->arch.gmap);
	if (IS_ERR_VALUE(user_address))
		goto out_inject;
	vma = find_vma(current->mm, user_address);
	if (!vma)
		goto out_inject;
	vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
	if (!(vma->vm_flags & VM_WRITE) && (vma->vm_flags & VM_READ))
		vcpu->arch.sie_block->gpsw.mask |= (1ul << 44);
	if (!(vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_READ))
		vcpu->arch.sie_block->gpsw.mask |= (2ul << 44);

	up_read(&current->mm->mmap_sem);
	return 0;

out_inject:
	up_read(&current->mm->mmap_sem);
	return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
}
Beispiel #2
0
static int handle_tprot(struct kvm_vcpu *vcpu)
{
	u64 address1, address2;
	struct vm_area_struct *vma;
	unsigned long user_address;

	vcpu->stat.instruction_tprot++;

	kvm_s390_get_base_disp_sse(vcpu, &address1, &address2);

	/* we only handle the Linux memory detection case:
	 * access key == 0
	 * guest DAT == off
	 * everything else goes to userspace. */
	if (address2 & 0xf0)
		return -EOPNOTSUPP;
	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
		return -EOPNOTSUPP;


	/* we must resolve the address without holding the mmap semaphore.
	 * This is ok since the userspace hypervisor is not supposed to change
	 * the mapping while the guest queries the memory. Otherwise the guest
	 * might crash or get wrong info anyway. */
	user_address = (unsigned long) __guestaddr_to_user(vcpu, address1);

	down_read(&current->mm->mmap_sem);
	vma = find_vma(current->mm, user_address);
	if (!vma) {
		up_read(&current->mm->mmap_sem);
		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
	}

	vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
	if (!(vma->vm_flags & VM_WRITE) && (vma->vm_flags & VM_READ))
		vcpu->arch.sie_block->gpsw.mask |= (1ul << 44);
	if (!(vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_READ))
		vcpu->arch.sie_block->gpsw.mask |= (2ul << 44);

	up_read(&current->mm->mmap_sem);
	return 0;
}