Skip to content

Commit d29a29a

Browse files
author
Claudio Imbrenda
committed
KVM: s390: Storage key functions refactoring
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>
1 parent cc50f10 commit d29a29a

4 files changed

Lines changed: 59 additions & 71 deletions

File tree

arch/s390/kvm/gaccess.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
961961
* *@old_addr contains the value at @gpa before the attempt to
962962
* exchange the value.
963963
* @new: The value to place at @gpa.
964-
* @access_key: The access key to use for the guest access.
964+
* @acc: The access key to use for the guest access.
965965
* @success: output value indicating if an exchange occurred.
966966
*
967967
* 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,
974974
* * -EAGAIN: transient failure (len 1 or 2)
975975
* * -EOPNOTSUPP: read-only memslot (should never occur)
976976
*/
977-
int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len,
978-
__uint128_t *old_addr, __uint128_t new,
979-
u8 access_key, bool *success)
977+
int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, union kvm_s390_quad *old_addr,
978+
union kvm_s390_quad new, u8 acc, bool *success)
980979
{
981980
gfn_t gfn = gpa_to_gfn(gpa);
982981
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,
10081007
case 1: {
10091008
u8 old;
10101009

1011-
ret = cmpxchg_user_key((u8 __user *)hva, &old, *old_addr, new, access_key);
1012-
*success = !ret && old == *old_addr;
1013-
*old_addr = old;
1010+
ret = cmpxchg_user_key((u8 __user *)hva, &old, old_addr->one, new.one, acc);
1011+
*success = !ret && old == old_addr->one;
1012+
old_addr->one = old;
10141013
break;
10151014
}
10161015
case 2: {
10171016
u16 old;
10181017

1019-
ret = cmpxchg_user_key((u16 __user *)hva, &old, *old_addr, new, access_key);
1020-
*success = !ret && old == *old_addr;
1021-
*old_addr = old;
1018+
ret = cmpxchg_user_key((u16 __user *)hva, &old, old_addr->two, new.two, acc);
1019+
*success = !ret && old == old_addr->two;
1020+
old_addr->two = old;
10221021
break;
10231022
}
10241023
case 4: {
10251024
u32 old;
10261025

1027-
ret = cmpxchg_user_key((u32 __user *)hva, &old, *old_addr, new, access_key);
1028-
*success = !ret && old == *old_addr;
1029-
*old_addr = old;
1026+
ret = cmpxchg_user_key((u32 __user *)hva, &old, old_addr->four, new.four, acc);
1027+
*success = !ret && old == old_addr->four;
1028+
old_addr->four = old;
10301029
break;
10311030
}
10321031
case 8: {
10331032
u64 old;
10341033

1035-
ret = cmpxchg_user_key((u64 __user *)hva, &old, *old_addr, new, access_key);
1036-
*success = !ret && old == *old_addr;
1037-
*old_addr = old;
1034+
ret = cmpxchg_user_key((u64 __user *)hva, &old, old_addr->eight, new.eight, acc);
1035+
*success = !ret && old == old_addr->eight;
1036+
old_addr->eight = old;
10381037
break;
10391038
}
10401039
case 16: {
10411040
__uint128_t old;
10421041

1043-
ret = cmpxchg_user_key((__uint128_t __user *)hva, &old, *old_addr, new, access_key);
1044-
*success = !ret && old == *old_addr;
1045-
*old_addr = old;
1042+
ret = cmpxchg_user_key((__uint128_t __user *)hva, &old, old_addr->sixteen,
1043+
new.sixteen, acc);
1044+
*success = !ret && old == old_addr->sixteen;
1045+
old_addr->sixteen = old;
10461046
break;
10471047
}
10481048
default:

arch/s390/kvm/gaccess.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
206206
int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
207207
void *data, unsigned long len, enum gacc_mode mode);
208208

209-
int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, __uint128_t *old,
210-
__uint128_t new, u8 access_key, bool *success);
209+
int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, union kvm_s390_quad *old_addr,
210+
union kvm_s390_quad new, u8 access_key, bool *success);
211211

212212
/**
213213
* write_guest_with_key - copy data from kernel space to guest space

arch/s390/kvm/kvm-s390.c

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2900,9 +2900,9 @@ static int mem_op_validate_common(struct kvm_s390_mem_op *mop, u64 supported_fla
29002900
static int kvm_s390_vm_mem_op_abs(struct kvm *kvm, struct kvm_s390_mem_op *mop)
29012901
{
29022902
void __user *uaddr = (void __user *)mop->buf;
2903+
void *tmpbuf __free(kvfree) = NULL;
29032904
enum gacc_mode acc_mode;
2904-
void *tmpbuf = NULL;
2905-
int r, srcu_idx;
2905+
int r;
29062906

29072907
r = mem_op_validate_common(mop, KVM_S390_MEMOP_F_SKEY_PROTECTION |
29082908
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)
29152915
return -ENOMEM;
29162916
}
29172917

2918-
srcu_idx = srcu_read_lock(&kvm->srcu);
2918+
acc_mode = mop->op == KVM_S390_MEMOP_ABSOLUTE_READ ? GACC_FETCH : GACC_STORE;
29192919

2920-
if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr)) {
2921-
r = PGM_ADDRESSING;
2922-
goto out_unlock;
2923-
}
2920+
scoped_guard(srcu, &kvm->srcu) {
2921+
if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr))
2922+
return PGM_ADDRESSING;
29242923

2925-
acc_mode = mop->op == KVM_S390_MEMOP_ABSOLUTE_READ ? GACC_FETCH : GACC_STORE;
2926-
if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
2927-
r = check_gpa_range(kvm, mop->gaddr, mop->size, acc_mode, mop->key);
2928-
goto out_unlock;
2929-
}
2930-
if (acc_mode == GACC_FETCH) {
2924+
if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)
2925+
return check_gpa_range(kvm, mop->gaddr, mop->size, acc_mode, mop->key);
2926+
2927+
if (acc_mode == GACC_STORE && copy_from_user(tmpbuf, uaddr, mop->size))
2928+
return -EFAULT;
29312929
r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
2932-
mop->size, GACC_FETCH, mop->key);
2930+
mop->size, acc_mode, mop->key);
29332931
if (r)
2934-
goto out_unlock;
2935-
if (copy_to_user(uaddr, tmpbuf, mop->size))
2936-
r = -EFAULT;
2937-
} else {
2938-
if (copy_from_user(tmpbuf, uaddr, mop->size)) {
2939-
r = -EFAULT;
2940-
goto out_unlock;
2941-
}
2942-
r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
2943-
mop->size, GACC_STORE, mop->key);
2932+
return r;
2933+
if (acc_mode != GACC_STORE && copy_to_user(uaddr, tmpbuf, mop->size))
2934+
return -EFAULT;
29442935
}
29452936

2946-
out_unlock:
2947-
srcu_read_unlock(&kvm->srcu, srcu_idx);
2948-
2949-
vfree(tmpbuf);
2950-
return r;
2937+
return 0;
29512938
}
29522939

29532940
static int kvm_s390_vm_mem_op_cmpxchg(struct kvm *kvm, struct kvm_s390_mem_op *mop)
29542941
{
29552942
void __user *uaddr = (void __user *)mop->buf;
29562943
void __user *old_addr = (void __user *)mop->old_addr;
2957-
union {
2958-
__uint128_t quad;
2959-
char raw[sizeof(__uint128_t)];
2960-
} old = { .quad = 0}, new = { .quad = 0 };
2961-
unsigned int off_in_quad = sizeof(new) - mop->size;
2962-
int r, srcu_idx;
2963-
bool success;
2944+
union kvm_s390_quad old = { .sixteen = 0 };
2945+
union kvm_s390_quad new = { .sixteen = 0 };
2946+
bool success = false;
2947+
int r;
29642948

29652949
r = mem_op_validate_common(mop, KVM_S390_MEMOP_F_SKEY_PROTECTION);
29662950
if (r)
@@ -2972,25 +2956,21 @@ static int kvm_s390_vm_mem_op_cmpxchg(struct kvm *kvm, struct kvm_s390_mem_op *m
29722956
*/
29732957
if (mop->size > sizeof(new))
29742958
return -EINVAL;
2975-
if (copy_from_user(&new.raw[off_in_quad], uaddr, mop->size))
2959+
if (copy_from_user(&new, uaddr, mop->size))
29762960
return -EFAULT;
2977-
if (copy_from_user(&old.raw[off_in_quad], old_addr, mop->size))
2961+
if (copy_from_user(&old, old_addr, mop->size))
29782962
return -EFAULT;
29792963

2980-
srcu_idx = srcu_read_lock(&kvm->srcu);
2964+
scoped_guard(srcu, &kvm->srcu) {
2965+
if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr))
2966+
return PGM_ADDRESSING;
29812967

2982-
if (!kvm_is_gpa_in_memslot(kvm, mop->gaddr)) {
2983-
r = PGM_ADDRESSING;
2984-
goto out_unlock;
2985-
}
2986-
2987-
r = cmpxchg_guest_abs_with_key(kvm, mop->gaddr, mop->size, &old.quad,
2988-
new.quad, mop->key, &success);
2989-
if (!success && copy_to_user(old_addr, &old.raw[off_in_quad], mop->size))
2990-
r = -EFAULT;
2968+
r = cmpxchg_guest_abs_with_key(kvm, mop->gaddr, mop->size, &old, new,
2969+
mop->key, &success);
29912970

2992-
out_unlock:
2993-
srcu_read_unlock(&kvm->srcu, srcu_idx);
2971+
if (!success && copy_to_user(old_addr, &old, mop->size))
2972+
return -EFAULT;
2973+
}
29942974
return r;
29952975
}
29962976

arch/s390/kvm/kvm-s390.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@
2222

2323
#define KVM_S390_UCONTROL_MEMSLOT (KVM_USER_MEM_SLOTS + 0)
2424

25+
union kvm_s390_quad {
26+
__uint128_t sixteen;
27+
unsigned long eight;
28+
unsigned int four;
29+
unsigned short two;
30+
unsigned char one;
31+
};
32+
2533
static inline void kvm_s390_fpu_store(struct kvm_run *run)
2634
{
2735
fpu_stfpc(&run->s.regs.fpc);

0 commit comments

Comments
 (0)