Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/i386/linux/linux_copyout.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2018 The FreeBSD Foundation
5
*
6
* This software was developed by Konstantin Belousov <[email protected]>
7
* under sponsorship from the FreeBSD Foundation.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*/
30
31
#include <sys/param.h>
32
#include <sys/imgact.h>
33
#include <sys/lock.h>
34
#include <sys/sx.h>
35
36
#include <vm/vm.h>
37
#include <vm/vm_param.h>
38
#include <vm/vm_extern.h>
39
#include <vm/pmap.h>
40
41
#include <machine/atomic.h>
42
#include <machine/md_var.h>
43
44
#include <i386/linux/linux.h>
45
#include <compat/linux/linux_emul.h>
46
#include <compat/linux/linux_futex.h>
47
48
struct futex_st0 {
49
int oparg;
50
int *oldval;
51
};
52
53
static void
54
futex_xchgl_slow0(vm_offset_t kva, void *arg)
55
{
56
struct futex_st0 *st;
57
58
st = arg;
59
*st->oldval = atomic_swap_int((int *)kva, st->oparg);
60
}
61
62
int
63
futex_xchgl(int oparg, uint32_t *uaddr, int *oldval)
64
{
65
struct futex_st0 st;
66
67
st.oparg = oparg;
68
st.oldval = oldval;
69
if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
70
futex_xchgl_slow0, &st) != 0)
71
return (EFAULT);
72
return (0);
73
}
74
75
static void
76
futex_addl_slow0(vm_offset_t kva, void *arg)
77
{
78
struct futex_st0 *st;
79
80
st = arg;
81
*st->oldval = atomic_fetchadd_int((int *)kva, st->oparg);
82
}
83
84
int
85
futex_addl(int oparg, uint32_t *uaddr, int *oldval)
86
{
87
struct futex_st0 st;
88
89
st.oparg = oparg;
90
st.oldval = oldval;
91
if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
92
futex_addl_slow0, &st) != 0)
93
return (EFAULT);
94
return (0);
95
}
96
97
static void
98
futex_orl_slow0(vm_offset_t kva, void *arg)
99
{
100
struct futex_st0 *st;
101
int old;
102
103
st = arg;
104
old = *(int *)kva;
105
while (!atomic_fcmpset_int((int *)kva, &old, old | st->oparg))
106
;
107
*st->oldval = old;
108
}
109
110
int
111
futex_orl(int oparg, uint32_t *uaddr, int *oldval)
112
{
113
struct futex_st0 st;
114
115
st.oparg = oparg;
116
st.oldval = oldval;
117
if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
118
futex_orl_slow0, &st) != 0)
119
return (EFAULT);
120
return (0);
121
}
122
123
static void
124
futex_andl_slow0(vm_offset_t kva, void *arg)
125
{
126
struct futex_st0 *st;
127
int old;
128
129
st = arg;
130
old = *(int *)kva;
131
while (!atomic_fcmpset_int((int *)kva, &old, old & st->oparg))
132
;
133
*st->oldval = old;
134
}
135
136
int
137
futex_andl(int oparg, uint32_t *uaddr, int *oldval)
138
{
139
struct futex_st0 st;
140
141
st.oparg = oparg;
142
st.oldval = oldval;
143
if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
144
futex_andl_slow0, &st) != 0)
145
return (EFAULT);
146
return (0);
147
}
148
149
static void
150
futex_xorl_slow0(vm_offset_t kva, void *arg)
151
{
152
struct futex_st0 *st;
153
int old;
154
155
st = arg;
156
old = *(int *)kva;
157
while (!atomic_fcmpset_int((int *)kva, &old, old ^ st->oparg))
158
;
159
*st->oldval = old;
160
}
161
162
int
163
futex_xorl(int oparg, uint32_t *uaddr, int *oldval)
164
{
165
struct futex_st0 st;
166
167
st.oparg = oparg;
168
st.oldval = oldval;
169
if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
170
futex_xorl_slow0, &st) != 0)
171
return (EFAULT);
172
return (0);
173
}
174
175