Deleted Added
full compact
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}