linux_misc.c (63778) | linux_misc.c (64909) |
---|---|
1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 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 --- 11 unchanged lines hidden (view full) --- 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 * | 1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 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 --- 11 unchanged lines hidden (view full) --- 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: head/sys/compat/linux/linux_misc.c 63778 2000-07-23 16:54:18Z marcel $ | 28 * $FreeBSD: head/sys/compat/linux/linux_misc.c 64909 2000-08-22 01:46:50Z marcel $ |
29 */ 30 31#include "opt_compat.h" 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/sysproto.h> 36#include <sys/kernel.h> --- 18 unchanged lines hidden (view full) --- 55#include <vm/vm_map.h> 56#include <vm/vm_extern.h> 57 58#include <machine/frame.h> 59#include <machine/psl.h> 60#include <machine/sysarch.h> 61#include <machine/segments.h> 62 | 29 */ 30 31#include "opt_compat.h" 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/sysproto.h> 36#include <sys/kernel.h> --- 18 unchanged lines hidden (view full) --- 55#include <vm/vm_map.h> 56#include <vm/vm_extern.h> 57 58#include <machine/frame.h> 59#include <machine/psl.h> 60#include <machine/sysarch.h> 61#include <machine/segments.h> 62 |
63#include <i386/linux/linux.h> 64#include <i386/linux/linux_proto.h> 65#include <i386/linux/linux_util.h> 66#include <i386/linux/linux_mib.h> 67 | |
68#include <posix4/sched.h> 69 | 63#include <posix4/sched.h> 64 |
65#include <machine/../linux/linux.h> 66#include <machine/../linux/linux_proto.h> 67#include <compat/linux/linux_mib.h> 68#include <compat/linux/linux_util.h> 69 |
|
70#define BSD_TO_LINUX_SIGNAL(sig) \ 71 (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) 72 73static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = 74{ RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, 75 RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, 76 RLIMIT_MEMLOCK, -1 77}; --- 336 unchanged lines hidden (view full) --- 414 * Release the kernel mapping. 415 */ 416 if (a_out) 417 vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE); 418 419 return error; 420} 421 | 70#define BSD_TO_LINUX_SIGNAL(sig) \ 71 (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) 72 73static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = 74{ RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, 75 RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, 76 RLIMIT_MEMLOCK, -1 77}; --- 336 unchanged lines hidden (view full) --- 414 * Release the kernel mapping. 415 */ 416 if (a_out) 417 vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE); 418 419 return error; 420} 421 |
422/* XXX move */ 423struct linux_select_argv { 424 int nfds; 425 fd_set *readfds; 426 fd_set *writefds; 427 fd_set *exceptfds; 428 struct timeval *timeout; 429}; 430 | |
431int | 422int |
432linux_select(struct proc *p, struct linux_select_args *args) 433{ 434 struct linux_select_argv linux_args; 435 struct linux_newselect_args newsel; 436 int error; 437 438#ifdef SELECT_DEBUG 439 printf("Linux-emul(%ld): select(%x)\n", (long)p->p_pid, args->ptr); 440#endif 441 if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, 442 sizeof(linux_args)))) 443 return error; 444 445 newsel.nfds = linux_args.nfds; 446 newsel.readfds = linux_args.readfds; 447 newsel.writefds = linux_args.writefds; 448 newsel.exceptfds = linux_args.exceptfds; 449 newsel.timeout = linux_args.timeout; 450 451 return linux_newselect(p, &newsel); 452} 453 454int | |
455linux_newselect(struct proc *p, struct linux_newselect_args *args) 456{ 457 struct select_args bsa; 458 struct timeval tv0, tv1, utv, *tvp; 459 caddr_t sg; 460 int error; 461 462#ifdef DEBUG --- 100 unchanged lines hidden (view full) --- 563 return ESRCH; 564 } 565 else 566 curp = p; 567 p->p_retval[0] = curp->p_pgid; 568 return 0; 569} 570 | 423linux_newselect(struct proc *p, struct linux_newselect_args *args) 424{ 425 struct select_args bsa; 426 struct timeval tv0, tv1, utv, *tvp; 427 caddr_t sg; 428 int error; 429 430#ifdef DEBUG --- 100 unchanged lines hidden (view full) --- 531 return ESRCH; 532 } 533 else 534 curp = p; 535 p->p_retval[0] = curp->p_pgid; 536 return 0; 537} 538 |
571int 572linux_fork(struct proc *p, struct linux_fork_args *args) 573{ 574 int error; 575 576#ifdef DEBUG 577 printf("Linux-emul(%ld): fork()\n", (long)p->p_pid); 578#endif 579 if ((error = fork(p, (struct fork_args *)args)) != 0) 580 return error; 581 if (p->p_retval[1] == 1) 582 p->p_retval[0] = 0; 583 return 0; 584} 585 586int 587linux_vfork(struct proc *p, struct linux_vfork_args *args) 588{ 589 int error; 590 591#ifdef DEBUG 592 printf("Linux-emul(%ld): vfork()\n", (long)p->p_pid); 593#endif 594 595 if ((error = vfork(p, (struct vfork_args *)args)) != 0) 596 return error; 597 /* Are we the child? */ 598 if (p->p_retval[1] == 1) 599 p->p_retval[0] = 0; 600 return 0; 601} 602 603#define CLONE_VM 0x100 604#define CLONE_FS 0x200 605#define CLONE_FILES 0x400 606#define CLONE_SIGHAND 0x800 607#define CLONE_PID 0x1000 608 609int 610linux_clone(struct proc *p, struct linux_clone_args *args) 611{ 612 int error, ff = RFPROC; 613 struct proc *p2; 614 int exit_signal; 615 vm_offset_t start; 616 struct rfork_args rf_args; 617 618#ifdef DEBUG 619 if (args->flags & CLONE_PID) 620 printf("linux_clone(%ld): CLONE_PID not yet supported\n", 621 (long)p->p_pid); 622 printf("linux_clone(%ld): invoked with flags %x and stack %x\n", 623 (long)p->p_pid, (unsigned int)args->flags, 624 (unsigned int)args->stack); 625#endif 626 627 if (!args->stack) 628 return (EINVAL); 629 630 exit_signal = args->flags & 0x000000ff; 631 if (exit_signal >= LINUX_NSIG) 632 return EINVAL; 633 634 if (exit_signal <= LINUX_SIGTBLSZ) 635 exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)]; 636 637 /* RFTHREAD probably not necessary here, but it shouldn't hurt either */ 638 ff |= RFTHREAD; 639 640 if (args->flags & CLONE_VM) 641 ff |= RFMEM; 642 if (args->flags & CLONE_SIGHAND) 643 ff |= RFSIGSHARE; 644 if (!(args->flags & CLONE_FILES)) 645 ff |= RFFDG; 646 647 error = 0; 648 start = 0; 649 650 rf_args.flags = ff; 651 if ((error = rfork(p, &rf_args)) != 0) 652 return error; 653 654 p2 = pfind(p->p_retval[0]); 655 if (p2 == 0) 656 return ESRCH; 657 658 p2->p_sigparent = exit_signal; 659 p2->p_md.md_regs->tf_esp = (unsigned int)args->stack; 660 661#ifdef DEBUG 662 printf ("linux_clone(%ld): successful rfork to %ld\n", 663 (long)p->p_pid, (long)p2->p_pid); 664#endif 665 return 0; 666} 667 668/* XXX move */ 669struct linux_mmap_argv { 670 linux_caddr_t addr; 671 int len; 672 int prot; 673 int flags; 674 int fd; 675 int pos; 676}; 677 678#define STACK_SIZE (2 * 1024 * 1024) 679#define GUARD_SIZE (4 * PAGE_SIZE) 680int 681linux_mmap(struct proc *p, struct linux_mmap_args *args) 682{ 683 struct mmap_args /* { 684 caddr_t addr; 685 size_t len; 686 int prot; 687 int flags; 688 int fd; 689 long pad; 690 off_t pos; 691 } */ bsd_args; 692 int error; 693 struct linux_mmap_argv linux_args; 694 695 if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, 696 sizeof(linux_args)))) 697 return error; 698#ifdef DEBUG 699 printf("Linux-emul(%ld): mmap(%p, %d, %d, 0x%08x, %d, %d)", 700 (long)p->p_pid, (void *)linux_args.addr, linux_args.len, 701 linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pos); 702#endif 703 bsd_args.flags = 0; 704 if (linux_args.flags & LINUX_MAP_SHARED) 705 bsd_args.flags |= MAP_SHARED; 706 if (linux_args.flags & LINUX_MAP_PRIVATE) 707 bsd_args.flags |= MAP_PRIVATE; 708 if (linux_args.flags & LINUX_MAP_FIXED) 709 bsd_args.flags |= MAP_FIXED; 710 if (linux_args.flags & LINUX_MAP_ANON) 711 bsd_args.flags |= MAP_ANON; 712 if (linux_args.flags & LINUX_MAP_GROWSDOWN) { 713 bsd_args.flags |= MAP_STACK; 714 715 /* The linux MAP_GROWSDOWN option does not limit auto 716 * growth of the region. Linux mmap with this option 717 * takes as addr the inital BOS, and as len, the initial 718 * region size. It can then grow down from addr without 719 * limit. However, linux threads has an implicit internal 720 * limit to stack size of STACK_SIZE. Its just not 721 * enforced explicitly in linux. But, here we impose 722 * a limit of (STACK_SIZE - GUARD_SIZE) on the stack 723 * region, since we can do this with our mmap. 724 * 725 * Our mmap with MAP_STACK takes addr as the maximum 726 * downsize limit on BOS, and as len the max size of 727 * the region. It them maps the top SGROWSIZ bytes, 728 * and autgrows the region down, up to the limit 729 * in addr. 730 * 731 * If we don't use the MAP_STACK option, the effect 732 * of this code is to allocate a stack region of a 733 * fixed size of (STACK_SIZE - GUARD_SIZE). 734 */ 735 736 /* This gives us TOS */ 737 bsd_args.addr = linux_args.addr + linux_args.len; 738 739 /* This gives us our maximum stack size */ 740 if (linux_args.len > STACK_SIZE - GUARD_SIZE) 741 bsd_args.len = linux_args.len; 742 else 743 bsd_args.len = STACK_SIZE - GUARD_SIZE; 744 745 /* This gives us a new BOS. If we're using VM_STACK, then 746 * mmap will just map the top SGROWSIZ bytes, and let 747 * the stack grow down to the limit at BOS. If we're 748 * not using VM_STACK we map the full stack, since we 749 * don't have a way to autogrow it. 750 */ 751 bsd_args.addr -= bsd_args.len; 752 753 } else { 754 bsd_args.addr = linux_args.addr; 755 bsd_args.len = linux_args.len; 756 } 757 758 bsd_args.prot = linux_args.prot | PROT_READ; /* always required */ 759 if (linux_args.flags & LINUX_MAP_ANON) 760 bsd_args.fd = -1; 761 else 762 bsd_args.fd = linux_args.fd; 763 bsd_args.pos = linux_args.pos; 764 bsd_args.pad = 0; 765#ifdef DEBUG 766 printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n", 767 (void *)bsd_args.addr, bsd_args.len, 768 bsd_args.prot, bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); 769#endif 770 return mmap(p, &bsd_args); 771} 772 | |
773int 774linux_mremap(struct proc *p, struct linux_mremap_args *args) 775{ 776 struct munmap_args /* { 777 void *addr; 778 size_t len; 779 } */ bsd_args; 780 int error = 0; --- 29 unchanged lines hidden (view full) --- 810 bsd_args.addr = args->addr; 811 bsd_args.len = args->len; 812 bsd_args.flags = 0; /* XXX ignore */ 813 814 return msync(p, &bsd_args); 815} 816 817int | 539int 540linux_mremap(struct proc *p, struct linux_mremap_args *args) 541{ 542 struct munmap_args /* { 543 void *addr; 544 size_t len; 545 } */ bsd_args; 546 int error = 0; --- 29 unchanged lines hidden (view full) --- 576 bsd_args.addr = args->addr; 577 bsd_args.len = args->len; 578 bsd_args.flags = 0; /* XXX ignore */ 579 580 return msync(p, &bsd_args); 581} 582 583int |
818linux_pipe(struct proc *p, struct linux_pipe_args *args) 819{ 820 int error; 821 int reg_edx; 822 823#ifdef DEBUG 824 printf("Linux-emul(%ld): pipe(*)\n", (long)p->p_pid); 825#endif 826 reg_edx = p->p_retval[1]; 827 error = pipe(p, 0); 828 if (error) { 829 p->p_retval[1] = reg_edx; 830 return error; 831 } 832 833 error = copyout(p->p_retval, args->pipefds, 2*sizeof(int)); 834 if (error) { 835 p->p_retval[1] = reg_edx; 836 return error; 837 } 838 839 p->p_retval[1] = reg_edx; 840 p->p_retval[0] = 0; 841 return 0; 842} 843 844int | |
845linux_time(struct proc *p, struct linux_time_args *args) 846{ 847 struct timeval tv; 848 linux_time_t tm; 849 int error; 850 851#ifdef DEBUG 852 printf("Linux-emul(%ld): time(*)\n", (long)p->p_pid); --- 286 unchanged lines hidden (view full) --- 1139 (long)p->p_pid, (void *)args->itv); 1140#endif 1141 bsa.which = args->which; 1142 bsa.itv = args->itv; 1143 return getitimer(p, &bsa); 1144} 1145 1146int | 584linux_time(struct proc *p, struct linux_time_args *args) 585{ 586 struct timeval tv; 587 linux_time_t tm; 588 int error; 589 590#ifdef DEBUG 591 printf("Linux-emul(%ld): time(*)\n", (long)p->p_pid); --- 286 unchanged lines hidden (view full) --- 878 (long)p->p_pid, (void *)args->itv); 879#endif 880 bsa.which = args->which; 881 bsa.itv = args->itv; 882 return getitimer(p, &bsa); 883} 884 885int |
1147linux_ioperm(struct proc *p, struct linux_ioperm_args *args) 1148{ 1149 struct sysarch_args sa; 1150 struct i386_ioperm_args *iia; 1151 caddr_t sg; 1152 1153 sg = stackgap_init(); 1154 iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args)); 1155 iia->start = args->start; 1156 iia->length = args->length; 1157 iia->enable = args->enable; 1158 sa.op = I386_SET_IOPERM; 1159 sa.parms = (char *)iia; 1160 return sysarch(p, &sa); 1161} 1162 1163int 1164linux_iopl(struct proc *p, struct linux_iopl_args *args) 1165{ 1166 int error; 1167 1168 if (args->level < 0 || args->level > 3) 1169 return (EINVAL); 1170 if ((error = suser(p)) != 0) 1171 return (error); 1172 if (securelevel > 0) 1173 return (EPERM); 1174 p->p_md.md_regs->tf_eflags = (p->p_md.md_regs->tf_eflags & ~PSL_IOPL) | 1175 (args->level * (PSL_IOPL / 3)); 1176 return (0); 1177} 1178 1179int | |
1180linux_nice(struct proc *p, struct linux_nice_args *args) 1181{ 1182 struct setpriority_args bsd_args; 1183 1184 bsd_args.which = PRIO_PROCESS; 1185 bsd_args.who = 0; /* current process */ 1186 bsd_args.prio = args->inc; 1187 return setpriority(p, &bsd_args); --- 193 unchanged lines hidden (view full) --- 1381 break; 1382 case SCHED_RR: 1383 p->p_retval[0] = LINUX_SCHED_RR; 1384 break; 1385 } 1386 1387 return error; 1388} | 886linux_nice(struct proc *p, struct linux_nice_args *args) 887{ 888 struct setpriority_args bsd_args; 889 890 bsd_args.which = PRIO_PROCESS; 891 bsd_args.who = 0; /* current process */ 892 bsd_args.prio = args->inc; 893 return setpriority(p, &bsd_args); --- 193 unchanged lines hidden (view full) --- 1087 break; 1088 case SCHED_RR: 1089 p->p_retval[0] = LINUX_SCHED_RR; 1090 break; 1091 } 1092 1093 return error; 1094} |
1389 1390struct linux_descriptor { 1391 unsigned int entry_number; 1392 unsigned long base_addr; 1393 unsigned int limit; 1394 unsigned int seg_32bit:1; 1395 unsigned int contents:2; 1396 unsigned int read_exec_only:1; 1397 unsigned int limit_in_pages:1; 1398 unsigned int seg_not_present:1; 1399 unsigned int useable:1; 1400}; 1401 1402int 1403linux_modify_ldt(p, uap) 1404 struct proc *p; 1405 struct linux_modify_ldt_args *uap; 1406{ 1407 int error; 1408 caddr_t sg; 1409 struct sysarch_args args; 1410 struct i386_ldt_args *ldt; 1411 struct linux_descriptor ld; 1412 union descriptor *desc; 1413 1414 sg = stackgap_init(); 1415 1416 if (uap->ptr == NULL) 1417 return (EINVAL); 1418 1419 switch (uap->func) { 1420 case 0x00: /* read_ldt */ 1421 ldt = stackgap_alloc(&sg, sizeof(*ldt)); 1422 ldt->start = 0; 1423 ldt->descs = uap->ptr; 1424 ldt->num = uap->bytecount / sizeof(union descriptor); 1425 args.op = I386_GET_LDT; 1426 args.parms = (char*)ldt; 1427 error = sysarch(p, &args); 1428 p->p_retval[0] *= sizeof(union descriptor); 1429 break; 1430 case 0x01: /* write_ldt */ 1431 case 0x11: /* write_ldt */ 1432 if (uap->bytecount != sizeof(ld)) 1433 return (EINVAL); 1434 1435 error = copyin(uap->ptr, &ld, sizeof(ld)); 1436 if (error) 1437 return (error); 1438 1439 ldt = stackgap_alloc(&sg, sizeof(*ldt)); 1440 desc = stackgap_alloc(&sg, sizeof(*desc)); 1441 ldt->start = ld.entry_number; 1442 ldt->descs = desc; 1443 ldt->num = 1; 1444 desc->sd.sd_lolimit = (ld.limit & 0x0000ffff); 1445 desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; 1446 desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff); 1447 desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; 1448 desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | 1449 (ld.contents << 2); 1450 desc->sd.sd_dpl = 3; 1451 desc->sd.sd_p = (ld.seg_not_present ^ 1); 1452 desc->sd.sd_xx = 0; 1453 desc->sd.sd_def32 = ld.seg_32bit; 1454 desc->sd.sd_gran = ld.limit_in_pages; 1455 args.op = I386_SET_LDT; 1456 args.parms = (char*)ldt; 1457 error = sysarch(p, &args); 1458 break; 1459 default: 1460 error = EINVAL; 1461 break; 1462 } 1463 1464 if (error == EOPNOTSUPP) { 1465 printf("linux: modify_ldt needs kernel option USER_LDT\n"); 1466 error = ENOSYS; 1467 } 1468 1469 return (error); 1470} | |