]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/copyinout.S
Copy needed include files from EDK2. This is a minimal set gleened
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / copyinout.S
1 /*-
2  * Copyright (c) 2015 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Andrew Turner under
6  * sponsorship from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30
31 #include <machine/asm.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/errno.h>
35
36 #include <machine/vmparam.h>
37
38 #include "assym.s"
39
40 /*
41  * Fault handler for the copy{in,out} functions below.
42  */
43 ENTRY(copyio_fault)
44         SET_FAULT_HANDLER(xzr, x1) /* Clear the handler */
45 copyio_fault_nopcb:
46         mov     x0, #EFAULT
47         ret
48 END(copyio_fault)
49
50 /*
51  * Copies from a kernel to user address
52  *
53  * int copyout(const void *kaddr, void *udaddr, size_t len)
54  */
55 ENTRY(copyout)
56         cbz     x2, 1f
57         adds    x3, x1, x2
58         b.cs    copyio_fault_nopcb
59         ldr     x4, =VM_MAXUSER_ADDRESS
60         cmp     x3, x4
61         b.hi    copyio_fault_nopcb
62
63         b       copycommon
64
65 1:      mov     x0, xzr         /* return 0 */
66         ret
67
68 END(copyout)
69
70 /*
71  * Copies from a user to kernel address
72  *
73  * int copyin(const void *uaddr, void *kdaddr, size_t len)
74  */
75 ENTRY(copyin)
76         cbz     x2, 1f
77         adds    x3, x0, x2
78         b.cs    copyio_fault_nopcb
79         ldr     x4, =VM_MAXUSER_ADDRESS
80         cmp     x3, x4
81         b.hi    copyio_fault_nopcb
82
83         b       copycommon
84
85 1:      mov     x0, xzr         /* return 0 */
86         ret
87
88 END(copyin)
89
90 /*
91  * Copies a string from a user to kernel address
92  *
93  * int copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
94  */
95 ENTRY(copyinstr)
96         mov     x5, xzr         /* count = 0 */
97         mov     w4, #1          /* If zero return faulure */
98         cbz     x2, 3f          /* If len == 0 then skip loop */
99
100         adr     x6, copyio_fault /* Get the handler address */
101         SET_FAULT_HANDLER(x6, x7) /* Set the handler */
102
103         ldr     x7, =VM_MAXUSER_ADDRESS
104 1:      cmp     x0, x7
105         b.cs    copyio_fault
106         ldrb    w4, [x0], #1    /* Load from uaddr */
107         strb    w4, [x1], #1    /* Store in kaddr */
108         add     x5, x5, #1      /* count++ */
109         cbz     w4, 2f          /* Break when NUL-terminated */
110         sub     x2, x2, #1      /* len-- */
111         cbnz    x2, 1b
112
113 2:      SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */
114
115 3:      cbz     x3, 4f          /* Check if done != NULL */
116         str     x5, [x3]        /* done = count */
117
118 4:      mov     w1, #ENAMETOOLONG /* Load ENAMETOOLONG to return if failed */
119         cmp     w4, #0          /* Check if we saved the NUL-terminator */
120         csel    w0, wzr, w1, eq /* If so return success, else failure */
121         ret
122 END(copyinstr)
123
124 /*
125  * Local helper
126  *
127  * x0 - src pointer
128  * x1 - dst pointer
129  * x2 - size
130  * lr - the return address, so jump here instead of calling
131  *
132  * This function is optimized to minimize concurrent memory accesses. In
133  * present form it is suited for cores with a single memory prefetching
134  * unit.
135  * ARM64TODO: 
136  *   Consider using separate functions for each ARM64 core. Adding memory
137  *   access interleaving might increase a total throughput on A57 or A72.
138  */
139         .text
140         .align  4
141         .local  copycommon
142         .type   copycommon,@function
143
144 copycommon:
145         adr     x6, copyio_fault /* Get the handler address */
146         SET_FAULT_HANDLER(x6, x7) /* Set the handler */
147
148
149         /* Check alignment */
150         orr     x3, x0, x1
151         ands    x3, x3, 0x07
152         b.eq    aligned
153
154         /* Unaligned is byte by byte copy */
155 byte_by_byte:
156         ldrb    w3, [x0], #0x01
157         strb    w3, [x1], #0x01
158         subs    x2, x2, #0x01
159         b.ne    byte_by_byte
160         b       ending
161
162 aligned:
163         cmp     x2, #0x10
164         b.lt    lead_out
165         cmp     x2, #0x40
166         b.lt    by_dwords_start
167
168         /* Block copy */
169         lsr     x15, x2, #0x06
170 by_blocks:
171         ldp     x3, x4, [x0], #0x10
172         ldp     x5, x6, [x0], #0x10
173         ldp     x7, x8, [x0], #0x10
174         ldp     x9, x10, [x0], #0x10
175         stp     x3, x4, [x1], #0x10
176         stp     x5, x6, [x1], #0x10
177         stp     x7, x8, [x1], #0x10
178         stp     x9, x10, [x1], #0x10
179
180         subs    x15, x15, #0x01
181         b.ne    by_blocks
182
183         and     x2, x2, #0x3f
184
185 by_dwords_start:
186         lsr     x15, x2, #0x04
187         cbz     x15, lead_out
188 by_dwords:
189         ldp     x3, x4, [x0], #0x10
190         stp     x3, x4, [x1], #0x10
191         subs    x15, x15, #0x01
192         b.ne    by_dwords
193
194         /* Less than 16 bytes to copy */
195 lead_out:
196         tbz     x2, #0x03, last_word
197         ldr     x3, [x0], #0x08
198         str     x3, [x1], #0x08
199
200 last_word:
201         tbz     x2, #0x02, last_hword
202         ldr     w3, [x0], #0x04
203         str     w3, [x1], #0x04
204
205 last_hword:
206         tbz     x2, #0x01, last_byte
207         ldrh    w3, [x0], #0x02
208         strh    w3, [x1], #0x02
209
210 last_byte:
211         tbz     x2, #0x00, ending
212         ldrb    w3, [x0]
213         strb    w3, [x1]
214
215 ending:
216         SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */
217
218         mov     x0, xzr         /* return 0 */
219         ret
220         .size   copycommon, . - copycommon