1 /*-
2 * Copyright (c) 2000 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/lock.h>
34 #include <sys/mman.h>
35 #include <sys/mount.h>
36 #include <sys/proc.h>
37 #include <sys/sysproto.h>
38 #include <sys/unistd.h>
39
40 #include <vm/vm.h>
41 #include <vm/pmap.h>
42 #include <vm/vm_map.h>
43
44 #include <sys/user.h>
45
46 #include <alpha/linux/linux.h>
47 #include <alpha/linux/linux_proto.h>
48 #include <compat/linux/linux_signal.h>
49 #include <compat/linux/linux_util.h>
50
51 struct linux_select_argv {
52 int nfds;
53 fd_set *readfds;
54 fd_set *writefds;
55 fd_set *exceptfds;
56 struct timeval *timeout;
57 };
58
59 int
60 linux_execve(struct proc *p, struct linux_execve_args *args)
61 {
62 struct execve_args bsd;
63 caddr_t sg;
64
65 sg = stackgap_init();
66 CHECKALTEXIST(p, &sg, args->path);
67
68 #ifdef DEBUG
69 if (ldebug(execve))
70 printf(ARGS(execve, "%s"), args->path);
71 #endif
72 bsd.fname = args->path;
73 bsd.argv = args->argp;
74 bsd.envv = args->envp;
75 return (execve(p, &bsd));
76 }
77
78 int
79 linux_fork(struct proc *p, struct linux_fork_args *args)
80 {
81 int error;
82
83 #ifdef DEBUG
84 if (ldebug(fork))
85 printf(ARGS(fork, ""));
86 #endif
87 if ((error = fork(p, (struct fork_args *)args)) != 0)
88 return (error);
89
90 if (p->p_retval[1] == 1)
91 p->p_retval[0] = 0;
92
93 return (0);
94 }
95
96 int
97 linux_vfork(struct proc *p, struct linux_vfork_args *args)
98 {
99 int error;
100
101 #ifdef DEBUG
102 if (ldebug(vfork))
103 printf(ARGS(vfork, ""));
104 #endif
105 if ((error = vfork(p, (struct vfork_args *)args)) != 0)
106 return (error);
107 /* Are we the child? */
108 if (p->p_retval[1] == 1)
109 p->p_retval[0] = 0;
110 return (0);
111 }
112
113 #define CLONE_VM 0x100
114 #define CLONE_FS 0x200
115 #define CLONE_FILES 0x400
116 #define CLONE_SIGHAND 0x800
117 #define CLONE_PID 0x1000
118
119 int
120 linux_clone(struct proc *p, struct linux_clone_args *args)
121 {
122 int error, ff = RFPROC;
123 struct proc *p2;
124 int exit_signal;
125 vm_offset_t start;
126 struct rfork_args rf_args;
127
128 #ifdef DEBUG
129 if (ldebug(clone)) {
130 printf(ARGS(clone, "flags %x, stack %x"),
131 (unsigned int)args->flags, (unsigned int)args->stack);
132 if (args->flags & CLONE_PID)
133 printf(LMSG("CLONE_PID not yet supported"));
134 }
135 #endif
136
137 if (!args->stack)
138 return (EINVAL);
139
140 exit_signal = args->flags & 0x000000ff;
141 if (exit_signal >= LINUX_NSIG)
142 return (EINVAL);
143
144 /* if (exit_signal <= LINUX_SIGTBLSZ)
145 exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)];
146 */
147 /* RFTHREAD probably not necessary here, but it shouldn't hurt */
148 ff |= RFTHREAD;
149
150 if (args->flags & CLONE_VM)
151 ff |= RFMEM;
152 if (args->flags & CLONE_SIGHAND)
153 ff |= RFSIGSHARE;
154 if (!(args->flags & CLONE_FILES))
155 ff |= RFFDG;
156
157 error = 0;
158 start = 0;
159
160 rf_args.flags = ff;
161 if ((error = rfork(p, &rf_args)) != 0)
162 return (error);
163
164 p2 = pfind(p->p_retval[0]);
165 if (p2 == 0)
166 return (ESRCH);
167
168 p2->p_sigparent = exit_signal;
169 p2->p_addr->u_pcb.pcb_hw.apcb_usp = (unsigned long)args->stack;
170
171 #ifdef DEBUG
172 if (ldebug(clone))
173 printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
174 (long)p2->p_pid, args->stack, exit_signal);
175 #endif
176
177 return (0);
178 }
179
180 #define STACK_SIZE (2 * 1024 * 1024)
181 #define GUARD_SIZE (4 * PAGE_SIZE)
182
183 int
184 linux_mmap(struct proc *p, struct linux_mmap_args *linux_args)
185 {
186 struct mmap_args /* {
187 caddr_t addr;
188 size_t len;
189 int prot;
190 int flags;
191 int fd;
192 long pad;
193 off_t pos;
194 } */ bsd_args;
195 int error;
196
197 #ifdef DEBUG
198 if (ldebug(mmap))
199 printf(ARGS(mmap, "%p, 0x%lx, 0x%x, 0x%x, 0x%x, 0x%lx"),
200 (void *)linux_args->addr, linux_args->len,
201 linux_args->prot, linux_args->flags, linux_args->fd,
202 linux_args->pos);
203 #endif
204 bsd_args.prot = linux_args->prot | PROT_READ; /* always required */
205
206 bsd_args.flags = 0;
207 if (linux_args->flags & LINUX_MAP_SHARED)
208 bsd_args.flags |= MAP_SHARED;
209 if (linux_args->flags & LINUX_MAP_PRIVATE)
210 bsd_args.flags |= MAP_PRIVATE;
211 if (linux_args->flags & LINUX_MAP_FIXED){
212 bsd_args.flags |= MAP_FIXED;
213 bsd_args.pos = trunc_page(linux_args->pos);
214 } else {
215 bsd_args.pos = linux_args->pos;
216 }
217 if (linux_args->flags & LINUX_MAP_ANON)
218 bsd_args.flags |= MAP_ANON;
219 if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
220 bsd_args.flags |= MAP_STACK;
221
222 /* The linux MAP_GROWSDOWN option does not limit auto
223 * growth of the region. Linux mmap with this option
224 * takes as addr the inital BOS, and as len, the initial
225 * region size. It can then grow down from addr without
226 * limit. However, linux threads has an implicit internal
227 * limit to stack size of STACK_SIZE. Its just not
228 * enforced explicitly in linux. But, here we impose
229 * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
230 * region, since we can do this with our mmap.
231 *
232 * Our mmap with MAP_STACK takes addr as the maximum
233 * downsize limit on BOS, and as len the max size of
234 * the region. It them maps the top SGROWSIZ bytes,
235 * and autgrows the region down, up to the limit
236 * in addr.
237 *
238 * If we don't use the MAP_STACK option, the effect
239 * of this code is to allocate a stack region of a
240 * fixed size of (STACK_SIZE - GUARD_SIZE).
241 */
242
243 /* This gives us TOS */
244 bsd_args.addr = (caddr_t)(linux_args->addr + linux_args->len);
245
246 /* This gives us our maximum stack size */
247 if (linux_args->len > STACK_SIZE - GUARD_SIZE)
248 bsd_args.len = linux_args->len;
249 else
250 bsd_args.len = STACK_SIZE - GUARD_SIZE;
251
252 /* This gives us a new BOS. If we're using VM_STACK, then
253 * mmap will just map the top SGROWSIZ bytes, and let
254 * the stack grow down to the limit at BOS. If we're
255 * not using VM_STACK we map the full stack, since we
256 * don't have a way to autogrow it.
257 */
258 bsd_args.addr -= bsd_args.len;
259 bsd_args.addr = (caddr_t)round_page(bsd_args.addr); /* XXXX */
260 } else {
261 bsd_args.addr = (caddr_t)linux_args->addr;
262 bsd_args.len = linux_args->len;
263 }
264
265 bsd_args.fd = linux_args->fd;
266 if(linux_args->fd == 0)
267 bsd_args.fd = -1;
268
269 bsd_args.pad = 0;
270 #ifdef DEBUG
271 if (ldebug(mmap))
272 printf(ARGS(mmap, "%p, 0x%lx, 0x%x, 0x%x, 0x%x, 0x%lx)",
273 (void *)bsd_args.addr,
274 bsd_args.len,
275 bsd_args.prot,
276 bsd_args.flags,
277 bsd_args.fd,
278 bsd_args.pos);
279 #endif
280 if (bsd_args.addr == 0)
281 bsd_args.addr = (caddr_t)0x40000000UL;
282 error = mmap(p, &bsd_args);
283 #ifdef DEBUG
284 if (ldebug(mmap))
285 printf(LMSG("mmap returns %d, 0x%lx", error, p->p_retval[0]);
286 #endif
287 return (error);
288 }
289
290 int
291 linux_rt_sigsuspend(p, uap)
292 struct proc *p;
293 struct linux_rt_sigsuspend_args *uap;
294 {
295 int error;
296 l_sigset_t lmask;
297 sigset_t *bmask;
298 struct sigsuspend_args bsd;
299 caddr_t sg;
300
301 sg = stackgap_init();
302
303 #ifdef DEBUG
304 if (ldebug(rt_sigsuspend))
305 printf(ARGS(rt_sigsuspend, "%p, %d"),
306 (void *)uap->newset, uap->sigsetsize);
307 #endif
308 if (uap->sigsetsize != sizeof(l_sigset_t))
309 return (EINVAL);
310
311 error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
312 if (error)
313 return (error);
314
315 bmask = stackgap_alloc(&sg, sizeof(sigset_t));
316 linux_to_bsd_sigset(&lmask, bmask);
317 bsd.sigmask = bmask;
318 return (sigsuspend(p, &bsd));
319 }
320
321 int
322 linux_mprotect(p, uap)
323 struct proc *p;
324 struct linux_mprotect_args *uap;
325 {
326
327 #ifdef DEBUG
328 if (ldebug(mprotect))
329 printf(ARGS(mprotect, "%p, 0x%lx, 0x%x)",
330 (void *)uap->addr, uap->len, uap->prot);
331 #endif
332 return (mprotect(p, (void *)uap));
333 }
334
335 int
336 linux_munmap(p, uap)
337 struct proc *p;
338 struct linux_munmap_args *uap;
339 {
340
341 #ifdef DEBUG
342 if (ldebug(munmap))
343 printf(ARGS(munmap, "%p, 0x%lx",
344 (void *)uap->addr, uap->len);
345 #endif
346 return (munmap(p, (void *)uap));
347 }
348
349 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
350 RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
351 RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NOFILE, -1,
352 RLIMIT_NPROC, RLIMIT_MEMLOCK
353 };
354
355 int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp));
356
357 int
358 linux_setrlimit(p, uap)
359 struct proc *p;
360 struct linux_setrlimit_args *uap;
361 {
362 struct rlimit rlim;
363 u_int which;
364 int error;
365
366 #ifdef DEBUG
367 if (ldebug(setrlimit))
368 printf(ARGS(setrlimit, "%d, %p"),
369 uap->resource, (void *)uap->rlim);
370 #endif
371 if (uap->resource >= LINUX_RLIM_NLIMITS)
372 return EINVAL;
373
374 which = linux_to_bsd_resource[uap->resource];
375
376 if (which == -1)
377 return EINVAL;
378
379 if ((error =
380 copyin((caddr_t)uap->rlim, (caddr_t)&rlim, sizeof (struct rlimit))))
381 return (error);
382 return dosetrlimit(p, which, &rlim);
383 }
384
385 int
386 linux_getrlimit(p, uap)
387 struct proc *p;
388 struct linux_getrlimit_args *uap;
389 {
390 u_int which;
391
392 #ifdef DEBUG
393 if (ldebug(getrlimit))
394 printf(ARGS(getrlimit, "%d, %p"),
395 uap->resource, (void *)uap->rlim);
396 #endif
397 if (uap->resource >= LINUX_RLIM_NLIMITS)
398 return EINVAL;
399
400 which = linux_to_bsd_resource[uap->resource];
401
402 if (which == -1)
403 return EINVAL;
404
405 return (copyout((caddr_t)&p->p_rlimit[which],
406 (caddr_t)uap->rlim, sizeof (struct rlimit)));
407 }
Cache object: 3373018e93be2b7889ecfbf3e16ca754
|