diff options
author | obrien <obrien@FreeBSD.org> | 2000-09-07 06:12:41 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2000-09-07 06:12:41 +0000 |
commit | c6d630aab04f96f333bdc9e4f8f3ef5969ba8f9c (patch) | |
tree | 47defb90992016146b55fdab82c1a4f564f13fe5 /sys/alpha/linux/linux_machdep.c | |
parent | fbcd630f0942f4340facafd9c7d4e9894772ede8 (diff) | |
download | FreeBSD-src-c6d630aab04f96f333bdc9e4f8f3ef5969ba8f9c.zip FreeBSD-src-c6d630aab04f96f333bdc9e4f8f3ef5969ba8f9c.tar.gz |
Minimal set of diffs from the i386 bits to the AlphaLinux.
Submitted by: gallatin (content, minimization by me)
Diffstat (limited to 'sys/alpha/linux/linux_machdep.c')
-rw-r--r-- | sys/alpha/linux/linux_machdep.c | 533 |
1 files changed, 127 insertions, 406 deletions
diff --git a/sys/alpha/linux/linux_machdep.c b/sys/alpha/linux/linux_machdep.c index afcfd4c..8dd672b 100644 --- a/sys/alpha/linux/linux_machdep.c +++ b/sys/alpha/linux/linux_machdep.c @@ -30,34 +30,21 @@ #include <sys/param.h> #include <sys/mman.h> -#include <sys/proc.h> +#include <sys/mount.h> #include <sys/sysproto.h> #include <sys/systm.h> -#include <sys/unistd.h> -#include <machine/frame.h> -#include <machine/psl.h> -#include <machine/segments.h> -#include <machine/sysarch.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> -#include <i386/linux/linux.h> -#include <i386/linux/linux_proto.h> -#include <compat/linux/linux_ipc.h> +#include <sys/user.h> + +#include <alpha/linux/linux.h> +#include <alpha/linux/linux_proto.h> #include <compat/linux/linux_signal.h> #include <compat/linux/linux_util.h> -struct linux_descriptor { - unsigned int entry_number; - unsigned long base_addr; - unsigned int limit; - unsigned int seg_32bit:1; - unsigned int contents:2; - unsigned int read_exec_only:1; - unsigned int limit_in_pages:1; - unsigned int seg_not_present:1; - unsigned int useable:1; -}; - struct linux_select_argv { int nfds; fd_set *readfds; @@ -87,61 +74,6 @@ linux_execve(struct proc *p, struct linux_execve_args *args) } int -linux_ipc(struct proc *p, struct linux_ipc_args *args) -{ - switch (args->what) { - case LINUX_SEMOP: - return (linux_semop(p, args)); - case LINUX_SEMGET: - return (linux_semget(p, args)); - case LINUX_SEMCTL: - return (linux_semctl(p, args)); - case LINUX_MSGSND: - return (linux_msgsnd(p, args)); - case LINUX_MSGRCV: - return (linux_msgrcv(p, args)); - case LINUX_MSGGET: - return (linux_msgget(p, args)); - case LINUX_MSGCTL: - return (linux_msgctl(p, args)); - case LINUX_SHMAT: - return (linux_shmat(p, args)); - case LINUX_SHMDT: - return (linux_shmdt(p, args)); - case LINUX_SHMGET: - return (linux_shmget(p, args)); - case LINUX_SHMCTL: - return (linux_shmctl(p, args)); - } - - uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); - return (ENOSYS); -} - -int -linux_select(struct proc *p, struct linux_select_args *args) -{ - struct linux_select_argv linux_args; - struct linux_newselect_args newsel; - int error; - -#ifdef SELECT_DEBUG - printf("Linux-emul(%ld): select(%x)\n", (long)p->p_pid, args->ptr); -#endif - - error = copyin(args->ptr, &linux_args, sizeof(linux_args)); - if (error) - return (error); - - newsel.nfds = linux_args.nfds; - newsel.readfds = linux_args.readfds; - newsel.writefds = linux_args.writefds; - newsel.exceptfds = linux_args.exceptfds; - newsel.timeout = linux_args.timeout; - return (linux_newselect(p, &newsel)); -} - -int linux_fork(struct proc *p, struct linux_fork_args *args) { int error; @@ -184,78 +116,14 @@ linux_vfork(struct proc *p, struct linux_vfork_args *args) int linux_clone(struct proc *p, struct linux_clone_args *args) { - int error, ff = RFPROC; - struct proc *p2; - int exit_signal; - vm_offset_t start; - struct rfork_args rf_args; - -#ifdef DEBUG - if (args->flags & CLONE_PID) - printf("linux_clone(%ld): CLONE_PID not yet supported\n", - (long)p->p_pid); - printf("linux_clone(%ld): invoked with flags %x and stack %x\n", - (long)p->p_pid, (unsigned int)args->flags, - (unsigned int)args->stack); -#endif - - if (!args->stack) - return (EINVAL); - - exit_signal = args->flags & 0x000000ff; - if (exit_signal >= LINUX_NSIG) - return (EINVAL); - - if (exit_signal <= LINUX_SIGTBLSZ) - exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)]; - - /* RFTHREAD probably not necessary here, but it shouldn't hurt */ - ff |= RFTHREAD; - - if (args->flags & CLONE_VM) - ff |= RFMEM; - if (args->flags & CLONE_SIGHAND) - ff |= RFSIGSHARE; - if (!(args->flags & CLONE_FILES)) - ff |= RFFDG; - - error = 0; - start = 0; - - rf_args.flags = ff; - if ((error = rfork(p, &rf_args)) != 0) - return (error); - - p2 = pfind(p->p_retval[0]); - if (p2 == 0) - return (ESRCH); - - p2->p_sigparent = exit_signal; - p2->p_md.md_regs->tf_esp = (unsigned int)args->stack; - -#ifdef DEBUG - printf ("linux_clone(%ld): successful rfork to %ld\n", (long)p->p_pid, - (long)p2->p_pid); -#endif - - return (0); + return ENOSYS; } -/* XXX move */ -struct linux_mmap_argv { - linux_caddr_t addr; - int len; - int prot; - int flags; - int fd; - int pos; -}; - -#define STACK_SIZE (2 * 1024 * 1024) -#define GUARD_SIZE (4 * PAGE_SIZE) +#define STACK_SIZE (2 * 1024 * 1024) +#define GUARD_SIZE (4 * PAGE_SIZE) int -linux_mmap(struct proc *p, struct linux_mmap_args *args) +linux_mmap(struct proc *p, struct linux_mmap_args *linux_args) { struct mmap_args /* { caddr_t addr; @@ -267,28 +135,28 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args) off_t pos; } */ bsd_args; int error; - struct linux_mmap_argv linux_args; - - error = copyin(args->ptr, &linux_args, sizeof(linux_args)); - if (error) - return (error); - #ifdef DEBUG - printf("Linux-emul(%ld): mmap(%p, %d, %d, 0x%08x, %d, %d)", - (long)p->p_pid, (void *)linux_args.addr, linux_args.len, - linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pos); + printf("Linux-emul(%ld): mmap(%p, 0x%lx, 0x%x, 0x%x, 0x%x, 0x%lx)\n", + (long)p->p_pid, (void *)linux_args->addr, linux_args->len, + linux_args->prot, linux_args->flags, linux_args->fd, linux_args->pos); #endif + bsd_args.prot = linux_args->prot | PROT_READ; /* always required */ + bsd_args.flags = 0; - if (linux_args.flags & LINUX_MAP_SHARED) + if (linux_args->flags & LINUX_MAP_SHARED) bsd_args.flags |= MAP_SHARED; - if (linux_args.flags & LINUX_MAP_PRIVATE) + if (linux_args->flags & LINUX_MAP_PRIVATE) bsd_args.flags |= MAP_PRIVATE; - if (linux_args.flags & LINUX_MAP_FIXED) + if (linux_args->flags & LINUX_MAP_FIXED){ bsd_args.flags |= MAP_FIXED; - if (linux_args.flags & LINUX_MAP_ANON) + bsd_args.pos = trunc_page(linux_args->pos); + } else { + bsd_args.pos = linux_args->pos; + } + if (linux_args->flags & LINUX_MAP_ANON) bsd_args.flags |= MAP_ANON; - if (linux_args.flags & LINUX_MAP_GROWSDOWN) { + if (linux_args->flags & LINUX_MAP_GROWSDOWN) { bsd_args.flags |= MAP_STACK; /* The linux MAP_GROWSDOWN option does not limit auto @@ -313,11 +181,11 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args) */ /* This gives us TOS */ - bsd_args.addr = linux_args.addr + linux_args.len; + bsd_args.addr = linux_args->addr + linux_args->len; /* This gives us our maximum stack size */ - if (linux_args.len > STACK_SIZE - GUARD_SIZE) - bsd_args.len = linux_args.len; + if (linux_args->len > STACK_SIZE - GUARD_SIZE) + bsd_args.len = linux_args->len; else bsd_args.len = STACK_SIZE - GUARD_SIZE; @@ -328,308 +196,161 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args) * don't have a way to autogrow it. */ bsd_args.addr -= bsd_args.len; + bsd_args.addr = (caddr_t)round_page(bsd_args.addr); /* XXXX */ } else { - bsd_args.addr = linux_args.addr; - bsd_args.len = linux_args.len; + bsd_args.addr = linux_args->addr; + bsd_args.len = linux_args->len; } - bsd_args.prot = linux_args.prot | PROT_READ; /* always required */ - if (linux_args.flags & LINUX_MAP_ANON) + bsd_args.fd = linux_args->fd; + if(linux_args->fd == 0) bsd_args.fd = -1; - else - bsd_args.fd = linux_args.fd; - bsd_args.pos = linux_args.pos; - bsd_args.pad = 0; + bsd_args.pad = 0; #ifdef DEBUG - printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n", (void *)bsd_args.addr, - bsd_args.len, bsd_args.prot, bsd_args.flags, bsd_args.fd, - (int)bsd_args.pos); + printf("Linux-emul(%ld): mmap(%p, 0x%lx, 0x%x, 0x%x, 0x%x, 0x%lx)\n", + (long)p->p_pid, + (void *)bsd_args.addr, + bsd_args.len, + bsd_args.prot, + bsd_args.flags, + bsd_args.fd, + bsd_args.pos); #endif - - return (mmap(p, &bsd_args)); + if (bsd_args.addr == 0) + bsd_args.addr = (caddr_t)0x40000000UL; + error = mmap(p, &bsd_args); +#ifdef DEBUG + printf("Linux-emul(%ld): mmap returns %d, 0x%lx\n", + (long)p->p_pid, error, p->p_retval[0]); +#endif + return (error); } int -linux_pipe(struct proc *p, struct linux_pipe_args *args) +linux_rt_sigsuspend(p, uap) + struct proc *p; + struct linux_rt_sigsuspend_args *uap; { + linux_sigset_t lmask; + sigset_t *bmask; + struct sigsuspend_args bsd; + caddr_t sg = stackgap_init(); int error; - int reg_edx; #ifdef DEBUG - printf("Linux-emul(%ld): pipe(*)\n", (long)p->p_pid); + printf("Linux-emul(%ld): rt_sigsuspend(%p, %d)\n", (long)p->p_pid, + (void *)uap->newset, uap->sigsetsize); #endif - reg_edx = p->p_retval[1]; - error = pipe(p, 0); - if (error) { - p->p_retval[1] = reg_edx; - return (error); - } + if (uap->sigsetsize != sizeof(linux_sigset_t)) + return (EINVAL); - error = copyout(p->p_retval, args->pipefds, 2*sizeof(int)); - if (error) { - p->p_retval[1] = reg_edx; + error = copyin(uap->newset, &lmask, sizeof(linux_sigset_t)); + if (error) return (error); - } - - p->p_retval[1] = reg_edx; - p->p_retval[0] = 0; - return (0); -} - -int -linux_ioperm(struct proc *p, struct linux_ioperm_args *args) -{ - struct sysarch_args sa; - struct i386_ioperm_args *iia; - caddr_t sg; - sg = stackgap_init(); - iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args)); - iia->start = args->start; - iia->length = args->length; - iia->enable = args->enable; - sa.op = I386_SET_IOPERM; - sa.parms = (char *)iia; - return (sysarch(p, &sa)); -} - -int -linux_iopl(struct proc *p, struct linux_iopl_args *args) -{ - int error; - - if (args->level < 0 || args->level > 3) - return (EINVAL); - if ((error = suser(p)) != 0) - return (error); - if (securelevel > 0) - return (EPERM); - p->p_md.md_regs->tf_eflags = (p->p_md.md_regs->tf_eflags & ~PSL_IOPL) | - (args->level * (PSL_IOPL / 3)); - return (0); + bmask = stackgap_alloc(&sg, sizeof(sigset_t)); + linux_to_bsd_sigset(&lmask, bmask); + bsd.sigmask = bmask; + return (sigsuspend(p, &bsd)); } int -linux_modify_ldt(p, uap) +linux_mprotect(p, uap) struct proc *p; - struct linux_modify_ldt_args *uap; + struct linux_mprotect_args *uap; { - int error; - caddr_t sg; - struct sysarch_args args; - struct i386_ldt_args *ldt; - struct linux_descriptor ld; - union descriptor *desc; - - sg = stackgap_init(); - - if (uap->ptr == NULL) - return (EINVAL); - - switch (uap->func) { - case 0x00: /* read_ldt */ - ldt = stackgap_alloc(&sg, sizeof(*ldt)); - ldt->start = 0; - ldt->descs = uap->ptr; - ldt->num = uap->bytecount / sizeof(union descriptor); - args.op = I386_GET_LDT; - args.parms = (char*)ldt; - error = sysarch(p, &args); - p->p_retval[0] *= sizeof(union descriptor); - break; - case 0x01: /* write_ldt */ - case 0x11: /* write_ldt */ - if (uap->bytecount != sizeof(ld)) - return (EINVAL); - - error = copyin(uap->ptr, &ld, sizeof(ld)); - if (error) - return (error); - - ldt = stackgap_alloc(&sg, sizeof(*ldt)); - desc = stackgap_alloc(&sg, sizeof(*desc)); - ldt->start = ld.entry_number; - ldt->descs = desc; - ldt->num = 1; - desc->sd.sd_lolimit = (ld.limit & 0x0000ffff); - desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; - desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff); - desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; - desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | - (ld.contents << 2); - desc->sd.sd_dpl = 3; - desc->sd.sd_p = (ld.seg_not_present ^ 1); - desc->sd.sd_xx = 0; - desc->sd.sd_def32 = ld.seg_32bit; - desc->sd.sd_gran = ld.limit_in_pages; - args.op = I386_SET_LDT; - args.parms = (char*)ldt; - error = sysarch(p, &args); - break; - default: - error = EINVAL; - break; - } - - if (error == EOPNOTSUPP) { - printf("linux: modify_ldt needs kernel option USER_LDT\n"); - error = ENOSYS; - } - - return (error); +#ifdef DEBUG + printf("Linux-emul(%ld): mprotect(%p, 0x%lx, 0x%x)\n", + (long)p->p_pid, (void *)uap->addr, uap->len, uap->prot); +#endif + return (mprotect(p, (void *)uap)); } int -linux_sigaction(struct proc *p, struct linux_sigaction_args *args) +linux_munmap(p, uap) + struct proc *p; + struct linux_munmap_args *uap; { - linux_osigaction_t osa; - linux_sigaction_t act, oact; - int error; - #ifdef DEBUG - printf("Linux-emul(%ld): sigaction(%d, %p, %p)\n", (long)p->p_pid, - args->sig, (void *)args->nsa, (void *)args->osa); + printf("Linux-emul(%ld): munmap(%p, 0x%lx)\n", + (long)p->p_pid, (void *)uap->addr, uap->len); #endif - - if (args->nsa != NULL) { - error = copyin(args->nsa, &osa, sizeof(linux_osigaction_t)); - if (error) - return (error); - act.lsa_handler = osa.lsa_handler; - act.lsa_flags = osa.lsa_flags; - act.lsa_restorer = osa.lsa_restorer; - LINUX_SIGEMPTYSET(act.lsa_mask); - act.lsa_mask.__bits[0] = osa.lsa_mask; - } - - error = linux_do_sigaction(p, args->sig, args->nsa ? &act : NULL, - args->osa ? &oact : NULL); - - if (args->osa != NULL && !error) { - osa.lsa_handler = oact.lsa_handler; - osa.lsa_flags = oact.lsa_flags; - osa.lsa_restorer = oact.lsa_restorer; - osa.lsa_mask = oact.lsa_mask.__bits[0]; - error = copyout(&osa, args->osa, sizeof(linux_osigaction_t)); - } - - return (error); + return (munmap(p, (void *)uap)); } /* - * Linux has two extra args, restart and oldmask. We dont use these, - * but it seems that "restart" is actually a context pointer that - * enables the signal to happen with a different register set. + * linux/alpha has 2 mappings for this, + * This is here purely to shut the compiler up. */ + int -linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args) +linux_setpgid(p, uap) + struct proc *p; + struct linux_setpgid_args *uap; { - struct sigsuspend_args bsd; - sigset_t *sigmask; - linux_sigset_t mask; - caddr_t sg = stackgap_init(); + return (setpgid(p, (void *)uap)); +} -#ifdef DEBUG - printf("Linux-emul(%ld): sigsuspend(%08lx)\n", - (long)p->p_pid, (unsigned long)args->mask); -#endif - sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); - LINUX_SIGEMPTYSET(mask); - mask.__bits[0] = args->mask; - linux_to_bsd_sigset(&mask, sigmask); - bsd.sigmask = sigmask; - return (sigsuspend(p, &bsd)); -} +static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = +{ RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, + RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NOFILE, -1, + RLIMIT_NPROC, RLIMIT_MEMLOCK +}; + +int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); int -linux_rt_sigsuspend(p, uap) - struct proc *p; - struct linux_rt_sigsuspend_args *uap; +linux_setrlimit(p, uap) + struct proc *p; + struct linux_setrlimit_args *uap; { - linux_sigset_t lmask; - sigset_t *bmask; - struct sigsuspend_args bsd; - caddr_t sg = stackgap_init(); - int error; + struct rlimit rlim; + u_int which; + int error; #ifdef DEBUG - printf("Linux-emul(%ld): rt_sigsuspend(%p, %d)\n", (long)p->p_pid, - (void *)uap->newset, uap->sigsetsize); + printf("Linux-emul(%ld): setrlimit(%d, %p)\n", + (long)p->p_pid, uap->resource, (void *)uap->rlim); #endif - if (uap->sigsetsize != sizeof(linux_sigset_t)) - return (EINVAL); + if (uap->resource >= LINUX_RLIM_NLIMITS) + return EINVAL; - error = copyin(uap->newset, &lmask, sizeof(linux_sigset_t)); - if (error) - return (error); + which = linux_to_bsd_resource[uap->resource]; - bmask = stackgap_alloc(&sg, sizeof(sigset_t)); - linux_to_bsd_sigset(&lmask, bmask); - bsd.sigmask = bmask; - return (sigsuspend(p, &bsd)); + if (which == -1) + return EINVAL; + + if ((error = + copyin((caddr_t)uap->rlim, (caddr_t)&rlim, sizeof (struct rlimit)))) + return (error); + return dosetrlimit(p, which, &rlim); } int -linux_pause(struct proc *p, struct linux_pause_args *args) +linux_getrlimit(p, uap) + struct proc *p; + struct linux_getrlimit_args *uap; { - struct sigsuspend_args bsd; - sigset_t *sigmask; - caddr_t sg = stackgap_init(); + u_int which; #ifdef DEBUG - printf("Linux-emul(%d): pause()\n", p->p_pid); + printf("Linux-emul(%ld): getrlimit(%d, %p)\n", + (long)p->p_pid, uap->resource, (void *)uap->rlim); #endif - sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); - *sigmask = p->p_sigmask; - bsd.sigmask = sigmask; - return (sigsuspend(p, &bsd)); -} - -int -linux_sigaltstack(p, uap) - struct proc *p; - struct linux_sigaltstack_args *uap; -{ - struct sigaltstack_args bsd; - stack_t *ss, *oss; - linux_stack_t lss; - int error; - caddr_t sg = stackgap_init(); + if (uap->resource >= LINUX_RLIM_NLIMITS) + return EINVAL; -#ifdef DEBUG - printf("Linux-emul(%ld): sigaltstack(%p, %p)\n", - (long)p->p_pid, uap->uss, uap->uoss); -#endif + which = linux_to_bsd_resource[uap->resource]; - error = copyin(uap->uss, &lss, sizeof(linux_stack_t)); - if (error) - return (error); + if (which == -1) + return EINVAL; - ss = stackgap_alloc(&sg, sizeof(stack_t)); - ss->ss_sp = lss.ss_sp; - ss->ss_size = (lss.ss_size >= LINUX_MINSIGSTKSZ && - lss.ss_size < MINSIGSTKSZ) ? MINSIGSTKSZ : lss.ss_size; - ss->ss_flags = lss.ss_flags; - - oss = (uap->uoss != NULL) - ? stackgap_alloc(&sg, sizeof(stack_t)) - : NULL; - - bsd.ss = ss; - bsd.oss = oss; - error = sigaltstack(p, &bsd); - - if (!error && oss != NULL) { - lss.ss_sp = oss->ss_sp; - lss.ss_size = oss->ss_size; - lss.ss_flags = oss->ss_flags; - error = copyout(&lss, uap->uoss, sizeof(linux_stack_t)); - } + return (copyout((caddr_t)&p->p_rlimit[which], (caddr_t)uap->rlim, + sizeof (struct rlimit))); - return (error); } |