Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[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.2 2003/06/17 04:28:38 dillon Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/lock.h>
35 #include <sys/mman.h>
36 #include <sys/proc.h>
37 #include <sys/resource.h>
38 #include <sys/resourcevar.h>
39 #include <sys/sysproto.h>
40 #include <sys/unistd.h>
41
42 #include <machine/frame.h>
43 #include <machine/psl.h>
44 #include <machine/segments.h>
45 #include <machine/sysarch.h>
46
47 #include <vm/vm.h>
48 #include <vm/pmap.h>
49 #include <vm/vm_map.h>
50
51 #include <i386/linux/linux.h>
52 #include <i386/linux/linux_proto.h>
53 #include <compat/linux/linux_ipc.h>
54 #include <compat/linux/linux_signal.h>
55 #include <compat/linux/linux_util.h>
56
57 struct l_descriptor {
58         l_uint          entry_number;
59         l_ulong         base_addr;
60         l_uint          limit;
61         l_uint          seg_32bit:1;
62         l_uint          contents:2;
63         l_uint          read_exec_only:1;
64         l_uint          limit_in_pages:1;
65         l_uint          seg_not_present:1;
66         l_uint          useable:1;
67 };
68
69 struct l_old_select_argv {
70         l_int           nfds;
71         l_fd_set        *readfds;
72         l_fd_set        *writefds;
73         l_fd_set        *exceptfds;
74         struct l_timeval        *timeout;
75 };
76
77 int
78 linux_to_bsd_sigaltstack(int lsa)
79 {
80         int bsa = 0;
81
82         if (lsa & LINUX_SS_DISABLE)
83                 bsa |= SS_DISABLE;
84         if (lsa & LINUX_SS_ONSTACK)
85                 bsa |= SS_ONSTACK;
86         return (bsa);
87 }
88
89 int
90 bsd_to_linux_sigaltstack(int bsa)
91 {
92         int lsa = 0;
93
94         if (bsa & SS_DISABLE)
95                 lsa |= LINUX_SS_DISABLE;
96         if (bsa & SS_ONSTACK)
97                 lsa |= LINUX_SS_ONSTACK;
98         return (lsa);
99 }
100
101 int
102 linux_execve(struct proc *p, struct linux_execve_args *args)
103 {
104         struct execve_args bsd;
105         caddr_t sg;
106
107         sg = stackgap_init();
108         CHECKALTEXIST(p, &sg, args->path);
109
110 #ifdef DEBUG
111         if (ldebug(execve))
112                 printf(ARGS(execve, "%s"), args->path);
113 #endif
114
115         bsd.fname = args->path;
116         bsd.argv = args->argp;
117         bsd.envv = args->envp;
118         return (execve(p, &bsd));
119 }
120
121 struct l_ipc_kludge {
122         struct l_msgbuf *msgp;
123         l_long msgtyp;
124 };
125
126 int
127 linux_ipc(struct proc *p, struct linux_ipc_args *args)
128 {
129
130         switch (args->what & 0xFFFF) {
131         case LINUX_SEMOP: {
132                 struct linux_semop_args a;
133
134                 a.semid = args->arg1;
135                 a.tsops = args->ptr;
136                 a.nsops = args->arg2;
137                 return (linux_semop(p, &a));
138         }
139         case LINUX_SEMGET: {
140                 struct linux_semget_args a;
141
142                 a.key = args->arg1;
143                 a.nsems = args->arg2;
144                 a.semflg = args->arg3;
145                 return (linux_semget(p, &a));
146         }
147         case LINUX_SEMCTL: {
148                 struct linux_semctl_args a;
149                 int error;
150
151                 a.semid = args->arg1;
152                 a.semnum = args->arg2;
153                 a.cmd = args->arg3;
154                 error = copyin((caddr_t)args->ptr, &a.arg, sizeof(a.arg));
155                 if (error)
156                         return (error);
157                 return (linux_semctl(p, &a));
158         }
159         case LINUX_MSGSND: {
160                 struct linux_msgsnd_args a;
161
162                 a.msqid = args->arg1;
163                 a.msgp = args->ptr;
164                 a.msgsz = args->arg2;
165                 a.msgflg = args->arg3;
166                 return (linux_msgsnd(p, &a));
167         }
168         case LINUX_MSGRCV: {
169                 struct linux_msgrcv_args a;
170
171                 a.msqid = args->arg1;
172                 a.msgsz = args->arg2;
173                 a.msgflg = args->arg3;
174                 if ((args->what >> 16) == 0) {
175                         struct l_ipc_kludge tmp;
176                         int error;
177
178                         if (args->ptr == NULL)
179                                 return (EINVAL);
180                         error = copyin((caddr_t)args->ptr, &tmp, sizeof(tmp));
181                         if (error)
182                                 return (error);
183                         a.msgp = tmp.msgp;
184                         a.msgtyp = tmp.msgtyp;
185                 } else {
186                         a.msgp = args->ptr;
187                         a.msgtyp = args->arg5;
188                 }
189                 return (linux_msgrcv(p, &a));
190         }
191         case LINUX_MSGGET: {
192                 struct linux_msgget_args a;
193
194                 a.key = args->arg1;
195                 a.msgflg = args->arg2;
196                 return (linux_msgget(p, &a));
197         }
198         case LINUX_MSGCTL: {
199                 struct linux_msgctl_args a;
200
201                 a.msqid = args->arg1;
202                 a.cmd = args->arg2;
203                 a.buf = args->ptr;
204                 return (linux_msgctl(p, &a));
205         }
206         case LINUX_SHMAT: {
207                 struct linux_shmat_args a;
208
209                 a.shmid = args->arg1;
210                 a.shmaddr = args->ptr;
211                 a.shmflg = args->arg2;
212                 a.raddr = (l_ulong *)args->arg3;
213                 return (linux_shmat(p, &a));
214         }
215         case LINUX_SHMDT: {
216                 struct linux_shmdt_args a;
217
218                 a.shmaddr = args->ptr;
219                 return (linux_shmdt(p, &a));
220         }
221         case LINUX_SHMGET: {
222                 struct linux_shmget_args a;
223
224                 a.key = args->arg1;
225                 a.size = args->arg2;
226                 a.shmflg = args->arg3;
227                 return (linux_shmget(p, &a));
228         }
229         case LINUX_SHMCTL: {
230                 struct linux_shmctl_args a;
231
232                 a.shmid = args->arg1;
233                 a.cmd = args->arg2;
234                 a.buf = args->ptr;
235                 return (linux_shmctl(p, &a));
236         }
237         default:
238                 break;
239         }
240
241         return (EINVAL);
242 }
243
244 int
245 linux_old_select(struct proc *p, struct linux_old_select_args *args)
246 {
247         struct l_old_select_argv linux_args;
248         struct linux_select_args newsel;
249         int error;
250
251 #ifdef DEBUG
252         if (ldebug(old_select))
253                 printf(ARGS(old_select, "%x"), args->ptr);
254 #endif
255
256         error = copyin((caddr_t)args->ptr, &linux_args, sizeof(linux_args));
257         if (error)
258                 return (error);
259
260         newsel.nfds = linux_args.nfds;
261         newsel.readfds = linux_args.readfds;
262         newsel.writefds = linux_args.writefds;
263         newsel.exceptfds = linux_args.exceptfds;
264         newsel.timeout = linux_args.timeout;
265         return (linux_select(p, &newsel));
266 }
267
268 int
269 linux_fork(struct proc *p, struct linux_fork_args *args)
270 {
271         int error;
272
273 #ifdef DEBUG
274         if (ldebug(fork))
275                 printf(ARGS(fork, ""));
276 #endif
277
278         if ((error = fork(p, (struct fork_args *)args)) != 0)
279                 return (error);
280
281         if (p->p_retval[1] == 1)
282                 p->p_retval[0] = 0;
283         return (0);
284 }
285
286 int
287 linux_vfork(struct proc *p, struct linux_vfork_args *args)
288 {
289         int error;
290
291 #ifdef DEBUG
292         if (ldebug(vfork))
293                 printf(ARGS(vfork, ""));
294 #endif
295
296         if ((error = vfork(p, (struct vfork_args *)args)) != 0)
297                 return (error);
298         /* Are we the child? */
299         if (p->p_retval[1] == 1)
300                 p->p_retval[0] = 0;
301         return (0);
302 }
303
304 #define CLONE_VM        0x100
305 #define CLONE_FS        0x200
306 #define CLONE_FILES     0x400
307 #define CLONE_SIGHAND   0x800
308 #define CLONE_PID       0x1000
309
310 int
311 linux_clone(struct proc *p, struct linux_clone_args *args)
312 {
313         int error, ff = RFPROC;
314         struct proc *p2;
315         int exit_signal;
316         vm_offset_t start;
317         struct rfork_args rf_args;
318
319 #ifdef DEBUG
320         if (ldebug(clone)) {
321                 printf(ARGS(clone, "flags %x, stack %x"), 
322                     (unsigned int)args->flags, (unsigned int)args->stack);
323                 if (args->flags & CLONE_PID)
324                         printf(LMSG("CLONE_PID not yet supported"));
325         }
326 #endif
327
328         if (!args->stack)
329                 return (EINVAL);
330
331         exit_signal = args->flags & 0x000000ff;
332         if (exit_signal >= LINUX_NSIG)
333                 return (EINVAL);
334
335         if (exit_signal <= LINUX_SIGTBLSZ)
336                 exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)];
337
338         /* RFTHREAD probably not necessary here, but it shouldn't hurt */
339         ff |= RFTHREAD;
340
341         if (args->flags & CLONE_VM)
342                 ff |= RFMEM;
343         if (args->flags & CLONE_SIGHAND)
344                 ff |= RFSIGSHARE;
345         if (!(args->flags & CLONE_FILES))
346                 ff |= RFFDG;
347
348         error = 0;
349         start = 0;
350
351         rf_args.flags = ff;
352         if ((error = rfork(p, &rf_args)) != 0)
353                 return (error);
354
355         p2 = pfind(p->p_retval[0]);
356         if (p2 == 0)
357                 return (ESRCH);
358
359         p2->p_sigparent = exit_signal;
360         p2->p_md.md_regs->tf_esp = (unsigned int)args->stack;
361
362 #ifdef DEBUG
363         if (ldebug(clone))
364                 printf(LMSG("clone: successful rfork to %ld"),
365                     (long)p2->p_pid);
366 #endif
367
368         return (0);
369 }
370
371 /* XXX move */
372 struct l_mmap_argv {
373         l_caddr_t       addr;
374         l_int           len;
375         l_int           prot;
376         l_int           flags;
377         l_int           fd;
378         l_int           pos;
379 };
380
381 #define STACK_SIZE  (2 * 1024 * 1024)
382 #define GUARD_SIZE  (4 * PAGE_SIZE)
383
384 int
385 linux_mmap(struct proc *p, struct linux_mmap_args *args)
386 {
387         struct mmap_args /* {
388                 caddr_t addr;
389                 size_t len;
390                 int prot;
391                 int flags;
392                 int fd;
393                 long pad;
394                 off_t pos;
395         } */ bsd_args;
396         int error;
397         struct l_mmap_argv linux_args;
398
399         error = copyin((caddr_t)args->ptr, &linux_args, sizeof(linux_args));
400         if (error)
401                 return (error);
402
403 #ifdef DEBUG
404         if (ldebug(mmap))
405                 printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"),
406                     (void *)linux_args.addr, linux_args.len, linux_args.prot,
407                     linux_args.flags, linux_args.fd, linux_args.pos);
408 #endif
409
410         bsd_args.flags = 0;
411         if (linux_args.flags & LINUX_MAP_SHARED)
412                 bsd_args.flags |= MAP_SHARED;
413         if (linux_args.flags & LINUX_MAP_PRIVATE)
414                 bsd_args.flags |= MAP_PRIVATE;
415         if (linux_args.flags & LINUX_MAP_FIXED)
416                 bsd_args.flags |= MAP_FIXED;
417         if (linux_args.flags & LINUX_MAP_ANON)
418                 bsd_args.flags |= MAP_ANON;
419         else
420                 bsd_args.flags |= MAP_NOSYNC;
421         if (linux_args.flags & LINUX_MAP_GROWSDOWN) {
422                 bsd_args.flags |= MAP_STACK;
423
424                 /* The linux MAP_GROWSDOWN option does not limit auto
425                  * growth of the region.  Linux mmap with this option
426                  * takes as addr the inital BOS, and as len, the initial
427                  * region size.  It can then grow down from addr without
428                  * limit.  However, linux threads has an implicit internal
429                  * limit to stack size of STACK_SIZE.  Its just not
430                  * enforced explicitly in linux.  But, here we impose
431                  * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
432                  * region, since we can do this with our mmap.
433                  *
434                  * Our mmap with MAP_STACK takes addr as the maximum
435                  * downsize limit on BOS, and as len the max size of
436                  * the region.  It them maps the top SGROWSIZ bytes,
437                  * and autgrows the region down, up to the limit
438                  * in addr.
439                  *
440                  * If we don't use the MAP_STACK option, the effect
441                  * of this code is to allocate a stack region of a
442                  * fixed size of (STACK_SIZE - GUARD_SIZE).
443                  */
444
445                 /* This gives us TOS */
446                 bsd_args.addr = linux_args.addr + linux_args.len;
447
448                 if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) {
449                         /* Some linux apps will attempt to mmap
450                          * thread stacks near the top of their
451                          * address space.  If their TOS is greater
452                          * than vm_maxsaddr, vm_map_growstack()
453                          * will confuse the thread stack with the
454                          * process stack and deliver a SEGV if they
455                          * attempt to grow the thread stack past their
456                          * current stacksize rlimit.  To avoid this,
457                          * adjust vm_maxsaddr upwards to reflect
458                          * the current stacksize rlimit rather
459                          * than the maximum possible stacksize.
460                          * It would be better to adjust the
461                          * mmap'ed region, but some apps do not check
462                          * mmap's return value.
463                          */
464                         p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
465                             p->p_rlimit[RLIMIT_STACK].rlim_cur;
466                 }
467
468                 /* This gives us our maximum stack size */
469                 if (linux_args.len > STACK_SIZE - GUARD_SIZE)
470                         bsd_args.len = linux_args.len;
471                 else
472                         bsd_args.len  = STACK_SIZE - GUARD_SIZE;
473
474                 /* This gives us a new BOS.  If we're using VM_STACK, then
475                  * mmap will just map the top SGROWSIZ bytes, and let
476                  * the stack grow down to the limit at BOS.  If we're
477                  * not using VM_STACK we map the full stack, since we
478                  * don't have a way to autogrow it.
479                  */
480                 bsd_args.addr -= bsd_args.len;
481         } else {
482                 bsd_args.addr = linux_args.addr;
483                 bsd_args.len  = linux_args.len;
484         }
485
486         bsd_args.prot = linux_args.prot | PROT_READ;    /* always required */
487         if (linux_args.flags & LINUX_MAP_ANON)
488                 bsd_args.fd = -1;
489         else
490                 bsd_args.fd = linux_args.fd;
491         bsd_args.pos = linux_args.pos;
492         bsd_args.pad = 0;
493
494 #ifdef DEBUG
495         if (ldebug(mmap))
496                 printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n",
497                     (void *)bsd_args.addr, bsd_args.len, bsd_args.prot,
498                     bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
499 #endif
500
501         return (mmap(p, &bsd_args));
502 }
503
504 int
505 linux_pipe(struct proc *p, struct linux_pipe_args *args)
506 {
507         int error;
508         int reg_edx;
509
510 #ifdef DEBUG
511         if (ldebug(pipe))
512                 printf(ARGS(pipe, "*"));
513 #endif
514
515         reg_edx = p->p_retval[1];
516         error = pipe(p, 0);
517         if (error) {
518                 p->p_retval[1] = reg_edx;
519                 return (error);
520         }
521
522         error = copyout(p->p_retval, args->pipefds, 2*sizeof(int));
523         if (error) {
524                 p->p_retval[1] = reg_edx;
525                 return (error);
526         }
527
528         p->p_retval[1] = reg_edx;
529         p->p_retval[0] = 0;
530         return (0);
531 }
532
533 int
534 linux_ioperm(struct proc *p, struct linux_ioperm_args *args)
535 {
536         struct sysarch_args sa;
537         struct i386_ioperm_args *iia;
538         caddr_t sg;
539
540         sg = stackgap_init();
541         iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args));
542         iia->start = args->start;
543         iia->length = args->length;
544         iia->enable = args->enable;
545         sa.op = I386_SET_IOPERM;
546         sa.parms = (char *)iia;
547         return (sysarch(p, &sa));
548 }
549
550 int
551 linux_iopl(struct proc *p, struct linux_iopl_args *args)
552 {
553         int error;
554
555         if (args->level < 0 || args->level > 3)
556                 return (EINVAL);
557         if ((error = suser(p)) != 0)
558                 return (error);
559         if (securelevel > 0)
560                 return (EPERM);
561         p->p_md.md_regs->tf_eflags = (p->p_md.md_regs->tf_eflags & ~PSL_IOPL) |
562             (args->level * (PSL_IOPL / 3));
563         return (0);
564 }
565
566 int
567 linux_modify_ldt(p, uap)
568         struct proc *p;
569         struct linux_modify_ldt_args *uap;
570 {
571         int error;
572         caddr_t sg;
573         struct sysarch_args args;
574         struct i386_ldt_args *ldt;
575         struct l_descriptor ld;
576         union descriptor *desc;
577
578         sg = stackgap_init();
579
580         if (uap->ptr == NULL)
581                 return (EINVAL);
582
583         switch (uap->func) {
584         case 0x00: /* read_ldt */
585                 ldt = stackgap_alloc(&sg, sizeof(*ldt));
586                 ldt->start = 0;
587                 ldt->descs = uap->ptr;
588                 ldt->num = uap->bytecount / sizeof(union descriptor);
589                 args.op = I386_GET_LDT;
590                 args.parms = (char*)ldt;
591                 error = sysarch(p, &args);
592                 p->p_retval[0] *= sizeof(union descriptor);
593                 break;
594         case 0x01: /* write_ldt */
595         case 0x11: /* write_ldt */
596                 if (uap->bytecount != sizeof(ld))
597                         return (EINVAL);
598
599                 error = copyin(uap->ptr, &ld, sizeof(ld));
600                 if (error)
601                         return (error);
602
603                 ldt = stackgap_alloc(&sg, sizeof(*ldt));
604                 desc = stackgap_alloc(&sg, sizeof(*desc));
605                 ldt->start = ld.entry_number;
606                 ldt->descs = desc;
607                 ldt->num = 1;
608                 desc->sd.sd_lolimit = (ld.limit & 0x0000ffff);
609                 desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16;
610                 desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff);
611                 desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24;
612                 desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) |
613                         (ld.contents << 2);
614                 desc->sd.sd_dpl = 3;
615                 desc->sd.sd_p = (ld.seg_not_present ^ 1);
616                 desc->sd.sd_xx = 0;
617                 desc->sd.sd_def32 = ld.seg_32bit;
618                 desc->sd.sd_gran = ld.limit_in_pages;
619                 args.op = I386_SET_LDT;
620                 args.parms = (char*)ldt;
621                 error = sysarch(p, &args);
622                 break;
623         default:
624                 error = EINVAL;
625                 break;
626         }
627
628         if (error == EOPNOTSUPP) {
629                 printf("linux: modify_ldt needs kernel option USER_LDT\n");
630                 error = ENOSYS;
631         }
632
633         return (error);
634 }
635
636 int
637 linux_sigaction(struct proc *p, struct linux_sigaction_args *args)
638 {
639         l_osigaction_t osa;
640         l_sigaction_t act, oact;
641         int error;
642
643 #ifdef DEBUG
644         if (ldebug(sigaction))
645                 printf(ARGS(sigaction, "%d, %p, %p"),
646                     args->sig, (void *)args->nsa, (void *)args->osa);
647 #endif
648
649         if (args->nsa != NULL) {
650                 error = copyin((caddr_t)args->nsa, &osa,
651                     sizeof(l_osigaction_t));
652                 if (error)
653                         return (error);
654                 act.lsa_handler = osa.lsa_handler;
655                 act.lsa_flags = osa.lsa_flags;
656                 act.lsa_restorer = osa.lsa_restorer;
657                 LINUX_SIGEMPTYSET(act.lsa_mask);
658                 act.lsa_mask.__bits[0] = osa.lsa_mask;
659         }
660
661         error = linux_do_sigaction(p, args->sig, args->nsa ? &act : NULL,
662             args->osa ? &oact : NULL);
663
664         if (args->osa != NULL && !error) {
665                 osa.lsa_handler = oact.lsa_handler;
666                 osa.lsa_flags = oact.lsa_flags;
667                 osa.lsa_restorer = oact.lsa_restorer;
668                 osa.lsa_mask = oact.lsa_mask.__bits[0];
669                 error = copyout(&osa, (caddr_t)args->osa,
670                     sizeof(l_osigaction_t));
671         }
672
673         return (error);
674 }
675
676 /*
677  * Linux has two extra args, restart and oldmask.  We dont use these,
678  * but it seems that "restart" is actually a context pointer that
679  * enables the signal to happen with a different register set.
680  */
681 int
682 linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args)
683 {
684         struct sigsuspend_args bsd;
685         sigset_t *sigmask;
686         l_sigset_t mask;
687         caddr_t sg = stackgap_init();
688
689 #ifdef DEBUG
690         if (ldebug(sigsuspend))
691                 printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask);
692 #endif
693
694         sigmask = stackgap_alloc(&sg, sizeof(sigset_t));
695         LINUX_SIGEMPTYSET(mask);
696         mask.__bits[0] = args->mask;
697         linux_to_bsd_sigset(&mask, sigmask);
698         bsd.sigmask = sigmask;
699         return (sigsuspend(p, &bsd));
700 }
701
702 int
703 linux_rt_sigsuspend(p, uap)
704         struct proc *p;
705         struct linux_rt_sigsuspend_args *uap;
706 {
707         l_sigset_t lmask;
708         sigset_t *bmask;
709         struct sigsuspend_args bsd;
710         caddr_t sg = stackgap_init();
711         int error;
712
713 #ifdef DEBUG
714         if (ldebug(rt_sigsuspend))
715                 printf(ARGS(rt_sigsuspend, "%p, %d"),
716                     (void *)uap->newset, uap->sigsetsize);
717 #endif
718
719         if (uap->sigsetsize != sizeof(l_sigset_t))
720                 return (EINVAL);
721
722         error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
723         if (error)
724                 return (error);
725
726         bmask = stackgap_alloc(&sg, sizeof(sigset_t));
727         linux_to_bsd_sigset(&lmask, bmask);
728         bsd.sigmask = bmask;
729         return (sigsuspend(p, &bsd));
730 }
731
732 int
733 linux_pause(struct proc *p, struct linux_pause_args *args)
734 {
735         struct sigsuspend_args bsd;
736         sigset_t *sigmask;
737         caddr_t sg = stackgap_init();
738
739 #ifdef DEBUG
740         if (ldebug(pause))
741                 printf(ARGS(pause, ""));
742 #endif
743
744         sigmask = stackgap_alloc(&sg, sizeof(sigset_t));
745         *sigmask = p->p_sigmask;
746         bsd.sigmask = sigmask;
747         return (sigsuspend(p, &bsd));
748 }
749
750 int
751 linux_sigaltstack(struct proc *p, struct linux_sigaltstack_args *uap)
752 {
753         struct sigaltstack_args bsd;
754         stack_t *ss, *oss;
755         l_stack_t lss;
756         int error;
757         caddr_t sg = stackgap_init();
758
759 #ifdef DEBUG
760         if (ldebug(sigaltstack))
761                 printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss);
762 #endif
763
764         if (uap->uss == NULL) {
765                 ss = NULL;
766         } else {
767                 error = copyin(uap->uss, &lss, sizeof(l_stack_t));
768                 if (error)
769                         return (error);
770
771                 ss = stackgap_alloc(&sg, sizeof(stack_t));
772                 ss->ss_sp = lss.ss_sp;
773                 ss->ss_size = lss.ss_size;
774                 ss->ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
775         }
776         oss = (uap->uoss != NULL)
777             ? stackgap_alloc(&sg, sizeof(stack_t))
778             : NULL;
779
780         bsd.ss = ss;
781         bsd.oss = oss;
782         error = sigaltstack(p, &bsd);
783
784         if (!error && oss != NULL) {
785                 lss.ss_sp = oss->ss_sp;
786                 lss.ss_size = oss->ss_size;
787                 lss.ss_flags = bsd_to_linux_sigaltstack(oss->ss_flags);
788                 error = copyout(&lss, uap->uoss, sizeof(l_stack_t));
789         }
790
791         return (error);
792 }