linux_machdep.c revision 73856
1139749Simp/*- 253855Simp * Copyright (c) 2000 Marcel Moolenaar 353855Simp * All rights reserved. 453855Simp * 553855Simp * Redistribution and use in source and binary forms, with or without 653855Simp * modification, are permitted provided that the following conditions 753855Simp * are met: 853855Simp * 1. Redistributions of source code must retain the above copyright 953855Simp * notice, this list of conditions and the following disclaimer 1053855Simp * in this position and unchanged. 1153855Simp * 2. Redistributions in binary form must reproduce the above copyright 1253855Simp * notice, this list of conditions and the following disclaimer in the 1353855Simp * documentation and/or other materials provided with the distribution. 1453855Simp * 3. The name of the author may not be used to endorse or promote products 1553855Simp * derived from this software without specific prior written permission. 1653855Simp * 1753855Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1853855Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1953855Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2053855Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2153855Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2253855Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2353855Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2453855Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2553855Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2653855Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2753855Simp * 2853855Simp * $FreeBSD: head/sys/i386/linux/linux_machdep.c 73856 2001-03-06 02:59:46Z jhb $ 2959272Simp */ 30129798Simp 3197613Stakawata#include <sys/param.h> 3259272Simp#include <sys/mman.h> 3353855Simp#include <sys/proc.h> 3453855Simp#include <sys/sysproto.h> 3574636Simp#include <sys/systm.h> 3674636Simp#include <sys/unistd.h> 3774636Simp#include <sys/resource.h> 3853855Simp#include <sys/resourcevar.h> 3953855Simp 4053855Simp#include <machine/frame.h> 4153855Simp#include <machine/psl.h> 4253855Simp#include <machine/segments.h> 4353855Simp#include <machine/sysarch.h> 4453855Simp 4553855Simp#include <vm/vm.h> 4653855Simp#include <sys/lock.h> 4759193Simp#include <vm/pmap.h> 4853855Simp#include <vm/vm_map.h> 4953855Simp 5059193Simp#include <i386/linux/linux.h> 5158581Simp#include <i386/linux/linux_proto.h> 5259193Simp#include <compat/linux/linux_ipc.h> 5353855Simp#include <compat/linux/linux_signal.h> 5453855Simp#include <compat/linux/linux_util.h> 5559193Simp 5653855Simpstruct linux_descriptor { 5753855Simp unsigned int entry_number; 5859193Simp unsigned long base_addr; 5953855Simp unsigned int limit; 6059193Simp unsigned int seg_32bit:1; 6153855Simp unsigned int contents:2; 6259193Simp unsigned int read_exec_only:1; 6361779Simp unsigned int limit_in_pages:1; 6461779Simp unsigned int seg_not_present:1; 6561779Simp unsigned int useable:1; 6661779Simp}; 6759193Simp 6859193Simpstruct linux_select_argv { 6959193Simp int nfds; 7082376Sjon fd_set *readfds; 71140692Simp fd_set *writefds; 72140692Simp fd_set *exceptfds; 7359193Simp struct timeval *timeout; 7459193Simp}; 7564544Simp 7664544Simpint 7764544Simplinux_to_bsd_sigaltstack(int lsa) 7882376Sjon{ 79140692Simp int bsa = 0; 8064544Simp 8164544Simp if (lsa & LINUX_SS_DISABLE) 8261779Simp bsa |= SS_DISABLE; 8361779Simp if (lsa & LINUX_SS_ONSTACK) 8461779Simp bsa |= SS_ONSTACK; 8559193Simp return (bsa); 8659193Simp} 8759193Simp 8859193Simpint 8961779Simpbsd_to_linux_sigaltstack(int bsa) 9061779Simp{ 9161779Simp int lsa = 0; 9259193Simp 9359193Simp if (bsa & SS_DISABLE) 9459193Simp lsa |= LINUX_SS_DISABLE; 9559193Simp if (bsa & SS_ONSTACK) 9661779Simp lsa |= LINUX_SS_ONSTACK; 9766058Simp return (lsa); 9866058Simp} 9966058Simp 10066058Simpint 10166058Simplinux_execve(struct proc *p, struct linux_execve_args *args) 10266058Simp{ 10366058Simp struct execve_args bsd; 10466058Simp caddr_t sg; 10566058Simp 10666058Simp sg = stackgap_init(); 10766058Simp CHECKALTEXIST(p, &sg, args->path); 10866058Simp 10966058Simp#ifdef DEBUG 11066058Simp if (ldebug(execve)) 11166058Simp printf(ARGS(execve, "%s"), args->path); 11266058Simp#endif 11366058Simp 11466058Simp bsd.fname = args->path; 11566058Simp bsd.argv = args->argp; 11666058Simp bsd.envv = args->envp; 11766058Simp return (execve(p, &bsd)); 11866058Simp} 11974636Simp 12074636Simpint 12174636Simplinux_ipc(struct proc *p, struct linux_ipc_args *args) 12274636Simp{ 12366058Simp switch (args->what) { 12466058Simp case LINUX_SEMOP: 12566058Simp return (linux_semop(p, args)); 12666058Simp case LINUX_SEMGET: 12766058Simp return (linux_semget(p, args)); 12866058Simp case LINUX_SEMCTL: 12966058Simp return (linux_semctl(p, args)); 13066058Simp case LINUX_MSGSND: 13174636Simp return (linux_msgsnd(p, args)); 13274636Simp case LINUX_MSGRCV: 13374636Simp return (linux_msgrcv(p, args)); 13474636Simp case LINUX_MSGGET: 13574636Simp return (linux_msgget(p, args)); 13674636Simp case LINUX_MSGCTL: 13774636Simp return (linux_msgctl(p, args)); 13874636Simp case LINUX_SHMAT: 13974636Simp return (linux_shmat(p, args)); 14074636Simp case LINUX_SHMDT: 14174636Simp return (linux_shmdt(p, args)); 14274636Simp case LINUX_SHMGET: 14374636Simp return (linux_shmget(p, args)); 14474636Simp case LINUX_SHMCTL: 14574636Simp return (linux_shmctl(p, args)); 146100218Simp } 14774636Simp 14874636Simp uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 14974636Simp return (ENOSYS); 15074636Simp} 15174636Simp 15274636Simpint 153100218Simplinux_select(struct proc *p, struct linux_select_args *args) 154100218Simp{ 155100218Simp struct linux_select_argv linux_args; 15697613Stakawata struct linux_newselect_args newsel; 15797613Stakawata int error; 15897613Stakawata 15997613Stakawata#ifdef SELECT_DEBUG 16097613Stakawata if (ldebug(select)) 16197613Stakawata printf(ARGS(select, "%x"), args->ptr); 16297613Stakawata#endif 163100218Simp 16466058Simp error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 16566058Simp if (error) 16666058Simp return (error); 16766058Simp 16866058Simp newsel.nfds = linux_args.nfds; 16966058Simp newsel.readfds = linux_args.readfds; 17066058Simp newsel.writefds = linux_args.writefds; 17166058Simp newsel.exceptfds = linux_args.exceptfds; 172147711Simp newsel.timeout = linux_args.timeout; 173147711Simp return (linux_newselect(p, &newsel)); 174147711Simp} 175147711Simp 176147711Simpint 177147711Simplinux_fork(struct proc *p, struct linux_fork_args *args) 178147711Simp{ 179147711Simp int error; 180147711Simp 181#ifdef DEBUG 182 if (ldebug(fork)) 183 printf(ARGS(fork, "")); 184#endif 185 186 if ((error = fork(p, (struct fork_args *)args)) != 0) 187 return (error); 188 189 if (p->p_retval[1] == 1) 190 p->p_retval[0] = 0; 191 return (0); 192} 193 194int 195linux_vfork(struct proc *p, struct linux_vfork_args *args) 196{ 197 int error; 198 199#ifdef DEBUG 200 if (ldebug(vfork)) 201 printf(ARGS(vfork, "")); 202#endif 203 204 if ((error = vfork(p, (struct vfork_args *)args)) != 0) 205 return (error); 206 /* Are we the child? */ 207 if (p->p_retval[1] == 1) 208 p->p_retval[0] = 0; 209 return (0); 210} 211 212#define CLONE_VM 0x100 213#define CLONE_FS 0x200 214#define CLONE_FILES 0x400 215#define CLONE_SIGHAND 0x800 216#define CLONE_PID 0x1000 217 218int 219linux_clone(struct proc *p, struct linux_clone_args *args) 220{ 221 int error, ff = RFPROC | RFSTOPPED; 222 struct proc *p2; 223 int exit_signal; 224 vm_offset_t start; 225 struct rfork_args rf_args; 226 227#ifdef DEBUG 228 if (ldebug(clone)) { 229 printf(ARGS(clone, "flags %x, stack %x"), 230 (unsigned int)args->flags, (unsigned int)args->stack); 231 if (args->flags & CLONE_PID) 232 printf(LMSG("CLONE_PID not yet supported")); 233 } 234#endif 235 236 if (!args->stack) 237 return (EINVAL); 238 239 exit_signal = args->flags & 0x000000ff; 240 if (exit_signal >= LINUX_NSIG) 241 return (EINVAL); 242 243 if (exit_signal <= LINUX_SIGTBLSZ) 244 exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)]; 245 246 /* RFTHREAD probably not necessary here, but it shouldn't hurt */ 247 ff |= RFTHREAD; 248 249 if (args->flags & CLONE_VM) 250 ff |= RFMEM; 251 if (args->flags & CLONE_SIGHAND) 252 ff |= RFSIGSHARE; 253 if (!(args->flags & CLONE_FILES)) 254 ff |= RFFDG; 255 256 error = 0; 257 start = 0; 258 259 rf_args.flags = ff; 260 if ((error = rfork(p, &rf_args)) != 0) 261 return (error); 262 263 p2 = pfind(p->p_retval[0]); 264 if (p2 == NULL) 265 return (ESRCH); 266 267 PROC_LOCK(p2); 268 p2->p_sigparent = exit_signal; 269 PROC_UNLOCK(p2); 270 p2->p_md.md_regs->tf_esp = (unsigned int)args->stack; 271 272#ifdef DEBUG 273 if (ldebug(clone)) 274 printf(LMSG("clone: successful rfork to %ld"), 275 (long)p2->p_pid); 276#endif 277 278 /* 279 * Make this runnable after we are finished with it. 280 */ 281 mtx_lock_spin(&sched_lock); 282 p2->p_stat = SRUN; 283 setrunqueue(p2); 284 mtx_unlock_spin(&sched_lock); 285 286 return (0); 287} 288 289/* XXX move */ 290struct linux_mmap_argv { 291 linux_caddr_t addr; 292 int len; 293 int prot; 294 int flags; 295 int fd; 296 int pos; 297}; 298 299#define STACK_SIZE (2 * 1024 * 1024) 300#define GUARD_SIZE (4 * PAGE_SIZE) 301 302int 303linux_mmap(struct proc *p, struct linux_mmap_args *args) 304{ 305 struct mmap_args /* { 306 caddr_t addr; 307 size_t len; 308 int prot; 309 int flags; 310 int fd; 311 long pad; 312 off_t pos; 313 } */ bsd_args; 314 int error; 315 struct linux_mmap_argv linux_args; 316 317 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 318 if (error) 319 return (error); 320 321#ifdef DEBUG 322 if (ldebug(mmap)) 323 printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"), 324 (void *)linux_args.addr, linux_args.len, linux_args.prot, 325 linux_args.flags, linux_args.fd, linux_args.pos); 326#endif 327 328 bsd_args.flags = 0; 329 if (linux_args.flags & LINUX_MAP_SHARED) 330 bsd_args.flags |= MAP_SHARED; 331 if (linux_args.flags & LINUX_MAP_PRIVATE) 332 bsd_args.flags |= MAP_PRIVATE; 333 if (linux_args.flags & LINUX_MAP_FIXED) 334 bsd_args.flags |= MAP_FIXED; 335 if (linux_args.flags & LINUX_MAP_ANON) 336 bsd_args.flags |= MAP_ANON; 337 else 338 bsd_args.flags |= MAP_NOSYNC; 339 if (linux_args.flags & LINUX_MAP_GROWSDOWN) { 340 bsd_args.flags |= MAP_STACK; 341 342 /* The linux MAP_GROWSDOWN option does not limit auto 343 * growth of the region. Linux mmap with this option 344 * takes as addr the inital BOS, and as len, the initial 345 * region size. It can then grow down from addr without 346 * limit. However, linux threads has an implicit internal 347 * limit to stack size of STACK_SIZE. Its just not 348 * enforced explicitly in linux. But, here we impose 349 * a limit of (STACK_SIZE - GUARD_SIZE) on the stack 350 * region, since we can do this with our mmap. 351 * 352 * Our mmap with MAP_STACK takes addr as the maximum 353 * downsize limit on BOS, and as len the max size of 354 * the region. It them maps the top SGROWSIZ bytes, 355 * and autgrows the region down, up to the limit 356 * in addr. 357 * 358 * If we don't use the MAP_STACK option, the effect 359 * of this code is to allocate a stack region of a 360 * fixed size of (STACK_SIZE - GUARD_SIZE). 361 */ 362 363 /* This gives us TOS */ 364 bsd_args.addr = linux_args.addr + linux_args.len; 365 366 if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) { 367 /* Some linux apps will attempt to mmap 368 * thread stacks near the top of their 369 * address space. If their TOS is greater 370 * than vm_maxsaddr, vm_map_growstack() 371 * will confuse the thread stack with the 372 * process stack and deliver a SEGV if they 373 * attempt to grow the thread stack past their 374 * current stacksize rlimit. To avoid this, 375 * adjust vm_maxsaddr upwards to reflect 376 * the current stacksize rlimit rather 377 * than the maximum possible stacksize. 378 * It would be better to adjust the 379 * mmap'ed region, but some apps do not check 380 * mmap's return value. 381 */ 382 mtx_assert(&Giant, MA_OWNED); 383 p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - 384 p->p_rlimit[RLIMIT_STACK].rlim_cur; 385 } 386 387 /* This gives us our maximum stack size */ 388 if (linux_args.len > STACK_SIZE - GUARD_SIZE) 389 bsd_args.len = linux_args.len; 390 else 391 bsd_args.len = STACK_SIZE - GUARD_SIZE; 392 393 /* This gives us a new BOS. If we're using VM_STACK, then 394 * mmap will just map the top SGROWSIZ bytes, and let 395 * the stack grow down to the limit at BOS. If we're 396 * not using VM_STACK we map the full stack, since we 397 * don't have a way to autogrow it. 398 */ 399 bsd_args.addr -= bsd_args.len; 400 } else { 401 bsd_args.addr = linux_args.addr; 402 bsd_args.len = linux_args.len; 403 } 404 405 bsd_args.prot = linux_args.prot | PROT_READ; /* always required */ 406 if (linux_args.flags & LINUX_MAP_ANON) 407 bsd_args.fd = -1; 408 else 409 bsd_args.fd = linux_args.fd; 410 bsd_args.pos = linux_args.pos; 411 bsd_args.pad = 0; 412 413#ifdef DEBUG 414 if (ldebug(mmap)) 415 printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n", 416 (void *)bsd_args.addr, bsd_args.len, bsd_args.prot, 417 bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); 418#endif 419 420 return (mmap(p, &bsd_args)); 421} 422 423int 424linux_pipe(struct proc *p, struct linux_pipe_args *args) 425{ 426 int error; 427 int reg_edx; 428 429#ifdef DEBUG 430 if (ldebug(pipe)) 431 printf(ARGS(pipe, "*")); 432#endif 433 434 reg_edx = p->p_retval[1]; 435 error = pipe(p, 0); 436 if (error) { 437 p->p_retval[1] = reg_edx; 438 return (error); 439 } 440 441 error = copyout(p->p_retval, args->pipefds, 2*sizeof(int)); 442 if (error) { 443 p->p_retval[1] = reg_edx; 444 return (error); 445 } 446 447 p->p_retval[1] = reg_edx; 448 p->p_retval[0] = 0; 449 return (0); 450} 451 452int 453linux_ioperm(struct proc *p, struct linux_ioperm_args *args) 454{ 455 struct sysarch_args sa; 456 struct i386_ioperm_args *iia; 457 caddr_t sg; 458 459 sg = stackgap_init(); 460 iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args)); 461 iia->start = args->start; 462 iia->length = args->length; 463 iia->enable = args->enable; 464 sa.op = I386_SET_IOPERM; 465 sa.parms = (char *)iia; 466 return (sysarch(p, &sa)); 467} 468 469int 470linux_iopl(struct proc *p, struct linux_iopl_args *args) 471{ 472 int error; 473 474 if (args->level < 0 || args->level > 3) 475 return (EINVAL); 476 if ((error = suser(p)) != 0) 477 return (error); 478 if (securelevel > 0) 479 return (EPERM); 480 p->p_md.md_regs->tf_eflags = (p->p_md.md_regs->tf_eflags & ~PSL_IOPL) | 481 (args->level * (PSL_IOPL / 3)); 482 return (0); 483} 484 485int 486linux_modify_ldt(p, uap) 487 struct proc *p; 488 struct linux_modify_ldt_args *uap; 489{ 490 int error; 491 caddr_t sg; 492 struct sysarch_args args; 493 struct i386_ldt_args *ldt; 494 struct linux_descriptor ld; 495 union descriptor *desc; 496 497 sg = stackgap_init(); 498 499 if (uap->ptr == NULL) 500 return (EINVAL); 501 502 switch (uap->func) { 503 case 0x00: /* read_ldt */ 504 ldt = stackgap_alloc(&sg, sizeof(*ldt)); 505 ldt->start = 0; 506 ldt->descs = uap->ptr; 507 ldt->num = uap->bytecount / sizeof(union descriptor); 508 args.op = I386_GET_LDT; 509 args.parms = (char*)ldt; 510 error = sysarch(p, &args); 511 p->p_retval[0] *= sizeof(union descriptor); 512 break; 513 case 0x01: /* write_ldt */ 514 case 0x11: /* write_ldt */ 515 if (uap->bytecount != sizeof(ld)) 516 return (EINVAL); 517 518 error = copyin(uap->ptr, &ld, sizeof(ld)); 519 if (error) 520 return (error); 521 522 ldt = stackgap_alloc(&sg, sizeof(*ldt)); 523 desc = stackgap_alloc(&sg, sizeof(*desc)); 524 ldt->start = ld.entry_number; 525 ldt->descs = desc; 526 ldt->num = 1; 527 desc->sd.sd_lolimit = (ld.limit & 0x0000ffff); 528 desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; 529 desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff); 530 desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; 531 desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | 532 (ld.contents << 2); 533 desc->sd.sd_dpl = 3; 534 desc->sd.sd_p = (ld.seg_not_present ^ 1); 535 desc->sd.sd_xx = 0; 536 desc->sd.sd_def32 = ld.seg_32bit; 537 desc->sd.sd_gran = ld.limit_in_pages; 538 args.op = I386_SET_LDT; 539 args.parms = (char*)ldt; 540 error = sysarch(p, &args); 541 break; 542 default: 543 error = EINVAL; 544 break; 545 } 546 547 if (error == EOPNOTSUPP) { 548 printf("linux: modify_ldt needs kernel option USER_LDT\n"); 549 error = ENOSYS; 550 } 551 552 return (error); 553} 554 555int 556linux_sigaction(struct proc *p, struct linux_sigaction_args *args) 557{ 558 linux_osigaction_t osa; 559 linux_sigaction_t act, oact; 560 int error; 561 562#ifdef DEBUG 563 if (ldebug(sigaction)) 564 printf(ARGS(sigaction, "%d, %p, %p"), 565 args->sig, (void *)args->nsa, (void *)args->osa); 566#endif 567 568 if (args->nsa != NULL) { 569 error = copyin(args->nsa, &osa, sizeof(linux_osigaction_t)); 570 if (error) 571 return (error); 572 act.lsa_handler = osa.lsa_handler; 573 act.lsa_flags = osa.lsa_flags; 574 act.lsa_restorer = osa.lsa_restorer; 575 LINUX_SIGEMPTYSET(act.lsa_mask); 576 act.lsa_mask.__bits[0] = osa.lsa_mask; 577 } 578 579 error = linux_do_sigaction(p, args->sig, args->nsa ? &act : NULL, 580 args->osa ? &oact : NULL); 581 582 if (args->osa != NULL && !error) { 583 osa.lsa_handler = oact.lsa_handler; 584 osa.lsa_flags = oact.lsa_flags; 585 osa.lsa_restorer = oact.lsa_restorer; 586 osa.lsa_mask = oact.lsa_mask.__bits[0]; 587 error = copyout(&osa, args->osa, sizeof(linux_osigaction_t)); 588 } 589 590 return (error); 591} 592 593/* 594 * Linux has two extra args, restart and oldmask. We dont use these, 595 * but it seems that "restart" is actually a context pointer that 596 * enables the signal to happen with a different register set. 597 */ 598int 599linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args) 600{ 601 struct sigsuspend_args bsd; 602 sigset_t *sigmask; 603 linux_sigset_t mask; 604 caddr_t sg = stackgap_init(); 605 606#ifdef DEBUG 607 if (ldebug(sigsuspend)) 608 printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); 609#endif 610 611 sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); 612 LINUX_SIGEMPTYSET(mask); 613 mask.__bits[0] = args->mask; 614 linux_to_bsd_sigset(&mask, sigmask); 615 bsd.sigmask = sigmask; 616 return (sigsuspend(p, &bsd)); 617} 618 619int 620linux_rt_sigsuspend(p, uap) 621 struct proc *p; 622 struct linux_rt_sigsuspend_args *uap; 623{ 624 linux_sigset_t lmask; 625 sigset_t *bmask; 626 struct sigsuspend_args bsd; 627 caddr_t sg = stackgap_init(); 628 int error; 629 630#ifdef DEBUG 631 if (ldebug(rt_sigsuspend)) 632 printf(ARGS(rt_sigsuspend, "%p, %d"), 633 (void *)uap->newset, uap->sigsetsize); 634#endif 635 636 if (uap->sigsetsize != sizeof(linux_sigset_t)) 637 return (EINVAL); 638 639 error = copyin(uap->newset, &lmask, sizeof(linux_sigset_t)); 640 if (error) 641 return (error); 642 643 bmask = stackgap_alloc(&sg, sizeof(sigset_t)); 644 linux_to_bsd_sigset(&lmask, bmask); 645 bsd.sigmask = bmask; 646 return (sigsuspend(p, &bsd)); 647} 648 649int 650linux_pause(struct proc *p, struct linux_pause_args *args) 651{ 652 struct sigsuspend_args bsd; 653 sigset_t *sigmask; 654 caddr_t sg = stackgap_init(); 655 656#ifdef DEBUG 657 if (ldebug(pause)) 658 printf(ARGS(pause, "")); 659#endif 660 661 sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); 662 PROC_LOCK(p); 663 *sigmask = p->p_sigmask; 664 PROC_UNLOCK(p); 665 bsd.sigmask = sigmask; 666 return (sigsuspend(p, &bsd)); 667} 668 669int 670linux_sigaltstack(p, uap) 671 struct proc *p; 672 struct linux_sigaltstack_args *uap; 673{ 674 struct sigaltstack_args bsd; 675 stack_t *ss, *oss; 676 linux_stack_t lss; 677 int error; 678 caddr_t sg = stackgap_init(); 679 680#ifdef DEBUG 681 if (ldebug(sigaltstack)) 682 printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); 683#endif 684 685 if (uap->uss == NULL) { 686 ss = NULL; 687 } else { 688 error = copyin(uap->uss, &lss, sizeof(linux_stack_t)); 689 if (error) 690 return (error); 691 692 ss = stackgap_alloc(&sg, sizeof(stack_t)); 693 ss->ss_sp = lss.ss_sp; 694 ss->ss_size = lss.ss_size; 695 ss->ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 696 } 697 oss = (uap->uoss != NULL) 698 ? stackgap_alloc(&sg, sizeof(stack_t)) 699 : NULL; 700 701 bsd.ss = ss; 702 bsd.oss = oss; 703 error = sigaltstack(p, &bsd); 704 705 if (!error && oss != NULL) { 706 lss.ss_sp = oss->ss_sp; 707 lss.ss_size = oss->ss_size; 708 lss.ss_flags = bsd_to_linux_sigaltstack(oss->ss_flags); 709 error = copyout(&lss, uap->uoss, sizeof(linux_stack_t)); 710 } 711 712 return (error); 713} 714