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 from user space to 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 | |
23 | .macro ldrb1 reg, ptr, val |
24 | user_ldst 9998f, ldtrb, \reg, \ptr, \val |
25 | .endm |
26 | |
27 | .macro strb1 reg, ptr, val |
28 | strb \reg, [\ptr], \val |
29 | .endm |
30 | |
31 | .macro ldrh1 reg, ptr, val |
32 | user_ldst 9997f, ldtrh, \reg, \ptr, \val |
33 | .endm |
34 | |
35 | .macro strh1 reg, ptr, val |
36 | strh \reg, [\ptr], \val |
37 | .endm |
38 | |
39 | .macro ldr1 reg, ptr, val |
40 | user_ldst 9997f, ldtr, \reg, \ptr, \val |
41 | .endm |
42 | |
43 | .macro str1 reg, ptr, val |
44 | str \reg, [\ptr], \val |
45 | .endm |
46 | |
47 | .macro ldp1 reg1, reg2, ptr, val |
48 | user_ldp 9997f, \reg1, \reg2, \ptr, \val |
49 | .endm |
50 | |
51 | .macro stp1 reg1, reg2, ptr, val |
52 | stp \reg1, \reg2, [\ptr], \val |
53 | .endm |
54 | |
55 | end .req x5 |
56 | srcin .req x15 |
57 | SYM_FUNC_START(__arch_copy_from_user) |
58 | add end, x0, x2 |
59 | mov srcin, x1 |
60 | #include "copy_template.S" |
61 | mov x0, #0 // Nothing to copy |
62 | ret |
63 | |
64 | // Exception fixups |
65 | 9997: cmp dst, dstin |
66 | b.ne 9998f |
67 | // Before being absolutely sure we couldn't copy anything, try harder |
68 | USER(9998f, ldtrb tmp1w, [srcin]) |
69 | strb tmp1w, [dst], #1 |
70 | 9998: sub x0, end, dst // bytes not copied |
71 | ret |
72 | SYM_FUNC_END(__arch_copy_from_user) |
73 | EXPORT_SYMBOL(__arch_copy_from_user) |
74 | |