]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/linux/linux_support.S
zfs: merge openzfs/zfs@9cd71c860 (master)
[FreeBSD/FreeBSD.git] / sys / arm64 / linux / linux_support.S
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (C) 2018 Turing Robotic Industries Inc.
5  * Copyright (C) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #include <machine/asm.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <machine/param.h>
35 #include <machine/vmparam.h>
36
37 #include <sys/errno.h>
38
39 #include "assym.inc"
40
41 .macro check_user_access user_arg, limit, bad_addr_func
42         ldr     x7, =(\limit)
43         cmp     x\user_arg, x7
44         b.cs    \bad_addr_func
45 .endm
46
47 futex_fault:
48         SET_FAULT_HANDLER(xzr, x1)
49         EXIT_USER_ACCESS_CHECK(w0, x1)
50 futex_fault_nopcb:
51         mov     x0, #EFAULT
52         ret
53
54 #define LINUX_FUTEX_MAX_LOOPS   128
55
56 /*
57  * int oparg, uint32_t *uaddr, int *oldval
58  *
59  * Return 0 on success, errno on failure,
60  * EAGAIN is returned if LL/SC operation fails.
61  *
62  * XXX. VM_MAXUSER_ADDRESS is not applicable here, should be replaced
63  * by something like LINUX_SHAREDPAGE.
64  */
65
66 /* (int *)uaddr2 = oparg */
67 ENTRY(futex_xchgl)
68         check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
69         adr     x9, futex_fault         /* Load the fault handler */
70         SET_FAULT_HANDLER(x9, x4)       /* And set it */
71         ENTER_USER_ACCESS(w9, x4)
72         mov     w5, #LINUX_FUTEX_MAX_LOOPS
73         prfm    pstl1strm, [x1]
74         mov     w6, w0                  /* Save oparg */
75 1:      ldxr    w4, [x1]                /* Load oldval from uaddr */
76         stlxr   w0, w6, [x1]            /* Store oparg to uaddr */
77         cbz     w0, 3f                  /* Exit on success */
78         sub     w5, w5, w0              /* Dec loop counter, w0 is 1 */
79         cbnz    w5, 1b                  /* Loop */
80         mov     x0, #EAGAIN             /* Store of newval failed */
81 3:      dmb     ish
82         EXIT_USER_ACCESS(w9)
83         SET_FAULT_HANDLER(xzr, x9)      /* Reset the fault handler */
84         str w4, [x2]                    /* Store oldval */
85         ret
86 END(futex_xchgl)
87
88 /* (int *)uaddr2 += oparg */
89 ENTRY(futex_addl)
90         check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
91         adr     x9, futex_fault
92         SET_FAULT_HANDLER(x9, x4)
93         ENTER_USER_ACCESS(w9, x4)
94         mov     w5, #LINUX_FUTEX_MAX_LOOPS
95         prfm    pstl1strm, [x1]
96         mov     w6, w0
97 1:      ldxr    w4, [x1]
98         add     w3, w4, w6              /* oldval + oparg */
99         stlxr   w0, w3, [x1]
100         cbz     w0, 3f
101         sub     w5, w5, w0
102         cbnz    w5, 1b
103         mov     x0, #EAGAIN
104 3:      dmb     ish
105         EXIT_USER_ACCESS(w9)
106         SET_FAULT_HANDLER(xzr, x9)
107         str w4, [x2]
108         ret
109 END(futex_addl)
110
111 /* (int *)uaddr2 |= oparg */
112 ENTRY(futex_orl)
113         check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
114         adr     x9, futex_fault
115         SET_FAULT_HANDLER(x9, x4)
116         ENTER_USER_ACCESS(w9, x4)
117         mov     w5, #LINUX_FUTEX_MAX_LOOPS
118         prfm    pstl1strm, [x1]
119         mov     w6, w0
120 1:      ldxr    w4, [x1]
121         orr     w3, w4, w6              /* oldavl |= oparg */
122         stlxr   w0, w3, [x1]
123         cbz     w0, 3f
124         sub     w5, w5, w0
125         cbnz    w5, 1b
126         mov     x0, #EAGAIN
127 3:      dmb     ish
128         EXIT_USER_ACCESS(w9)
129         SET_FAULT_HANDLER(xzr, x9)
130         str w4, [x2]
131         ret
132 END(futex_orl)
133
134 /* (int *)uaddr2 &= oparg */
135 ENTRY(futex_andl)
136         check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
137         adr     x9, futex_fault
138         SET_FAULT_HANDLER(x9, x4)
139         ENTER_USER_ACCESS(w9, x4)
140         mov     w5, #LINUX_FUTEX_MAX_LOOPS
141         prfm    pstl1strm, [x1]
142         mov     w6, w0
143 1:      ldxr    w4, [x1]
144         and     w3, w4, w6              /* oldval &= oparg */
145         stlxr   w0, w3, [x1]
146         cbz     w0, 3f
147         sub     w5, w5, w0
148         cbnz    w5, 1b
149         mov     x0, #EAGAIN
150 3:      dmb     ish
151         EXIT_USER_ACCESS(w9)
152         SET_FAULT_HANDLER(xzr, x9)
153         str w4, [x2]
154         ret
155 END(futex_andl)
156
157 /* (int *)uaddr2 ^= oparg */
158 ENTRY(futex_xorl)
159         check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
160         adr     x9, futex_fault
161         SET_FAULT_HANDLER(x9, x4)
162         ENTER_USER_ACCESS(w9, x4)
163         mov     w5, #LINUX_FUTEX_MAX_LOOPS
164         prfm    pstl1strm, [x1]
165         mov     w6, w0
166 1:      ldxr    w4, [x1]
167         eor     w3, w4, w6              /* oldval ^= oparg */
168         stlxr   w0, w3, [x1]
169         cbz     w0, 3f
170         sub     w5, w5, w0
171         cbnz    w5, 1b
172         mov     x0, #EAGAIN
173 3:      dmb     ish
174         EXIT_USER_ACCESS(w9)
175         SET_FAULT_HANDLER(xzr, x9)
176         str w4, [x2]
177         ret
178 END(futex_xorl)