From 770abdbb9c2f22fc13f2dc8ee14024fe29933651 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 May 2003 04:10:49 +0000 Subject: Add BASIC i386 binary support for the amd64 kernel. This is largely stolen from the ia64/ia32 code (indeed there was a repocopy), but I've redone the MD parts and added and fixed a few essential syscalls. It is sufficient to run i386 binaries like /bin/ls, /usr/bin/id (dynamic) and p4. The ia64 code has not implemented signal delivery, so I had to do that. Before you say it, yes, this does need to go in a common place. But we're in a freeze at the moment and I didn't want to risk breaking ia64. I will sort this out after the freeze so that the common code is in a common place. On the AMD64 side, this required adding segment selector context switch support and some other support infrastructure. The %fs/%gs etc code is hairy because loading %gs will clobber the kernel's current MSR_GSBASE setting. The segment selectors are not used by the kernel, so they're only changed at context switch time or when changing modes. This still needs to be optimized. Approved by: re (amd64/* blanket) --- sys/compat/freebsd32/freebsd32_misc.c | 116 +++++++++++++++++++++++++++++++++- sys/compat/freebsd32/freebsd32_util.h | 2 +- sys/compat/freebsd32/syscalls.master | 16 +++-- 3 files changed, 123 insertions(+), 11 deletions(-) (limited to 'sys/compat/freebsd32') diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index c1cdd20..9ef02c5 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -74,9 +74,9 @@ #include #include -#include -#include -#include +#include +#include +#include static const char ia32_emul_path[] = "/compat/ia32"; /* @@ -439,6 +439,7 @@ ia32_execve(struct thread *td, struct ia32_execve_args *uap) return execve(td, &ap); } +#ifdef __ia64__ static int ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, int prot, int fd, off_t pos) @@ -485,6 +486,7 @@ ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, return (0); } } +#endif int ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) @@ -497,6 +499,7 @@ ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) int fd = uap->fd; off_t pos = (uap->poslo | ((off_t)uap->poshi << 32)); +#ifdef __ia64__ vm_size_t pageoff; int error; @@ -567,6 +570,7 @@ ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) addr = start; len = end - start; } +#endif ap.addr = (void *) addr; ap.len = len; @@ -653,6 +657,83 @@ ia32_select(struct thread *td, struct ia32_select_args *uap) return (select(td, (struct select_args *) uap)); } +struct kevent32 { + u_int32_t ident; /* identifier for this event */ + short filter; /* filter for event */ + u_short flags; + u_int fflags; + int32_t data; + u_int32_t udata; /* opaque user data identifier */ +}; + +int +ia32_kevent(struct thread *td, struct ia32_kevent_args *uap) +{ + int error; + caddr_t sg; + struct timespec32 ts32; + struct timespec ts; + struct kevent32 ks32; + struct kevent *ks; + struct kevent_args a; + int i; + + sg = stackgap_init(); + + a.fd = uap->fd; + a.changelist = uap->changelist; + a.nchanges = uap->nchanges; + a.eventlist = uap->eventlist; + a.nevents = uap->nevents; + a.timeout = NULL; + + if (uap->timeout) { + a.timeout = stackgap_alloc(&sg, sizeof(struct timespec)); + error = copyin(uap->timeout, &ts32, sizeof(ts32)); + if (error) + return (error); + CP(ts32, ts, tv_sec); + CP(ts32, ts, tv_nsec); + error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts)); + if (error) + return (error); + } + if (uap->changelist) { + a.changelist = (struct kevent *)stackgap_alloc(&sg, uap->nchanges * sizeof(struct kevent)); + for (i = 0; i < uap->nchanges; i++) { + error = copyin(&uap->changelist[i], &ks32, sizeof(ks32)); + if (error) + return (error); + ks = (struct kevent *)(uintptr_t)&a.changelist[i]; + CP(ks32, *ks, ident); + CP(ks32, *ks, filter); + CP(ks32, *ks, flags); + CP(ks32, *ks, fflags); + CP(ks32, *ks, data); + PTRIN_CP(ks32, *ks, udata); + } + } + if (uap->eventlist) { + a.eventlist = stackgap_alloc(&sg, uap->nevents * sizeof(struct kevent)); + } + error = kevent(td, &a); + if (uap->eventlist && error > 0) { + for (i = 0; i < error; i++) { + ks = &a.eventlist[i]; + CP(*ks, ks32, ident); + CP(*ks, ks32, filter); + CP(*ks, ks32, flags); + CP(*ks, ks32, fflags); + CP(*ks, ks32, data); + PTROUT_CP(*ks, ks32, udata); + error = copyout(&ks32, &uap->eventlist[i], sizeof(ks32)); + if (error) + return (error); + } + } + return error; +} + int ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) { @@ -1287,6 +1368,35 @@ ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap) return (error); } +#ifdef COMPAT_FREEBSD4 +int +freebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap) +{ + struct sigaction32 s32; + struct sigaction sa, osa, *sap; + int error; + + if (uap->act) { + error = copyin(uap->act, &s32, sizeof(s32)); + if (error) + return (error); + sa.sa_handler = PTRIN(s32.sa_u); + CP(s32, sa, sa_flags); + CP(s32, sa, sa_mask); + sap = &sa; + } else + sap = NULL; + error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); + if (error != 0 && uap->oact != NULL) { + s32.sa_u = PTROUT(osa.sa_handler); + CP(osa, s32, sa_flags); + CP(osa, s32, sa_mask); + error = copyout(&s32, uap->oact, sizeof(s32)); + } + return (error); +} +#endif + #if 0 int diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h index 23f2aba..20a5b1e 100644 --- a/sys/compat/freebsd32/freebsd32_util.h +++ b/sys/compat/freebsd32/freebsd32_util.h @@ -44,7 +44,7 @@ struct ia32_ps_strings { int ps_nenvstr; /* the number of environment strings */ }; -#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE) +#define IA32_USRSTACK USRSTACK #define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) static __inline caddr_t stackgap_init(void); diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 508fdf7..042bf00 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -37,8 +37,8 @@ #include #include #include -#include -#include +#include +#include ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. @@ -484,11 +484,11 @@ 340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \ sigset_t *oset); } 341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); } -342 STD POSIX { int ia32_sigaction(int sig, \ +342 COMPAT4 POSIX { int ia32_sigaction(int sig, \ struct sigaction32 *act, \ struct sigaction32 *oact); } 343 MNOPROTO POSIX { int sigpending(sigset_t *set); } -344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); } +344 MCOMPAT4 BSD { int ia32_sigreturn(const struct __ucontext *sigcntxp); } 345 UNIMPL NOHIDE sigtimedwait 346 UNIMPL NOHIDE sigwaitinfo 347 MNOPROTO BSD { int __acl_get_file(const char *path, \ @@ -521,7 +521,7 @@ 360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } 361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } 362 MNOPROTO BSD { int kqueue(void); } -363 MNOPROTO BSD { int kevent(int fd, \ +363 MSTD BSD { int ia32_kevent(int fd, \ const struct kevent *changelist, int nchanges, \ struct kevent *eventlist, int nevents, \ const struct timespec *timeout); } @@ -586,8 +586,10 @@ 413 UNIMPL BSD extattr_get_link 414 UNIMPL BSD extattr_delete_link 415 UNIMPL BSD __mac_execve -416 UNIMPL BSD newsigreturn -417 UNIMPL BSD newsigaction +416 MSTD BSD { int ia32_sigreturn(const struct ia32_ucontext *sigcntxp); } +417 STD POSIX { int ia32_sigaction(int sig, \ + struct sigaction32 *act, \ + struct sigaction32 *oact); } 418 UNIMPL BSD __xstat 419 UNIMPL BSD __xfstat 420 UNIMPL BSD __xlstat -- cgit v1.1