]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: s390: Storage key functions refactoring
authorClaudio Imbrenda <imbrenda@linux.ibm.com>
Wed, 4 Feb 2026 15:02:52 +0000 (16:02 +0100)
committerClaudio Imbrenda <imbrenda@linux.ibm.com>
Wed, 4 Feb 2026 16:00:09 +0000 (17:00 +0100)
Refactor some storage key functions to improve readability.

Introduce helper functions that will be used in the next patches.

Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
arch/s390/kvm/gaccess.c
arch/s390/kvm/gaccess.h
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h

index 9df868bddf9a1bfaf1d0fcfc0028b34f351199f7..2649365bf054d4e2ab69a3086bc3adfedb0b900b 100644 (file)
@@ -961,7 +961,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  *            *@old_addr contains the value at @gpa before the attempt to
  *            exchange the value.
  * @new: The value to place at @gpa.
- * @access_key: The access key to use for the guest access.
+ * @acc: The access key to use for the guest access.
  * @success: output value indicating if an exchange occurred.
  *
  * Atomically exchange the value at @gpa by @new, if it contains *@old.
@@ -974,9 +974,8 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  *         * -EAGAIN: transient failure (len 1 or 2)
  *         * -EOPNOTSUPP: read-only memslot (should never occur)
  */
-int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len,
-                              __uint128_t *old_addr, __uint128_t new,
-                              u8 access_key, bool *success)
+int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, union kvm_s390_quad *old_addr,
+                              union kvm_s390_quad new, u8 acc, bool *success)
 {
        gfn_t gfn = gpa_to_gfn(gpa);
        struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
@@ -1008,41 +1007,42 @@ int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len,
        case 1: {
                u8 old;
 
-               ret = cmpxchg_user_key((u8 __user *)hva, &old, *old_addr, new, access_key);
-               *success = !ret && old == *old_addr;
-               *old_addr = old;
+               ret = cmpxchg_user_key((u8 __user *)hva, &old, old_addr->one, new.one, acc);
+               *success = !ret && old == old_addr->one;
+               old_addr->one = old;
                break;
        }
        case 2: {
                u16 old;
 
-               ret = cmpxchg_user_key((u16 __user *)hva, &old, *old_addr, new, access_key);
-               *success = !ret && old == *old_addr;
-               *old_addr = old;
+               ret = cmpxchg_user_key((u16 __user *)hva, &old, old_addr->two, new.two, acc);
+               *success = !ret && old == old_addr->two;
+               old_addr->two = old;
                break;
        }
        case 4: {
                u32 old;
 
-               ret = cmpxchg_user_key((u32 __user *)hva, &old, *old_addr, new, access_key);
-               *success = !ret && old == *old_addr;
-               *old_addr = old;
+               ret = cmpxchg_user_key((u32 __user *)hva, &old, old_addr->four, new.four, acc);
+               *success = !ret && old == old_addr->four;
+               old_addr->four = old;
                break;
        }
        case 8: {
                u64 old;
 
-               ret = cmpxchg_user_key((u64 __user *)hva, &old, *old_addr, new, access_key);
-               *success = !ret && old == *old_addr;
-               *old_addr = old;
+               ret = cmpxchg_user_key((u64 __user *)hva, &old, old_addr->eight, new.eight, acc);
+               *success = !ret && old == old_addr->eight;
+               old_addr->eight = old;
                break;
        }
        case 16: {
                __uint128_t old;
 
-               ret = cmpxchg_user_key((__uint128_t __user *)hva, &old, *old_addr, new, access_key);
-               *success = !ret && old == *old_addr;
-               *old_addr = old;
+               ret = cmpxchg_user_key((__uint128_t __user *)hva, &old, old_addr->sixteen,
+                                      new.sixteen, acc);
+               *success = !ret && old == old_addr->sixteen;
+               old_addr->sixteen = old;
                break;
        }
        default:
index 3fde45a151f22ec89f7185dff9898f69e6632a9a..774cdf19998f81713dd8e842140c77de3c665b83 100644 (file)
@@ -206,8 +206,8 @@ int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
 int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
                      void *data, unsigned long len, enum gacc_mode mode);
 
-int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, __uint128_t *old,
-                              __uint128_t new, u8 access_key, bool *success);
+int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, union kvm_s390_quad *old_addr,
+                              union kvm_s390_quad new, u8 access_key, bool *success);
 
 /**
  * write_guest_with_key - copy data from kernel space to guest space
index 2b5ecdc3814e95e573f4489442847b83c92fec24..f5411e093fb5be53b28126d71785e5c228909284 100644 (file)
@@ -2900,9 +2900,9 @@ static int mem_op_validate_common(struct kvm_s390_mem_op *mop, u64 supported_fla
 static int kvm_s390_vm_mem_op_abs(struct kvm *kvm, struct kvm_s390_mem_op *mop)
 {
        void __user *uaddr = (void __user *)mop->buf;
+       void *tmpbuf __free(kvfree) = NULL;
        enum gacc_mode acc_mode;
-       void *tmpbuf = NULL;
-       int r, srcu_idx;
+       int r;
 
        r = mem_op_validate_common(mop, KVM_S390_MEMOP_F_SKEY_PROTECTION |
                                        KVM_S390_MEMOP_F_CHECK_ONLY);
@@ -2915,52 +2915,36 @@ static int kvm_s390_vm_mem_op_abs(struct kvm *kvm, struct kvm_s390_mem_op *mop)
                        return -ENOMEM;
        }
 
-       srcu_idx = srcu_read_lock(&kvm->srcu);
+       acc_mode = mop->op == KVM_S390_MEMOP_ABSOLUTE_READ ? GACC_FETCH : GACC_STORE;
 
-       if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr)) {
-               r = PGM_ADDRESSING;
-               goto out_unlock;
-       }
+       scoped_guard(srcu, &kvm->srcu) {
+               if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr))
+                       return PGM_ADDRESSING;
 
-       acc_mode = mop->op == KVM_S390_MEMOP_ABSOLUTE_READ ? GACC_FETCH : GACC_STORE;
-       if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
-               r = check_gpa_range(kvm, mop->gaddr, mop->size, acc_mode, mop->key);
-               goto out_unlock;
-       }
-       if (acc_mode == GACC_FETCH) {
+               if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)
+                       return check_gpa_range(kvm, mop->gaddr, mop->size, acc_mode, mop->key);
+
+               if (acc_mode == GACC_STORE && copy_from_user(tmpbuf, uaddr, mop->size))
+                       return -EFAULT;
                r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
-                                             mop->size, GACC_FETCH, mop->key);
+                                             mop->size, acc_mode, mop->key);
                if (r)
-                       goto out_unlock;
-               if (copy_to_user(uaddr, tmpbuf, mop->size))
-                       r = -EFAULT;
-       } else {
-               if (copy_from_user(tmpbuf, uaddr, mop->size)) {
-                       r = -EFAULT;
-                       goto out_unlock;
-               }
-               r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
-                                             mop->size, GACC_STORE, mop->key);
+                       return r;
+               if (acc_mode != GACC_STORE && copy_to_user(uaddr, tmpbuf, mop->size))
+                       return -EFAULT;
        }
 
-out_unlock:
-       srcu_read_unlock(&kvm->srcu, srcu_idx);
-
-       vfree(tmpbuf);
-       return r;
+       return 0;
 }
 
 static int kvm_s390_vm_mem_op_cmpxchg(struct kvm *kvm, struct kvm_s390_mem_op *mop)
 {
        void __user *uaddr = (void __user *)mop->buf;
        void __user *old_addr = (void __user *)mop->old_addr;
-       union {
-               __uint128_t quad;
-               char raw[sizeof(__uint128_t)];
-       } old = { .quad = 0}, new = { .quad = 0 };
-       unsigned int off_in_quad = sizeof(new) - mop->size;
-       int r, srcu_idx;
-       bool success;
+       union kvm_s390_quad old = { .sixteen = 0 };
+       union kvm_s390_quad new = { .sixteen = 0 };
+       bool success = false;
+       int r;
 
        r = mem_op_validate_common(mop, KVM_S390_MEMOP_F_SKEY_PROTECTION);
        if (r)
@@ -2972,25 +2956,21 @@ static int kvm_s390_vm_mem_op_cmpxchg(struct kvm *kvm, struct kvm_s390_mem_op *m
         */
        if (mop->size > sizeof(new))
                return -EINVAL;
-       if (copy_from_user(&new.raw[off_in_quad], uaddr, mop->size))
+       if (copy_from_user(&new, uaddr, mop->size))
                return -EFAULT;
-       if (copy_from_user(&old.raw[off_in_quad], old_addr, mop->size))
+       if (copy_from_user(&old, old_addr, mop->size))
                return -EFAULT;
 
-       srcu_idx = srcu_read_lock(&kvm->srcu);
+       scoped_guard(srcu, &kvm->srcu) {
+               if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr))
+                       return PGM_ADDRESSING;
 
-       if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr)) {
-               r = PGM_ADDRESSING;
-               goto out_unlock;
-       }
-
-       r = cmpxchg_guest_abs_with_key(kvm, mop->gaddr, mop->size, &old.quad,
-                                      new.quad, mop->key, &success);
-       if (!success && copy_to_user(old_addr, &old.raw[off_in_quad], mop->size))
-               r = -EFAULT;
+               r = cmpxchg_guest_abs_with_key(kvm, mop->gaddr, mop->size, &old, new,
+                                              mop->key, &success);
 
-out_unlock:
-       srcu_read_unlock(&kvm->srcu, srcu_idx);
+               if (!success && copy_to_user(old_addr, &old, mop->size))
+                       return -EFAULT;
+       }
        return r;
 }
 
index 9ce71c8433a14f330797ce921e515f636a48ec64..c44c52266e2601e52cfaa30e3a7aaa3cca031ccc 100644 (file)
 
 #define KVM_S390_UCONTROL_MEMSLOT (KVM_USER_MEM_SLOTS + 0)
 
+union kvm_s390_quad {
+       __uint128_t sixteen;
+       unsigned long eight;
+       unsigned int four;
+       unsigned short two;
+       unsigned char one;
+};
+
 static inline void kvm_s390_fpu_store(struct kvm_run *run)
 {
        fpu_stfpc(&run->s.regs.fpc);