powerpc/uaccess: Implement unsafe_put_user() using 'asm goto'
authorChristophe Leroy <christophe.leroy@c-s.fr>
Fri, 17 Apr 2020 17:08:51 +0000 (17:08 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 30 Apr 2020 10:30:40 +0000 (20:30 +1000)
commit334710b1496af8a0960e70121f850e209c20958f
treeef74db3994f9e1699e1be0c5d1fd4e9f22554227
parentd02f6b7dab8228487268298ea1f21081c0b4b3eb
powerpc/uaccess: Implement unsafe_put_user() using 'asm goto'

unsafe_put_user() is designed to take benefit of 'asm goto'.

Instead of using the standard __put_user() approach and branch
based on the returned error, use 'asm goto' and make the
exception code branch directly to the error label. There is
no code anymore in the fixup section.

This change significantly simplifies functions using
unsafe_put_user()

Small exemple of the benefit with the following code:

struct test {
u32 item1;
u16 item2;
u8 item3;
u64 item4;
};

int set_test_to_user(struct test __user *test, u32 item1, u16 item2, u8 item3, u64 item4)
{
unsafe_put_user(item1, &test->item1, failed);
unsafe_put_user(item2, &test->item2, failed);
unsafe_put_user(item3, &test->item3, failed);
unsafe_put_user(item4, &test->item4, failed);
return 0;
failed:
return -EFAULT;
}

Before the patch:

00000be8 <set_test_to_user>:
 be8: 39 20 00 00  li      r9,0
 bec: 90 83 00 00  stw     r4,0(r3)
 bf0: 2f 89 00 00  cmpwi   cr7,r9,0
 bf4: 40 9e 00 38  bne     cr7,c2c <set_test_to_user+0x44>
 bf8: b0 a3 00 04  sth     r5,4(r3)
 bfc: 2f 89 00 00  cmpwi   cr7,r9,0
 c00: 40 9e 00 2c  bne     cr7,c2c <set_test_to_user+0x44>
 c04: 98 c3 00 06  stb     r6,6(r3)
 c08: 2f 89 00 00  cmpwi   cr7,r9,0
 c0c: 40 9e 00 20  bne     cr7,c2c <set_test_to_user+0x44>
 c10: 90 e3 00 08  stw     r7,8(r3)
 c14: 91 03 00 0c  stw     r8,12(r3)
 c18: 21 29 00 00  subfic  r9,r9,0
 c1c: 7d 29 49 10  subfe   r9,r9,r9
 c20: 38 60 ff f2  li      r3,-14
 c24: 7d 23 18 38  and     r3,r9,r3
 c28: 4e 80 00 20  blr
 c2c: 38 60 ff f2  li      r3,-14
 c30: 4e 80 00 20  blr

00000000 <.fixup>:
...
  b8: 39 20 ff f2  li      r9,-14
  bc: 48 00 00 00  b       bc <.fixup+0xbc>
bc: R_PPC_REL24 .text+0xbf0
  c0: 39 20 ff f2  li      r9,-14
  c4: 48 00 00 00  b       c4 <.fixup+0xc4>
c4: R_PPC_REL24 .text+0xbfc
  c8: 39 20 ff f2  li      r9,-14
  cc: 48 00 00 00  b       cc <.fixup+0xcc>
  d0: 39 20 ff f2  li      r9,-14
  d4: 48 00 00 00  b       d4 <.fixup+0xd4>
d4: R_PPC_REL24 .text+0xc18

00000000 <__ex_table>:
...
a0: R_PPC_REL32 .text+0xbec
a4: R_PPC_REL32 .fixup+0xb8
a8: R_PPC_REL32 .text+0xbf8
ac: R_PPC_REL32 .fixup+0xc0
b0: R_PPC_REL32 .text+0xc04
b4: R_PPC_REL32 .fixup+0xc8
b8: R_PPC_REL32 .text+0xc10
bc: R_PPC_REL32 .fixup+0xd0
c0: R_PPC_REL32 .text+0xc14
c4: R_PPC_REL32 .fixup+0xd0

After the patch:

00000be8 <set_test_to_user>:
 be8: 90 83 00 00  stw     r4,0(r3)
 bec: b0 a3 00 04  sth     r5,4(r3)
 bf0: 98 c3 00 06  stb     r6,6(r3)
 bf4: 90 e3 00 08  stw     r7,8(r3)
 bf8: 91 03 00 0c  stw     r8,12(r3)
 bfc: 38 60 00 00  li      r3,0
 c00: 4e 80 00 20  blr
 c04: 38 60 ff f2  li      r3,-14
 c08: 4e 80 00 20  blr

00000000 <__ex_table>:
...
a0: R_PPC_REL32 .text+0xbe8
a4: R_PPC_REL32 .text+0xc04
a8: R_PPC_REL32 .text+0xbec
ac: R_PPC_REL32 .text+0xc04
b0: R_PPC_REL32 .text+0xbf0
b4: R_PPC_REL32 .text+0xc04
b8: R_PPC_REL32 .text+0xbf4
bc: R_PPC_REL32 .text+0xc04
c0: R_PPC_REL32 .text+0xbf8
c4: R_PPC_REL32 .text+0xc04

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/23e680624680a9a5405f4b88740d2596d4b17c26.1587143308.git.christophe.leroy@c-s.fr
arch/powerpc/include/asm/uaccess.h