Skip to content

Commit fe59e03

Browse files
kristina-martsenkoctmarinas
authored andcommitted
arm64: lib: Use MOPS for usercopy routines
Similarly to what was done with the memcpy() routines, make copy_to_user(), copy_from_user() and clear_user() also use the Armv8.8 FEAT_MOPS instructions. Both MOPS implementation options (A and B) are supported, including asymmetric systems. The exception fixup code fixes up the registers according to the option used. In case of a fault the routines return precisely how much was not copied (as required by the comment in include/linux/uaccess.h), as unprivileged versions of CPY/SET are guaranteed not to have written past the addresses reported in the GPRs. The MOPS instructions could possibly be inlined into callers (and patched to branch to the generic implementation if not detected; similarly to what x86 does), but as a first step this patch just uses them in the out-of-line routines. Signed-off-by: Kristina Martšenko <kristina.martsenko@arm.com> Acked-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/20250228170006.390100-4-kristina.martsenko@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 04a9f77 commit fe59e03

File tree

5 files changed

+55
-4
lines changed

5 files changed

+55
-4
lines changed

arch/arm64/include/asm/asm-uaccess.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ alternative_else_nop_endif
6161
9999: x; \
6262
_asm_extable_uaccess 9999b, l
6363

64+
#define USER_CPY(l, uaccess_is_write, x...) \
65+
9999: x; \
66+
_asm_extable_uaccess_cpy 9999b, l, uaccess_is_write
67+
6468
/*
6569
* Generate the assembly for LDTR/STTR with exception table entries.
6670
* This is complicated as there is no post-increment or pair versions of the

arch/arm64/lib/clear_user.S

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,27 @@
1717
* Alignment fixed up by hardware.
1818
*/
1919

20-
.p2align 4
21-
// Alignment is for the loop, but since the prologue (including BTI)
22-
// is also 16 bytes we can keep any padding outside the function
2320
SYM_FUNC_START(__arch_clear_user)
2421
add x2, x0, x1
22+
23+
#ifdef CONFIG_AS_HAS_MOPS
24+
.arch_extension mops
25+
alternative_if_not ARM64_HAS_MOPS
26+
b .Lno_mops
27+
alternative_else_nop_endif
28+
29+
USER(9f, setpt [x0]!, x1!, xzr)
30+
USER(6f, setmt [x0]!, x1!, xzr)
31+
USER(6f, setet [x0]!, x1!, xzr)
32+
mov x0, #0
33+
ret
34+
.Lno_mops:
35+
#endif
36+
2537
subs x1, x1, #8
2638
b.mi 2f
27-
1:
39+
40+
1: .p2align 4
2841
USER(9f, sttr xzr, [x0])
2942
add x0, x0, #8
3043
subs x1, x1, #8
@@ -47,6 +60,10 @@ USER(7f, sttrb wzr, [x2, #-1])
4760
ret
4861

4962
// Exception fixups
63+
6: b.cs 9f
64+
// Registers are in Option A format
65+
add x0, x0, x1
66+
b 9f
5067
7: sub x0, x2, #5 // Adjust for faulting on the final byte...
5168
8: add x0, x0, #4 // ...or the second word of the 4-7 byte case
5269
9: sub x0, x2, x0

arch/arm64/lib/copy_from_user.S

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@
5252
stp \reg1, \reg2, [\ptr], \val
5353
.endm
5454

55+
.macro cpy1 dst, src, count
56+
.arch_extension mops
57+
USER_CPY(9997f, 0, cpyfprt [\dst]!, [\src]!, \count!)
58+
USER_CPY(9996f, 0, cpyfmrt [\dst]!, [\src]!, \count!)
59+
USER_CPY(9996f, 0, cpyfert [\dst]!, [\src]!, \count!)
60+
.endm
61+
5562
end .req x5
5663
srcin .req x15
5764
SYM_FUNC_START(__arch_copy_from_user)
@@ -62,6 +69,9 @@ SYM_FUNC_START(__arch_copy_from_user)
6269
ret
6370

6471
// Exception fixups
72+
9996: b.cs 9997f
73+
// Registers are in Option A format
74+
add dst, dst, count
6575
9997: cmp dst, dstin
6676
b.ne 9998f
6777
// Before being absolutely sure we couldn't copy anything, try harder

arch/arm64/lib/copy_template.S

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ D_l .req x13
4040
D_h .req x14
4141

4242
mov dst, dstin
43+
44+
#ifdef CONFIG_AS_HAS_MOPS
45+
alternative_if_not ARM64_HAS_MOPS
46+
b .Lno_mops
47+
alternative_else_nop_endif
48+
cpy1 dst, src, count
49+
b .Lexitfunc
50+
.Lno_mops:
51+
#endif
52+
4353
cmp count, #16
4454
/*When memory length is less than 16, the accessed are not aligned.*/
4555
b.lo .Ltiny15

arch/arm64/lib/copy_to_user.S

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@
5151
user_stp 9997f, \reg1, \reg2, \ptr, \val
5252
.endm
5353

54+
.macro cpy1 dst, src, count
55+
.arch_extension mops
56+
USER_CPY(9997f, 1, cpyfpwt [\dst]!, [\src]!, \count!)
57+
USER_CPY(9996f, 1, cpyfmwt [\dst]!, [\src]!, \count!)
58+
USER_CPY(9996f, 1, cpyfewt [\dst]!, [\src]!, \count!)
59+
.endm
60+
5461
end .req x5
5562
srcin .req x15
5663
SYM_FUNC_START(__arch_copy_to_user)
@@ -61,6 +68,9 @@ SYM_FUNC_START(__arch_copy_to_user)
6168
ret
6269

6370
// Exception fixups
71+
9996: b.cs 9997f
72+
// Registers are in Option A format
73+
add dst, dst, count
6474
9997: cmp dst, dstin
6575
b.ne 9998f
6676
// Before being absolutely sure we couldn't copy anything, try harder

0 commit comments

Comments
 (0)