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

Commit d3ed1cee authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Christian Borntraeger
Browse files

s390/mm: set and get guest storage key mmap locking



Move the mmap semaphore locking out of set_guest_storage_key
and get_guest_storage_key. This makes the two functions more
like the other ptep_xxx operations and allows to avoid repeated
semaphore operations if multiple keys are read or written.

Reviewed-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent c427c42c
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -1050,26 +1050,30 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
	if (!keys)
		return -ENOMEM;

	down_read(&current->mm->mmap_sem);
	for (i = 0; i < args->count; i++) {
		hva = gfn_to_hva(kvm, args->start_gfn + i);
		if (kvm_is_error_hva(hva)) {
			r = -EFAULT;
			goto out;
			break;
		}

		curkey = get_guest_storage_key(current->mm, hva);
		if (IS_ERR_VALUE(curkey)) {
			r = curkey;
			goto out;
			break;
		}
		keys[i] = curkey;
	}
	up_read(&current->mm->mmap_sem);

	if (!r) {
		r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys,
				 sizeof(uint8_t) * args->count);
		if (r)
			r = -EFAULT;
out:
	}

	kvfree(keys);
	return r;
}
@@ -1106,24 +1110,26 @@ static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
	if (r)
		goto out;

	down_read(&current->mm->mmap_sem);
	for (i = 0; i < args->count; i++) {
		hva = gfn_to_hva(kvm, args->start_gfn + i);
		if (kvm_is_error_hva(hva)) {
			r = -EFAULT;
			goto out;
			break;
		}

		/* Lowest order bit is reserved */
		if (keys[i] & 0x01) {
			r = -EINVAL;
			goto out;
			break;
		}

		r = set_guest_storage_key(current->mm, hva,
					  (unsigned long)keys[i], 0);
		if (r)
			goto out;
			break;
	}
	up_read(&current->mm->mmap_sem);
out:
	kvfree(keys);
	return r;
+5 −2
Original line number Diff line number Diff line
@@ -728,9 +728,12 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)

			if (rc)
				return rc;
			if (set_guest_storage_key(current->mm, useraddr,
			down_read(&current->mm->mmap_sem);
			rc = set_guest_storage_key(current->mm, useraddr,
					vcpu->run->s.regs.gprs[reg1] & PFMF_KEY,
					vcpu->run->s.regs.gprs[reg1] & PFMF_NQ))
					vcpu->run->s.regs.gprs[reg1] & PFMF_NQ);
			up_read(&current->mm->mmap_sem);
			if (rc)
				return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
		}

+3 −12
Original line number Diff line number Diff line
@@ -506,12 +506,9 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
	pgste_t old, new;
	pte_t *ptep;

	down_read(&mm->mmap_sem);
	ptep = get_locked_pte(mm, addr, &ptl);
	if (unlikely(!ptep)) {
		up_read(&mm->mmap_sem);
	if (unlikely(!ptep))
		return -EFAULT;
	}

	new = old = pgste_get_lock(ptep);
	pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT |
@@ -538,7 +535,6 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,

	pgste_set_unlock(ptep, new);
	pte_unmap_unlock(ptep, ptl);
	up_read(&mm->mmap_sem);
	return 0;
}
EXPORT_SYMBOL(set_guest_storage_key);
@@ -550,14 +546,11 @@ unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
	pgste_t pgste;
	pte_t *ptep;

	down_read(&mm->mmap_sem);
	ptep = get_locked_pte(mm, addr, &ptl);
	if (unlikely(!ptep)) {
		up_read(&mm->mmap_sem);
	if (unlikely(!ptep))
		return -EFAULT;
	}
	pgste = pgste_get_lock(ptep);

	pgste = pgste_get_lock(ptep);
	if (pte_val(*ptep) & _PAGE_INVALID) {
		key  = (pgste_val(pgste) & PGSTE_ACC_BITS) >> 56;
		key |= (pgste_val(pgste) & PGSTE_FP_BIT) >> 56;
@@ -572,10 +565,8 @@ unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
		if (pgste_val(pgste) & PGSTE_GC_BIT)
			key |= _PAGE_CHANGED;
	}

	pgste_set_unlock(ptep, pgste);
	pte_unmap_unlock(ptep, ptl);
	up_read(&mm->mmap_sem);
	return key;
}
EXPORT_SYMBOL(get_guest_storage_key);