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: David Hildenbrand <dahi@linux.vnet.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>
This commit is contained in:
parent
c427c42cd6
commit
d3ed1ceeac
|
@ -1050,26 +1050,30 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
|
||||||
if (!keys)
|
if (!keys)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
down_read(¤t->mm->mmap_sem);
|
||||||
for (i = 0; i < args->count; i++) {
|
for (i = 0; i < args->count; i++) {
|
||||||
hva = gfn_to_hva(kvm, args->start_gfn + i);
|
hva = gfn_to_hva(kvm, args->start_gfn + i);
|
||||||
if (kvm_is_error_hva(hva)) {
|
if (kvm_is_error_hva(hva)) {
|
||||||
r = -EFAULT;
|
r = -EFAULT;
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
curkey = get_guest_storage_key(current->mm, hva);
|
curkey = get_guest_storage_key(current->mm, hva);
|
||||||
if (IS_ERR_VALUE(curkey)) {
|
if (IS_ERR_VALUE(curkey)) {
|
||||||
r = curkey;
|
r = curkey;
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
keys[i] = curkey;
|
keys[i] = curkey;
|
||||||
}
|
}
|
||||||
|
up_read(¤t->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;
|
||||||
|
}
|
||||||
|
|
||||||
r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys,
|
|
||||||
sizeof(uint8_t) * args->count);
|
|
||||||
if (r)
|
|
||||||
r = -EFAULT;
|
|
||||||
out:
|
|
||||||
kvfree(keys);
|
kvfree(keys);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1106,24 +1110,26 @@ static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
|
||||||
if (r)
|
if (r)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
down_read(¤t->mm->mmap_sem);
|
||||||
for (i = 0; i < args->count; i++) {
|
for (i = 0; i < args->count; i++) {
|
||||||
hva = gfn_to_hva(kvm, args->start_gfn + i);
|
hva = gfn_to_hva(kvm, args->start_gfn + i);
|
||||||
if (kvm_is_error_hva(hva)) {
|
if (kvm_is_error_hva(hva)) {
|
||||||
r = -EFAULT;
|
r = -EFAULT;
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lowest order bit is reserved */
|
/* Lowest order bit is reserved */
|
||||||
if (keys[i] & 0x01) {
|
if (keys[i] & 0x01) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = set_guest_storage_key(current->mm, hva,
|
r = set_guest_storage_key(current->mm, hva,
|
||||||
(unsigned long)keys[i], 0);
|
(unsigned long)keys[i], 0);
|
||||||
if (r)
|
if (r)
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
|
up_read(¤t->mm->mmap_sem);
|
||||||
out:
|
out:
|
||||||
kvfree(keys);
|
kvfree(keys);
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -728,9 +728,12 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
if (set_guest_storage_key(current->mm, useraddr,
|
down_read(¤t->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_KEY,
|
||||||
vcpu->run->s.regs.gprs[reg1] & PFMF_NQ))
|
vcpu->run->s.regs.gprs[reg1] & PFMF_NQ);
|
||||||
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
if (rc)
|
||||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -506,12 +506,9 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
|
||||||
pgste_t old, new;
|
pgste_t old, new;
|
||||||
pte_t *ptep;
|
pte_t *ptep;
|
||||||
|
|
||||||
down_read(&mm->mmap_sem);
|
|
||||||
ptep = get_locked_pte(mm, addr, &ptl);
|
ptep = get_locked_pte(mm, addr, &ptl);
|
||||||
if (unlikely(!ptep)) {
|
if (unlikely(!ptep))
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
new = old = pgste_get_lock(ptep);
|
new = old = pgste_get_lock(ptep);
|
||||||
pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT |
|
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);
|
pgste_set_unlock(ptep, new);
|
||||||
pte_unmap_unlock(ptep, ptl);
|
pte_unmap_unlock(ptep, ptl);
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(set_guest_storage_key);
|
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;
|
pgste_t pgste;
|
||||||
pte_t *ptep;
|
pte_t *ptep;
|
||||||
|
|
||||||
down_read(&mm->mmap_sem);
|
|
||||||
ptep = get_locked_pte(mm, addr, &ptl);
|
ptep = get_locked_pte(mm, addr, &ptl);
|
||||||
if (unlikely(!ptep)) {
|
if (unlikely(!ptep))
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
pgste = pgste_get_lock(ptep);
|
|
||||||
|
|
||||||
|
pgste = pgste_get_lock(ptep);
|
||||||
if (pte_val(*ptep) & _PAGE_INVALID) {
|
if (pte_val(*ptep) & _PAGE_INVALID) {
|
||||||
key = (pgste_val(pgste) & PGSTE_ACC_BITS) >> 56;
|
key = (pgste_val(pgste) & PGSTE_ACC_BITS) >> 56;
|
||||||
key |= (pgste_val(pgste) & PGSTE_FP_BIT) >> 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)
|
if (pgste_val(pgste) & PGSTE_GC_BIT)
|
||||||
key |= _PAGE_CHANGED;
|
key |= _PAGE_CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
pgste_set_unlock(ptep, pgste);
|
pgste_set_unlock(ptep, pgste);
|
||||||
pte_unmap_unlock(ptep, ptl);
|
pte_unmap_unlock(ptep, ptl);
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(get_guest_storage_key);
|
EXPORT_SYMBOL(get_guest_storage_key);
|
||||||
|
|
Loading…
Reference in New Issue