提交 d3ed1cee 编写于 作者: M Martin Schwidefsky 提交者: Christian Borntraeger

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: NDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: NChristian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: NMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: NChristian Borntraeger <borntraeger@de.ibm.com>
上级 c427c42c
...@@ -1050,26 +1050,30 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args) ...@@ -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(&current->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(&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;
}
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) ...@@ -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(&current->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(&current->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) ...@@ -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(&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_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); 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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册