On Wed, 2022-11-02 at 15:19 +0100, Heiko Carstens wrote: > Add cmpxchg_user_key() which allows to execute a compare and exchange > on a user space address. This allows also to specify a storage key > which makes sure that key-controlled protection is considered. > > This is based on a patch written by Janis Schoetterl-Glausch. > > Link: https://lore.kernel.org/all/20220930210751.225873-2-scgl@xxxxxxxxxxxxx > Cc: Janis Schoetterl-Glausch <scgl@xxxxxxxxxxxxx> > Signed-off-by: Heiko Carstens <hca@xxxxxxxxxxxxx> > --- > arch/s390/include/asm/uaccess.h | 183 ++++++++++++++++++++++++++++++++ > 1 file changed, 183 insertions(+) > > diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h > index f7038b800cc3..9bbdecb80e06 100644 > --- a/arch/s390/include/asm/uaccess.h > +++ b/arch/s390/include/asm/uaccess.h > @@ -390,4 +390,187 @@ do { \ > goto err_label; \ > } while (0) > > +void __cmpxchg_user_key_called_with_bad_pointer(void); > + > +static __always_inline int __cmpxchg_user_key(unsigned long address, void *uval, > + __uint128_t old, __uint128_t new, > + unsigned long key, int size) > +{ > + int rc = 0; > + > + switch (size) { > + case 1: { > + unsigned int prev, tmp, shift; > + > + shift = (3 ^ (address & 3)) << 3; > + address ^= address & 3; > + asm volatile( > + " spka 0(%[key])\n" > + " sacf 256\n" > + "0: l %[prev],%[address]\n" > + "1: nr %[prev],%[mask]\n" > + " lr %[tmp],%[prev]\n" > + " or %[prev],%[old]\n" > + " or %[tmp],%[new]\n" > + "2: cs %[prev],%[tmp],%[address]\n" > + "3: jnl 4f\n" > + " xr %[tmp],%[prev]\n" > + " nr %[tmp],%[mask]\n" Are you only entertaining cosmetic changes to cmpxchg.h? The loop condition being imprecise seems non-ideal. > + " jnz 1b\n" > + "4: sacf 768\n" > + " spka %[default_key]\n" > + EX_TABLE_UA_LOAD_REG(0b, 4b, %[rc], %[prev]) > + EX_TABLE_UA_LOAD_REG(1b, 4b, %[rc], %[prev]) > + EX_TABLE_UA_LOAD_REG(2b, 4b, %[rc], %[prev]) > + EX_TABLE_UA_LOAD_REG(3b, 4b, %[rc], %[prev]) > + : [rc] "+&d" (rc), > + [prev] "=&d" (prev), > + [tmp] "=&d" (tmp), > + [address] "+Q" (*(int *)address) > + : [old] "d" (((unsigned int)old & 0xff) << shift), > + [new] "d" (((unsigned int)new & 0xff) << shift), > + [mask] "d" (~(0xff << shift)), > + [key] "a" (key), Why did you get rid of the << 4 shift? That's inconsistent with the other uaccess functions that take an access key. > + [default_key] "J" (PAGE_DEFAULT_KEY) > + : "memory", "cc"); > + *(unsigned char *)uval = prev >> shift; > + return rc; > + } [...]