kernel - Fix proc_reparent() race/assertion panic
[dragonfly.git] / sys / emulation / linux / i386 / linux_machdep.c
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: src/sys/i386/linux/linux_machdep.c,v 1.6.2.4 2001/11/05 19:08:23 marcel Exp $
29  * $DragonFly: src/sys/emulation/linux/i386/linux_machdep.c,v 1.23 2007/07/30 17:41:23 pavalos Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/imgact.h>
35 #include <sys/kern_syscall.h>
36 #include <sys/lock.h>
37 #include <sys/mman.h>
38 #include <sys/nlookup.h>
39 #include <sys/proc.h>
40 #include <sys/priv.h>
41 #include <sys/resource.h>
42 #include <sys/resourcevar.h>
43 #include <sys/ptrace.h>
44 #include <sys/sysproto.h>
45 #include <sys/thread2.h>
46 #include <sys/unistd.h>
47 #include <sys/wait.h>
48
49 #include <machine/frame.h>
50 #include <machine/psl.h>
51 #include <machine/segments.h>
52 #include <machine/sysarch.h>
53
54 #include <vm/vm.h>
55 #include <vm/pmap.h>
56 #include <vm/vm_map.h>
57
58 #include <sys/mplock2.h>
59
60 #include "linux.h"
61 #include "linux_proto.h"
62 #include "../linux_ipc.h"
63 #include "../linux_signal.h"
64 #include "../linux_util.h"
65 #include "../linux_emuldata.h"
66
67 struct l_descriptor {
68         l_uint          entry_number;
69         l_ulong         base_addr;
70         l_uint          limit;
71         l_uint          seg_32bit:1;
72         l_uint          contents:2;
73         l_uint          read_exec_only:1;
74         l_uint          limit_in_pages:1;
75         l_uint          seg_not_present:1;
76         l_uint          useable:1;
77 };
78
79 struct l_old_select_argv {
80         l_int           nfds;
81         l_fd_set        *readfds;
82         l_fd_set        *writefds;
83         l_fd_set        *exceptfds;
84         struct l_timeval        *timeout;
85 };
86
87 int
88 linux_to_bsd_sigaltstack(int lsa)
89 {
90         int bsa = 0;
91
92         if (lsa & LINUX_SS_DISABLE)
93                 bsa |= SS_DISABLE;
94         if (lsa & LINUX_SS_ONSTACK)
95                 bsa |= SS_ONSTACK;
96         return (bsa);
97 }
98
99 int
100 bsd_to_linux_sigaltstack(int bsa)
101 {
102         int lsa = 0;
103
104         if (bsa & SS_DISABLE)
105                 lsa |= LINUX_SS_DISABLE;
106         if (bsa & SS_ONSTACK)
107                 lsa |= LINUX_SS_ONSTACK;
108         return (lsa);
109 }
110
111 /*
112  * MPALMOSTSAFE
113  */
114 int
115 sys_linux_execve(struct linux_execve_args *args)
116 {
117         struct nlookupdata nd;
118         struct image_args exec_args;
119         char *path;
120         int error;
121
122         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
123         if (error)
124                 return (error);
125 #ifdef DEBUG
126         if (ldebug(execve))
127                 kprintf(ARGS(execve, "%s"), path);
128 #endif
129         get_mplock();
130         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
131         bzero(&exec_args, sizeof(exec_args));
132         if (error == 0) {
133                 error = exec_copyin_args(&exec_args, path, PATH_SYSSPACE,
134                                         args->argp, args->envp);
135         }
136         if (error == 0)
137                 error = kern_execve(&nd, &exec_args);
138         nlookup_done(&nd);
139
140         /*
141          * The syscall result is returned in registers to the new program.
142          * Linux will register %edx as an atexit function and we must be
143          * sure to set it to 0.  XXX
144          */
145         if (error == 0) {
146                 args->sysmsg_result64 = 0;
147                 if (curproc->p_sysent == &elf_linux_sysvec)
148                         error = emuldata_init(curproc, NULL, 0);
149         }
150
151         exec_free_args(&exec_args);
152         linux_free_path(&path);
153
154         if (error < 0) {
155                 /* We hit a lethal error condition.  Let's die now. */
156                 exit1(W_EXITCODE(0, SIGABRT));
157                 /* NOTREACHED */
158         }
159         rel_mplock();
160
161         return(error);
162 }
163
164 struct l_ipc_kludge {
165         struct l_msgbuf *msgp;
166         l_long msgtyp;
167 };
168
169 /*
170  * MPALMOSTSAFE
171  */
172 int
173 sys_linux_ipc(struct linux_ipc_args *args)
174 {
175         int error = 0;
176
177         get_mplock();
178
179         switch (args->what & 0xFFFF) {
180         case LINUX_SEMOP: {
181                 struct linux_semop_args a;
182
183                 a.semid = args->arg1;
184                 a.tsops = args->ptr;
185                 a.nsops = args->arg2;
186                 a.sysmsg_lresult = 0;
187                 error = linux_semop(&a);
188                 args->sysmsg_lresult = a.sysmsg_lresult;
189                 break;
190         }
191         case LINUX_SEMGET: {
192                 struct linux_semget_args a;
193
194                 a.key = args->arg1;
195                 a.nsems = args->arg2;
196                 a.semflg = args->arg3;
197                 a.sysmsg_lresult = 0;
198                 error = linux_semget(&a);
199                 args->sysmsg_lresult = a.sysmsg_lresult;
200                 break;
201         }
202         case LINUX_SEMCTL: {
203                 struct linux_semctl_args a;
204                 int error;
205
206                 a.semid = args->arg1;
207                 a.semnum = args->arg2;
208                 a.cmd = args->arg3;
209                 a.sysmsg_lresult = 0;
210                 error = copyin((caddr_t)args->ptr, &a.arg, sizeof(a.arg));
211                 if (error)
212                         break;
213                 error = linux_semctl(&a);
214                 args->sysmsg_lresult = a.sysmsg_lresult;
215                 break;
216         }
217         case LINUX_MSGSND: {
218                 struct linux_msgsnd_args a;
219
220                 a.msqid = args->arg1;
221                 a.msgp = args->ptr;
222                 a.msgsz = args->arg2;
223                 a.msgflg = args->arg3;
224                 a.sysmsg_lresult = 0;
225                 error = linux_msgsnd(&a);
226                 args->sysmsg_lresult = a.sysmsg_lresult;
227                 break;
228         }
229         case LINUX_MSGRCV: {
230                 struct linux_msgrcv_args a;
231
232                 a.msqid = args->arg1;
233                 a.msgsz = args->arg2;
234                 if (a.msgsz < 0) {
235                         error = EINVAL;
236                         break;
237                 }
238                 a.msgflg = args->arg3;
239                 a.sysmsg_lresult = 0;
240                 if ((args->what >> 16) == 0) {
241                         struct l_ipc_kludge tmp;
242                         int error;
243
244                         if (args->ptr == NULL) {
245                                 error = EINVAL;
246                                 break;
247                         }
248                         error = copyin((caddr_t)args->ptr, &tmp, sizeof(tmp));
249                         if (error)
250                                 break;
251                         a.msgp = tmp.msgp;
252                         a.msgtyp = tmp.msgtyp;
253                 } else {
254                         a.msgp = args->ptr;
255                         a.msgtyp = args->arg5;
256                 }
257                 error = linux_msgrcv(&a);
258                 args->sysmsg_lresult = a.sysmsg_lresult;
259                 break;
260         }
261         case LINUX_MSGGET: {
262                 struct linux_msgget_args a;
263
264                 a.key = args->arg1;
265                 a.msgflg = args->arg2;
266                 a.sysmsg_lresult = 0;
267                 error = linux_msgget(&a);
268                 args->sysmsg_lresult = a.sysmsg_lresult;
269                 break;
270         }
271         case LINUX_MSGCTL: {
272                 struct linux_msgctl_args a;
273
274                 a.msqid = args->arg1;
275                 a.cmd = args->arg2;
276                 a.buf = args->ptr;
277                 a.sysmsg_lresult = 0;
278                 error = linux_msgctl(&a);
279                 args->sysmsg_lresult = a.sysmsg_lresult;
280                 break;
281         }
282         case LINUX_SHMAT: {
283                 struct linux_shmat_args a;
284
285                 a.shmid = args->arg1;
286                 a.shmaddr = args->ptr;
287                 a.shmflg = args->arg2;
288                 a.raddr = (l_ulong *)args->arg3;
289                 a.sysmsg_lresult = 0;
290                 error = linux_shmat(&a);
291                 args->sysmsg_lresult = a.sysmsg_lresult;
292                 break;
293         }
294         case LINUX_SHMDT: {
295                 struct linux_shmdt_args a;
296
297                 a.shmaddr = args->ptr;
298                 a.sysmsg_lresult = 0;
299                 error = linux_shmdt(&a);
300                 args->sysmsg_lresult = a.sysmsg_lresult;
301                 break;
302         }
303         case LINUX_SHMGET: {
304                 struct linux_shmget_args a;
305
306                 a.key = args->arg1;
307                 a.size = args->arg2;
308                 a.shmflg = args->arg3;
309                 a.sysmsg_lresult = 0;
310                 error = linux_shmget(&a);
311                 args->sysmsg_lresult = a.sysmsg_lresult;
312                 break;
313         }
314         case LINUX_SHMCTL: {
315                 struct linux_shmctl_args a;
316
317                 a.shmid = args->arg1;
318                 a.cmd = args->arg2;
319                 a.buf = args->ptr;
320                 a.sysmsg_lresult = 0;
321                 error = linux_shmctl(&a);
322                 args->sysmsg_lresult = a.sysmsg_lresult;
323                 break;
324         }
325         default:
326                 error = EINVAL;
327                 break;
328         }
329         rel_mplock();
330         return(error);
331 }
332
333 /*
334  * MPSAFE
335  */
336 int
337 sys_linux_old_select(struct linux_old_select_args *args)
338 {
339         struct l_old_select_argv linux_args;
340         struct linux_select_args newsel;
341         int error;
342
343 #ifdef DEBUG
344         if (ldebug(old_select))
345                 kprintf(ARGS(old_select, "%p"), args->ptr);
346 #endif
347
348         error = copyin((caddr_t)args->ptr, &linux_args, sizeof(linux_args));
349         if (error)
350                 return (error);
351
352         newsel.sysmsg_iresult = 0;
353         newsel.nfds = linux_args.nfds;
354         newsel.readfds = linux_args.readfds;
355         newsel.writefds = linux_args.writefds;
356         newsel.exceptfds = linux_args.exceptfds;
357         newsel.timeout = linux_args.timeout;
358         error = sys_linux_select(&newsel);
359         args->sysmsg_iresult = newsel.sysmsg_iresult;
360         return(error);
361 }
362
363 /*
364  * MPSAFE
365  */
366 int
367 sys_linux_fork(struct linux_fork_args *args)
368 {
369         struct lwp *lp = curthread->td_lwp;
370         struct proc *p2;
371         int error;
372
373         get_mplock();
374         error = fork1(lp, RFFDG | RFPROC | RFPGLOCK, &p2);
375         if (error == 0) {
376                 emuldata_init(curproc, p2, 0);
377
378                 start_forked_proc(lp, p2);
379                 args->sysmsg_fds[0] = p2->p_pid;
380                 args->sysmsg_fds[1] = 0;
381         }
382         rel_mplock();
383
384         /* Are we the child? */
385         if (args->sysmsg_iresult == 1)
386                 args->sysmsg_iresult = 0;
387
388         return (error);
389 }
390
391 /*
392  * MPALMOSTSAFE
393  */
394 int
395 sys_linux_exit_group(struct linux_exit_group_args *args)
396 {
397         struct linux_emuldata *em, *e;
398         int rval;
399
400         rval = args->rval;
401         EMUL_LOCK();
402
403         em = emuldata_get(curproc);
404
405         if (em->s->refs == 1) {
406                 EMUL_UNLOCK();
407                 exit1(W_EXITCODE(rval, 0));
408                 /* NOTREACHED */
409                 return (0);
410         }
411         KKASSERT(em->proc == curproc);
412         em->flags |= EMUL_DIDKILL;
413         em->s->flags |= LINUX_LES_INEXITGROUP;
414         em->s->xstat = W_EXITCODE(rval, 0);
415
416         LIST_REMOVE(em, threads);
417         LIST_INSERT_HEAD(&em->s->threads, em, threads);
418
419         while ((e = LIST_NEXT(em, threads)) != NULL) {
420                 LIST_REMOVE(em, threads);
421                 LIST_INSERT_AFTER(e, em, threads);
422                 if ((e->flags & EMUL_DIDKILL) == 0) {
423                         e->flags |= EMUL_DIDKILL;
424                         lwkt_gettoken(&proc_token);
425                         KKASSERT(pfindn(e->proc->p_pid) == e->proc);
426                         ksignal(e->proc, SIGKILL);
427                         lwkt_reltoken(&proc_token);
428                 }
429         }
430
431         EMUL_UNLOCK();
432         exit1(W_EXITCODE(rval, 0));
433         /* NOTREACHED */
434
435         return (0);
436 }
437
438 /*
439  * MPSAFE
440  */
441 int
442 sys_linux_vfork(struct linux_vfork_args *args)
443 {
444         struct lwp *lp = curthread->td_lwp;
445         struct proc *p2;
446         int error;
447
448         get_mplock();
449         error = fork1(lp, RFFDG | RFPROC | RFPPWAIT | RFMEM | RFPGLOCK, &p2);
450         if (error == 0) {
451                 emuldata_init(curproc, p2, 0);
452
453                 start_forked_proc(lp, p2);
454                 args->sysmsg_fds[0] = p2->p_pid;
455                 args->sysmsg_fds[1] = 0;
456         }
457         rel_mplock();
458
459         if (args->sysmsg_iresult == 1)
460                 args->sysmsg_iresult = 0;
461
462         return (error);
463 }
464
465 /*
466  * MPALMOSTSAFE
467  */
468 int
469 sys_linux_clone(struct linux_clone_args *args)
470 {
471         struct segment_descriptor *desc;
472         struct l_user_desc info;
473         int idx;
474         int a[2];
475
476         struct lwp *lp = curthread->td_lwp;
477         int error, ff = RFPROC;
478         struct proc *p2 = NULL;
479         int exit_signal;
480         vm_offset_t start;
481
482         exit_signal = args->flags & 0x000000ff;
483         if (exit_signal >= LINUX_NSIG)
484                 return (EINVAL);
485         if (exit_signal <= LINUX_SIGTBLSZ)
486                 exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)];
487
488         if (args->flags & LINUX_CLONE_VM)
489                 ff |= RFMEM;
490         if (args->flags & LINUX_CLONE_SIGHAND)
491                 ff |= RFSIGSHARE;
492         if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS)))
493                 ff |= RFFDG;
494         if ((args->flags & 0xffffff00) == LINUX_THREADING_FLAGS)
495                 ff |= RFTHREAD;
496         if (args->flags & LINUX_CLONE_VFORK)
497                 ff |= RFPPWAIT;
498         if (args->flags & LINUX_CLONE_PARENT_SETTID) {
499                 if (args->parent_tidptr == NULL)
500                         return (EINVAL);
501         }
502
503         error = 0;
504         start = 0;
505
506         get_mplock();
507         error = fork1(lp, ff | RFPGLOCK, &p2);
508         if (error) {
509                 rel_mplock();
510                 return error;
511         }
512
513         args->sysmsg_fds[0] = p2 ? p2->p_pid : 0;
514         args->sysmsg_fds[1] = 0;
515         
516         if (args->flags & (LINUX_CLONE_PARENT | LINUX_CLONE_THREAD)) {
517                 lwkt_gettoken(&curproc->p_token);
518                 while (p2->p_pptr != curproc->p_pptr)
519                         proc_reparent(p2, curproc->p_pptr);
520                 lwkt_reltoken(&curproc->p_token);
521         }
522
523         emuldata_init(curproc, p2, args->flags);
524         linux_proc_fork(p2, curproc, args->child_tidptr);
525         /*
526          * XXX: this can't happen, p2 is never NULL, or else we'd have
527          *      other problems, too (see p2->p_sigparent == ...,
528          *      linux_proc_fork and emuldata_init.
529          */
530         if (p2 == NULL) {
531                 error = ESRCH;
532         } else {
533                 if (args->flags & LINUX_CLONE_PARENT_SETTID) {
534                         error = copyout(&p2->p_pid, args->parent_tidptr, sizeof(p2->p_pid));
535                 }
536         }
537
538         p2->p_sigparent = exit_signal;
539         if (args->stack) {
540                 ONLY_LWP_IN_PROC(p2)->lwp_md.md_regs->tf_esp =
541                                         (unsigned long)args->stack;
542         }
543
544         if (args->flags & LINUX_CLONE_SETTLS) {
545                 error = copyin((void *)curthread->td_lwp->lwp_md.md_regs->tf_esi, &info, sizeof(struct l_user_desc));
546                 if (error) {
547                         kprintf("copyin of tf_esi to info failed\n");
548                 } else {
549                         idx = info.entry_number;
550                         /*
551                          * We understand both our own entries such as the ones
552                          * we provide on linux_set_thread_area, as well as the
553                          * linux-type entries 6-8.
554                          */
555                         if ((idx < 6 || idx > 8) && (idx < GTLS_START)) {
556                                 kprintf("LINUX_CLONE_SETTLS, invalid idx requested: %d\n", idx);
557                                 goto out;
558                         }
559                         if (idx < GTLS_START) {
560                                 idx -= 6;
561                         } else {
562 #if 0 /* was SMP */
563                                 idx -= (GTLS_START + mycpu->gd_cpuid * NGDT);
564 #endif
565                                 idx -= GTLS_START;
566                         }
567                         KKASSERT(idx >= 0);
568
569                         a[0] = LINUX_LDT_entry_a(&info);
570                         a[1] = LINUX_LDT_entry_b(&info);
571                         if (p2) {
572                                 desc = &FIRST_LWP_IN_PROC(p2)->lwp_thread->td_tls.tls[idx];
573                                 memcpy(desc, &a, sizeof(a));
574                         } else {
575                                 kprintf("linux_clone... we don't have a p2\n");
576                         }
577                 }
578         }
579 out:
580         if (p2)
581                 start_forked_proc(lp, p2);
582
583         rel_mplock();
584 #ifdef DEBUG
585         if (ldebug(clone))
586                 kprintf(LMSG("clone: successful rfork to %ld"),
587                     (long)p2->p_pid);
588 #endif
589
590         return (error);
591 }
592
593 /* XXX move */
594 struct l_mmap_argv {
595         l_caddr_t       addr;
596         l_int           len;
597         l_int           prot;
598         l_int           flags;
599         l_int           fd;
600         l_int           pos;
601 };
602
603 #define STACK_SIZE  (2 * 1024 * 1024)
604 #define GUARD_SIZE  (4 * PAGE_SIZE)
605
606 /*
607  * MPALMOSTSAFE
608  */
609 static int
610 linux_mmap_common(caddr_t linux_addr, size_t linux_len, int linux_prot,
611                   int linux_flags, int linux_fd, off_t pos, void **res)
612 {
613         struct thread *td = curthread;
614         struct proc *p = td->td_proc;
615         caddr_t addr;
616         void *new;
617         int error, flags, len, prot, fd;
618
619         flags = 0;
620         if (linux_flags & LINUX_MAP_SHARED)
621                 flags |= MAP_SHARED;
622         if (linux_flags & LINUX_MAP_PRIVATE)
623                 flags |= MAP_PRIVATE;
624         if (linux_flags & LINUX_MAP_FIXED)
625                 flags |= MAP_FIXED;
626         if (linux_flags & LINUX_MAP_ANON) {
627                 flags |= MAP_ANON;
628         } else {
629                 flags |= MAP_NOSYNC;
630         }
631
632         lwkt_gettoken(&curproc->p_vmspace->vm_map.token);
633
634         if (linux_flags & LINUX_MAP_GROWSDOWN) {
635                 flags |= MAP_STACK;
636                 /* The linux MAP_GROWSDOWN option does not limit auto
637                  * growth of the region.  Linux mmap with this option
638                  * takes as addr the inital BOS, and as len, the initial
639                  * region size.  It can then grow down from addr without
640                  * limit.  However, linux threads has an implicit internal
641                  * limit to stack size of STACK_SIZE.  Its just not
642                  * enforced explicitly in linux.  But, here we impose
643                  * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
644                  * region, since we can do this with our mmap.
645                  *
646                  * Our mmap with MAP_STACK takes addr as the maximum
647                  * downsize limit on BOS, and as len the max size of
648                  * the region.  It them maps the top SGROWSIZ bytes,
649                  * and autgrows the region down, up to the limit
650                  * in addr.
651                  *
652                  * If we don't use the MAP_STACK option, the effect
653                  * of this code is to allocate a stack region of a
654                  * fixed size of (STACK_SIZE - GUARD_SIZE).
655                  */
656
657                 /* This gives us TOS */
658                 addr = linux_addr + linux_len;
659
660                 if (addr > p->p_vmspace->vm_maxsaddr) {
661                         /* Some linux apps will attempt to mmap
662                          * thread stacks near the top of their
663                          * address space.  If their TOS is greater
664                          * than vm_maxsaddr, vm_map_growstack()
665                          * will confuse the thread stack with the
666                          * process stack and deliver a SEGV if they
667                          * attempt to grow the thread stack past their
668                          * current stacksize rlimit.  To avoid this,
669                          * adjust vm_maxsaddr upwards to reflect
670                          * the current stacksize rlimit rather
671                          * than the maximum possible stacksize.
672                          * It would be better to adjust the
673                          * mmap'ed region, but some apps do not check
674                          * mmap's return value.
675                          */
676                         p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
677                             p->p_rlimit[RLIMIT_STACK].rlim_cur;
678                 }
679
680                 /* This gives us our maximum stack size */
681                 if (linux_len > STACK_SIZE - GUARD_SIZE) {
682                         len = linux_len;
683                 } else {
684                         len = STACK_SIZE - GUARD_SIZE;
685                 }
686                 /* This gives us a new BOS.  If we're using VM_STACK, then
687                  * mmap will just map the top SGROWSIZ bytes, and let
688                  * the stack grow down to the limit at BOS.  If we're
689                  * not using VM_STACK we map the full stack, since we
690                  * don't have a way to autogrow it.
691                  */
692                 addr -= len;
693         } else {
694                 addr = linux_addr;
695                 len = linux_len;
696         }
697
698         prot = linux_prot;
699
700         if (prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
701                 prot |= PROT_READ | PROT_EXEC;
702
703         if (linux_flags & LINUX_MAP_ANON) {
704                 fd = -1;
705         } else {
706                 fd = linux_fd;
707         }
708         
709 #ifdef DEBUG
710         if (ldebug(mmap) || ldebug(mmap2))
711                 kprintf("-> (%p, %d, %d, 0x%08x, %d, %lld)\n",
712                     addr, len, prot, flags, fd, pos);
713 #endif
714         error = kern_mmap(curproc->p_vmspace, addr, len,
715                           prot, flags, fd, pos, &new);
716
717         lwkt_reltoken(&curproc->p_vmspace->vm_map.token);
718
719         if (error == 0)
720                 *res = new;
721         return (error);
722 }
723
724 /*
725  * MPSAFE
726  */
727 int
728 sys_linux_mmap(struct linux_mmap_args *args)
729 {
730         struct l_mmap_argv linux_args;
731         int error;
732
733         error = copyin((caddr_t)args->ptr, &linux_args, sizeof(linux_args));
734         if (error)
735                 return (error);
736
737 #ifdef DEBUG
738         if (ldebug(mmap))
739                 kprintf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"),
740                     (void *)linux_args.addr, linux_args.len, linux_args.prot,
741                     linux_args.flags, linux_args.fd, linux_args.pos);
742 #endif
743         error = linux_mmap_common(linux_args.addr, linux_args.len,
744             linux_args.prot, linux_args.flags, linux_args.fd,
745             linux_args.pos, &args->sysmsg_resultp);
746 #ifdef DEBUG
747         if (ldebug(mmap))
748                 kprintf("-> %p\n", args->sysmsg_resultp);
749 #endif
750         return(error);
751 }
752
753 /*
754  * MPSAFE
755  */
756 int
757 sys_linux_mmap2(struct linux_mmap2_args *args)
758 {
759         int error;
760
761 #ifdef DEBUG
762         if (ldebug(mmap2))
763                 kprintf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"),
764                     (void *)args->addr, args->len, args->prot, args->flags,
765                     args->fd, args->pgoff);
766 #endif
767         error = linux_mmap_common((void *)args->addr, args->len, args->prot,
768             args->flags, args->fd, args->pgoff * PAGE_SIZE,
769             &args->sysmsg_resultp);
770 #ifdef DEBUG
771         if (ldebug(mmap2))
772                 kprintf("-> %p\n", args->sysmsg_resultp);
773 #endif
774         return (error);
775 }
776
777 /*
778  * MPSAFE
779  */
780 int
781 sys_linux_pipe(struct linux_pipe_args *args)
782 {
783         int error;
784         int reg_edx;
785         struct pipe_args bsd_args;
786
787 #ifdef DEBUG
788         if (ldebug(pipe))
789                 kprintf(ARGS(pipe, "*"));
790 #endif
791
792         reg_edx = args->sysmsg_fds[1];
793         error = sys_pipe(&bsd_args);
794         if (error) {
795                 args->sysmsg_fds[1] = reg_edx;
796                 return (error);
797         }
798
799         error = copyout(bsd_args.sysmsg_fds, args->pipefds, 2*sizeof(int));
800         if (error) {
801                 args->sysmsg_fds[1] = reg_edx;
802                 return (error);
803         }
804
805         args->sysmsg_fds[1] = reg_edx;
806         args->sysmsg_fds[0] = 0;
807         return (0);
808 }
809
810 /*
811  * XXX: Preliminary
812  */
813 int
814 sys_linux_pipe2(struct linux_pipe2_args *args)
815 {
816         struct thread *td = curthread;
817         int error;
818         int reg_edx;
819         struct pipe_args bsd_args;
820         union fcntl_dat dat;
821
822         reg_edx = args->sysmsg_fds[1];
823         error = sys_pipe(&bsd_args);
824         if (error) {
825                 args->sysmsg_fds[1] = reg_edx;
826                 return (error);
827         }
828
829 //      if (args->flags & LINUX_O_CLOEXEC) {
830 //      }
831
832         if (args->flags & LINUX_O_NONBLOCK) {
833                 dat.fc_flags = O_NONBLOCK;
834                 kern_fcntl(bsd_args.sysmsg_fds[0], F_SETFL, &dat, td->td_ucred);
835                 kern_fcntl(bsd_args.sysmsg_fds[1], F_SETFL, &dat, td->td_ucred);
836         }
837
838         error = copyout(bsd_args.sysmsg_fds, args->pipefds, 2*sizeof(int));
839         if (error) {
840                 args->sysmsg_fds[1] = reg_edx;
841                 return (error);
842         }
843
844         args->sysmsg_fds[1] = reg_edx;
845         args->sysmsg_fds[0] = 0;
846         return (0);
847 }
848
849 /*
850  * MPSAFE
851  */
852 int
853 sys_linux_ioperm(struct linux_ioperm_args *args)
854 {
855         struct sysarch_args sa;
856         struct i386_ioperm_args *iia;
857         caddr_t sg;
858         int error;
859
860         sg = stackgap_init();
861         iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args));
862         iia->start = args->start;
863         iia->length = args->length;
864         iia->enable = args->enable;
865         sa.sysmsg_resultp = NULL;
866         sa.op = I386_SET_IOPERM;
867         sa.parms = (char *)iia;
868         error = sys_sysarch(&sa);
869         args->sysmsg_resultp = sa.sysmsg_resultp;
870         return(error);
871 }
872
873 /*
874  * MPSAFE
875  */
876 int
877 sys_linux_iopl(struct linux_iopl_args *args)
878 {
879         struct thread *td = curthread;
880         struct lwp *lp = td->td_lwp;
881         int error;
882
883         if (args->level < 0 || args->level > 3)
884                 return (EINVAL);
885         if ((error = priv_check(td, PRIV_ROOT)) != 0)
886                 return (error);
887         if (securelevel > 0)
888                 return (EPERM);
889         lp->lwp_md.md_regs->tf_eflags =
890             (lp->lwp_md.md_regs->tf_eflags & ~PSL_IOPL) |
891             (args->level * (PSL_IOPL / 3));
892         return (0);
893 }
894
895 /*
896  * MPSAFE
897  */
898 int
899 sys_linux_modify_ldt(struct linux_modify_ldt_args *uap)
900 {
901         int error;
902         caddr_t sg;
903         struct sysarch_args args;
904         struct i386_ldt_args *ldt;
905         struct l_descriptor ld;
906         union descriptor *desc;
907         int size, written;
908
909         sg = stackgap_init();
910
911         if (uap->ptr == NULL)
912                 return (EINVAL);
913
914         switch (uap->func) {
915         case 0x00: /* read_ldt */
916                 ldt = stackgap_alloc(&sg, sizeof(*ldt));
917                 ldt->start = 0;
918                 ldt->descs = uap->ptr;
919                 ldt->num = uap->bytecount / sizeof(union descriptor);
920                 args.op = I386_GET_LDT;
921                 args.parms = (char*)ldt;
922                 args.sysmsg_iresult = 0;
923                 error = sys_sysarch(&args);
924                 uap->sysmsg_iresult = args.sysmsg_iresult *
925                                       sizeof(union descriptor);
926                 break;
927         case 0x02: /* read_default_ldt = 0 */
928                 size = 5*sizeof(struct l_desc_struct);
929                 if (size > uap->bytecount)
930                         size = uap->bytecount;
931                 for (written = error = 0; written < size && error == 0; written++)
932                         error = subyte((char *)uap->ptr + written, 0);
933                 uap->sysmsg_iresult = written;
934                 break;
935         case 0x01: /* write_ldt */
936         case 0x11: /* write_ldt */
937                 if (uap->bytecount != sizeof(ld))
938                         return (EINVAL);
939
940                 error = copyin(uap->ptr, &ld, sizeof(ld));
941                 if (error)
942                         return (error);
943
944                 ldt = stackgap_alloc(&sg, sizeof(*ldt));
945                 desc = stackgap_alloc(&sg, sizeof(*desc));
946                 ldt->start = ld.entry_number;
947                 ldt->descs = desc;
948                 ldt->num = 1;
949                 desc->sd.sd_lolimit = (ld.limit & 0x0000ffff);
950                 desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16;
951                 desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff);
952                 desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24;
953                 desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) |
954                         (ld.contents << 2);
955                 desc->sd.sd_dpl = 3;
956                 desc->sd.sd_p = (ld.seg_not_present ^ 1);
957                 desc->sd.sd_xx = 0;
958                 desc->sd.sd_def32 = ld.seg_32bit;
959                 desc->sd.sd_gran = ld.limit_in_pages;
960                 args.op = I386_SET_LDT;
961                 args.parms = (char*)ldt;
962                 args.sysmsg_iresult = 0;
963                 error = sys_sysarch(&args);
964                 uap->sysmsg_iresult = args.sysmsg_iresult;
965                 break;
966         default:
967                 error = EINVAL;
968                 break;
969         }
970
971         return (error);
972 }
973
974 /*
975  * MPALMOSTSAFE
976  */
977 int
978 sys_linux_sigaction(struct linux_sigaction_args *args)
979 {
980         l_osigaction_t osa;
981         l_sigaction_t linux_act, linux_oact;
982         struct sigaction act, oact;
983         int error, sig;
984
985 #ifdef DEBUG
986         if (ldebug(sigaction))
987                 kprintf(ARGS(sigaction, "%d, %p, %p"),
988                     args->sig, (void *)args->nsa, (void *)args->osa);
989 #endif
990
991         if (args->nsa) {
992                 error = copyin(args->nsa, &osa, sizeof(l_osigaction_t));
993                 if (error)
994                         return (error);
995                 linux_act.lsa_handler = osa.lsa_handler;
996                 linux_act.lsa_flags = osa.lsa_flags;
997                 linux_act.lsa_restorer = osa.lsa_restorer;
998                 LINUX_SIGEMPTYSET(linux_act.lsa_mask);
999                 linux_act.lsa_mask.__bits[0] = osa.lsa_mask;
1000                 linux_to_bsd_sigaction(&linux_act, &act);
1001         }
1002
1003         if (args->sig <= LINUX_SIGTBLSZ)
1004                 sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
1005         else
1006                 sig = args->sig;
1007
1008         get_mplock();
1009         error = kern_sigaction(sig, args->nsa ? &act : NULL,
1010                                args->osa ? &oact : NULL);
1011         rel_mplock();
1012
1013         if (args->osa != NULL && !error) {
1014                 bsd_to_linux_sigaction(&oact, &linux_oact);
1015                 osa.lsa_handler = linux_oact.lsa_handler;
1016                 osa.lsa_flags = linux_oact.lsa_flags;
1017                 osa.lsa_restorer = linux_oact.lsa_restorer;
1018                 osa.lsa_mask = linux_oact.lsa_mask.__bits[0];
1019                 error = copyout(&osa, args->osa, sizeof(l_osigaction_t));
1020         }
1021         return (error);
1022 }
1023
1024 /*
1025  * Linux has two extra args, restart and oldmask.  We dont use these,
1026  * but it seems that "restart" is actually a context pointer that
1027  * enables the signal to happen with a different register set.
1028  *
1029  * MPALMOSTSAFE
1030  */
1031 int
1032 sys_linux_sigsuspend(struct linux_sigsuspend_args *args)
1033 {
1034         l_sigset_t linux_mask;
1035         sigset_t mask;
1036         int error;
1037
1038 #ifdef DEBUG
1039         if (ldebug(sigsuspend))
1040                 kprintf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask);
1041 #endif
1042
1043         LINUX_SIGEMPTYSET(mask);
1044         mask.__bits[0] = args->mask;
1045         linux_to_bsd_sigset(&linux_mask, &mask);
1046
1047         get_mplock();
1048         error = kern_sigsuspend(&mask);
1049         rel_mplock();
1050
1051         return(error);
1052 }
1053
1054 /*
1055  * MPALMOSTSAFE
1056  */
1057 int
1058 sys_linux_rt_sigsuspend(struct linux_rt_sigsuspend_args *uap)
1059 {
1060         l_sigset_t linux_mask;
1061         sigset_t mask;
1062         int error;
1063
1064 #ifdef DEBUG
1065         if (ldebug(rt_sigsuspend))
1066                 kprintf(ARGS(rt_sigsuspend, "%p, %d"),
1067                     (void *)uap->newset, uap->sigsetsize);
1068 #endif
1069
1070         if (uap->sigsetsize != sizeof(l_sigset_t))
1071                 return (EINVAL);
1072
1073         error = copyin(uap->newset, &linux_mask, sizeof(l_sigset_t));
1074         if (error)
1075                 return (error);
1076
1077         linux_to_bsd_sigset(&linux_mask, &mask);
1078
1079         get_mplock();
1080         error = kern_sigsuspend(&mask);
1081         rel_mplock();
1082
1083         return(error);
1084 }
1085
1086 /*
1087  * MPALMOSTSAFE
1088  */
1089 int
1090 sys_linux_pause(struct linux_pause_args *args)
1091 {
1092         struct thread *td = curthread;
1093         struct lwp *lp = td->td_lwp;
1094         sigset_t mask;
1095         int error;
1096
1097 #ifdef DEBUG
1098         if (ldebug(pause))
1099                 kprintf(ARGS(pause, ""));
1100 #endif
1101
1102         mask = lp->lwp_sigmask;
1103
1104         get_mplock();
1105         error = kern_sigsuspend(&mask);
1106         rel_mplock();
1107
1108         return(error);
1109 }
1110
1111 /*
1112  * MPALMOSTSAFE
1113  */
1114 int
1115 sys_linux_sigaltstack(struct linux_sigaltstack_args *uap)
1116 {
1117         stack_t ss, oss;
1118         l_stack_t linux_ss;
1119         int error;
1120
1121 #ifdef DEBUG
1122         if (ldebug(sigaltstack))
1123                 kprintf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss);
1124 #endif
1125
1126         if (uap->uss) {
1127                 error = copyin(uap->uss, &linux_ss, sizeof(l_stack_t));
1128                 if (error)
1129                         return (error);
1130
1131                 ss.ss_sp = linux_ss.ss_sp;
1132                 ss.ss_size = linux_ss.ss_size;
1133                 ss.ss_flags = linux_to_bsd_sigaltstack(linux_ss.ss_flags);
1134         }
1135
1136         get_mplock();
1137         error = kern_sigaltstack(uap->uss ? &ss : NULL,
1138                                  uap->uoss ? &oss : NULL);
1139         rel_mplock();
1140
1141         if (error == 0 && uap->uoss) {
1142                 linux_ss.ss_sp = oss.ss_sp;
1143                 linux_ss.ss_size = oss.ss_size;
1144                 linux_ss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags);
1145                 error = copyout(&linux_ss, uap->uoss, sizeof(l_stack_t));
1146         }
1147
1148         return (error);
1149 }
1150
1151 int
1152 sys_linux_set_thread_area(struct linux_set_thread_area_args *args)
1153 {
1154         struct segment_descriptor *desc;
1155         struct l_user_desc info;
1156         int error;
1157         int idx;
1158         int a[2];
1159         int i;
1160
1161         error = copyin(args->desc, &info, sizeof(struct l_user_desc));
1162         if (error)
1163                 return (EFAULT);
1164
1165 #ifdef DEBUG
1166         if (ldebug(set_thread_area))
1167                 kprintf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, %i, %i, %i\n"),
1168                       info.entry_number,
1169                       info.base_addr,
1170                       info.limit,
1171                       info.seg_32bit,
1172                       info.contents,
1173                       info.read_exec_only,
1174                       info.limit_in_pages,
1175                       info.seg_not_present,
1176                       info.useable);
1177 #endif
1178
1179         idx = info.entry_number;
1180         if (idx != -1 && (idx < 6 || idx > 8))
1181                 return (EINVAL);
1182
1183         if (idx == -1) {
1184                 /* -1 means finding the first free TLS entry */
1185                 for (i = 0; i < NGTLS; i++) {
1186                         /*
1187                          * try to determine if the TLS entry is empty by looking
1188                          * at the lolimit entry.
1189                          */
1190                         if (curthread->td_tls.tls[idx].sd_lolimit == 0) {
1191                                 idx = i;
1192                                 break;
1193                         }
1194                 }
1195
1196                 if (idx == -1) {
1197                         /*
1198                          * By now we should have an index. If not, it means
1199                          * that no entry is free, so return ESRCH.
1200                          */
1201                         return (ESRCH);
1202                 }
1203         } else {
1204                 /* translate the index from Linux to ours */
1205                 idx -= 6;
1206                 KKASSERT(idx >= 0);
1207         }
1208
1209         /* Tell the caller about the allocated entry number */
1210 #if 0 /* was SMP */
1211         info.entry_number = GTLS_START + mycpu->gd_cpuid * NGDT + idx;
1212 #endif
1213         info.entry_number = GTLS_START + idx;
1214
1215
1216         error = copyout(&info, args->desc, sizeof(struct l_user_desc));
1217         if (error)
1218                 return (error);
1219
1220         if (LINUX_LDT_empty(&info)) {
1221                 a[0] = 0;
1222                 a[1] = 0;
1223         } else {
1224                 a[0] = LINUX_LDT_entry_a(&info);
1225                 a[1] = LINUX_LDT_entry_b(&info);
1226         }
1227
1228         /*
1229          * Update the TLS and the TLS entries in the GDT, but hold a critical
1230          * section as required by set_user_TLS().
1231          */
1232         crit_enter();
1233         desc = &curthread->td_tls.tls[idx];
1234         memcpy(desc, &a, sizeof(a));
1235         set_user_TLS();
1236         crit_exit();
1237
1238         return (0);
1239 }
1240
1241 int
1242 sys_linux_get_thread_area(struct linux_get_thread_area_args *args)
1243 {
1244         struct segment_descriptor *sd;
1245         struct l_desc_struct desc;
1246         struct l_user_desc info;
1247         int error;
1248         int idx;
1249
1250 #ifdef DEBUG
1251         if (ldebug(get_thread_area))
1252                 kprintf(ARGS(get_thread_area, "%p"), args->desc);
1253 #endif
1254
1255         error = copyin(args->desc, &info, sizeof(struct l_user_desc));
1256         if (error)
1257                 return (EFAULT);
1258                 
1259         idx = info.entry_number;
1260         if ((idx < 6 || idx > 8) && (idx < GTLS_START)) {
1261                 kprintf("sys_linux_get_thread_area, invalid idx requested: %d\n", idx);
1262                 return (EINVAL);
1263         }
1264
1265         memset(&info, 0, sizeof(info));
1266
1267         /* translate the index from Linux to ours */
1268         info.entry_number = idx;
1269         if (idx < GTLS_START) {
1270                 idx -= 6;
1271         } else {
1272 #if 0 /* was SMP */
1273                 idx -= (GTLS_START + mycpu->gd_cpuid * NGDT);
1274 #endif
1275                 idx -= GTLS_START;
1276
1277         }
1278         KKASSERT(idx >= 0);
1279
1280         sd = &curthread->td_tls.tls[idx];
1281         memcpy(&desc, sd, sizeof(desc));
1282         info.base_addr = LINUX_GET_BASE(&desc);
1283         info.limit = LINUX_GET_LIMIT(&desc);
1284         info.seg_32bit = LINUX_GET_32BIT(&desc);
1285         info.contents = LINUX_GET_CONTENTS(&desc);
1286         info.read_exec_only = !LINUX_GET_WRITABLE(&desc);
1287         info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc);
1288         info.seg_not_present = !LINUX_GET_PRESENT(&desc);
1289         info.useable = LINUX_GET_USEABLE(&desc);
1290
1291         error = copyout(&info, args->desc, sizeof(struct l_user_desc));
1292         if (error)
1293                 return (EFAULT);
1294
1295         return (0);
1296 }