1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2012 ARM Ltd. |
4 | */ |
5 | |
6 | #include <linux/linkage.h> |
7 | |
8 | #include <asm/asm-uaccess.h> |
9 | #include <asm/assembler.h> |
10 | #include <asm/cache.h> |
11 | |
12 | /* |
13 | * Copy to user space from a kernel buffer (alignment handled by the hardware) |
14 | * |
15 | * Parameters: |
16 | * x0 - to |
17 | * x1 - from |
18 | * x2 - n |
19 | * Returns: |
20 | * x0 - bytes not copied |
21 | */ |
22 | .macro ldrb1 reg, ptr, val |
23 | ldrb \reg, [\ptr], \val |
24 | .endm |
25 | |
26 | .macro strb1 reg, ptr, val |
27 | user_ldst 9998f, sttrb, \reg, \ptr, \val |
28 | .endm |
29 | |
30 | .macro ldrh1 reg, ptr, val |
31 | ldrh \reg, [\ptr], \val |
32 | .endm |
33 | |
34 | .macro strh1 reg, ptr, val |
35 | user_ldst 9997f, sttrh, \reg, \ptr, \val |
36 | .endm |
37 | |
38 | .macro ldr1 reg, ptr, val |
39 | ldr \reg, [\ptr], \val |
40 | .endm |
41 | |
42 | .macro str1 reg, ptr, val |
43 | user_ldst 9997f, sttr, \reg, \ptr, \val |
44 | .endm |
45 | |
46 | .macro ldp1 reg1, reg2, ptr, val |
47 | ldp \reg1, \reg2, [\ptr], \val |
48 | .endm |
49 | |
50 | .macro stp1 reg1, reg2, ptr, val |
51 | user_stp 9997f, \reg1, \reg2, \ptr, \val |
52 | .endm |
53 | |
54 | end .req x5 |
55 | srcin .req x15 |
56 | SYM_FUNC_START(__arch_copy_to_user) |
57 | add end, x0, x2 |
58 | mov srcin, x1 |
59 | #include "copy_template.S" |
60 | mov x0, #0 |
61 | ret |
62 | |
63 | // Exception fixups |
64 | 9997: cmp dst, dstin |
65 | b.ne 9998f |
66 | // Before being absolutely sure we couldn't copy anything, try harder |
67 | ldrb tmp1w, [srcin] |
68 | USER(9998f, sttrb tmp1w, [dst]) |
69 | add dst, dst, #1 |
70 | 9998: sub x0, end, dst // bytes not copied |
71 | ret |
72 | SYM_FUNC_END(__arch_copy_to_user) |
73 | EXPORT_SYMBOL(__arch_copy_to_user) |
74 | |