diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-03-08 05:53:35 -0500 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2016-06-10 06:07:27 -0400 |
commit | d3ed1ceeace311af9973d17a07a114bfaf0ca1b1 (patch) | |
tree | 1e9a353c769d89bf8eee9489f931869dcaf0651a /arch/s390/kvm | |
parent | c427c42cd612719e8fb8b5891cc9761e7770024e (diff) |
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>
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 26 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 7 |
2 files changed, 21 insertions, 12 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 9d0e4d0487f4..d0156d7969e0 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -1050,26 +1050,30 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args) | |||
1050 | if (!keys) | 1050 | if (!keys) |
1051 | return -ENOMEM; | 1051 | return -ENOMEM; |
1052 | 1052 | ||
1053 | down_read(¤t->mm->mmap_sem); | ||
1053 | for (i = 0; i < args->count; i++) { | 1054 | for (i = 0; i < args->count; i++) { |
1054 | hva = gfn_to_hva(kvm, args->start_gfn + i); | 1055 | hva = gfn_to_hva(kvm, args->start_gfn + i); |
1055 | if (kvm_is_error_hva(hva)) { | 1056 | if (kvm_is_error_hva(hva)) { |
1056 | r = -EFAULT; | 1057 | r = -EFAULT; |
1057 | goto out; | 1058 | break; |
1058 | } | 1059 | } |
1059 | 1060 | ||
1060 | curkey = get_guest_storage_key(current->mm, hva); | 1061 | curkey = get_guest_storage_key(current->mm, hva); |
1061 | if (IS_ERR_VALUE(curkey)) { | 1062 | if (IS_ERR_VALUE(curkey)) { |
1062 | r = curkey; | 1063 | r = curkey; |
1063 | goto out; | 1064 | break; |
1064 | } | 1065 | } |
1065 | keys[i] = curkey; | 1066 | keys[i] = curkey; |
1066 | } | 1067 | } |
1068 | up_read(¤t->mm->mmap_sem); | ||
1069 | |||
1070 | if (!r) { | ||
1071 | r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys, | ||
1072 | sizeof(uint8_t) * args->count); | ||
1073 | if (r) | ||
1074 | r = -EFAULT; | ||
1075 | } | ||
1067 | 1076 | ||
1068 | r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys, | ||
1069 | sizeof(uint8_t) * args->count); | ||
1070 | if (r) | ||
1071 | r = -EFAULT; | ||
1072 | out: | ||
1073 | kvfree(keys); | 1077 | kvfree(keys); |
1074 | return r; | 1078 | return r; |
1075 | } | 1079 | } |
@@ -1106,24 +1110,26 @@ static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args) | |||
1106 | if (r) | 1110 | if (r) |
1107 | goto out; | 1111 | goto out; |
1108 | 1112 | ||
1113 | down_read(¤t->mm->mmap_sem); | ||
1109 | for (i = 0; i < args->count; i++) { | 1114 | for (i = 0; i < args->count; i++) { |
1110 | hva = gfn_to_hva(kvm, args->start_gfn + i); | 1115 | hva = gfn_to_hva(kvm, args->start_gfn + i); |
1111 | if (kvm_is_error_hva(hva)) { | 1116 | if (kvm_is_error_hva(hva)) { |
1112 | r = -EFAULT; | 1117 | r = -EFAULT; |
1113 | goto out; | 1118 | break; |
1114 | } | 1119 | } |
1115 | 1120 | ||
1116 | /* Lowest order bit is reserved */ | 1121 | /* Lowest order bit is reserved */ |
1117 | if (keys[i] & 0x01) { | 1122 | if (keys[i] & 0x01) { |
1118 | r = -EINVAL; | 1123 | r = -EINVAL; |
1119 | goto out; | 1124 | break; |
1120 | } | 1125 | } |
1121 | 1126 | ||
1122 | r = set_guest_storage_key(current->mm, hva, | 1127 | r = set_guest_storage_key(current->mm, hva, |
1123 | (unsigned long)keys[i], 0); | 1128 | (unsigned long)keys[i], 0); |
1124 | if (r) | 1129 | if (r) |
1125 | goto out; | 1130 | break; |
1126 | } | 1131 | } |
1132 | up_read(¤t->mm->mmap_sem); | ||
1127 | out: | 1133 | out: |
1128 | kvfree(keys); | 1134 | kvfree(keys); |
1129 | return r; | 1135 | return r; |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 95916fa7c670..c6deed782c61 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -728,9 +728,12 @@ static int handle_pfmf(struct kvm_vcpu *vcpu) | |||
728 | 728 | ||
729 | if (rc) | 729 | if (rc) |
730 | return rc; | 730 | return rc; |
731 | if (set_guest_storage_key(current->mm, useraddr, | 731 | down_read(¤t->mm->mmap_sem); |
732 | rc = set_guest_storage_key(current->mm, useraddr, | ||
732 | vcpu->run->s.regs.gprs[reg1] & PFMF_KEY, | 733 | vcpu->run->s.regs.gprs[reg1] & PFMF_KEY, |
733 | vcpu->run->s.regs.gprs[reg1] & PFMF_NQ)) | 734 | vcpu->run->s.regs.gprs[reg1] & PFMF_NQ); |
735 | up_read(¤t->mm->mmap_sem); | ||
736 | if (rc) | ||
734 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 737 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
735 | } | 738 | } |
736 | 739 | ||