2008-03-22 00:54:58 +03:00
|
|
|
/* $NetBSD: irix_syssgi.c,v 1.47 2008/03/21 21:54:58 ad Exp $ */
|
2001-11-28 15:00:53 +03:00
|
|
|
|
|
|
|
/*-
|
2008-03-22 00:54:58 +03:00
|
|
|
* Copyright (c) 2001, 2002, 2008 The NetBSD Foundation, Inc.
|
2001-11-28 15:00:53 +03:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
|
|
* by Emmanuel Dreyfus.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the NetBSD
|
|
|
|
* Foundation, Inc. and its contributors.
|
|
|
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
2008-03-22 00:54:58 +03:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: irix_syssgi.c,v 1.47 2008/03/21 21:54:58 ad Exp $");
|
2001-12-22 12:35:11 +03:00
|
|
|
|
2002-11-30 15:28:26 +03:00
|
|
|
#if defined(_KERNEL_OPT)
|
2001-12-22 12:35:11 +03:00
|
|
|
#include "opt_ddb.h"
|
2002-11-30 15:28:26 +03:00
|
|
|
#endif
|
2001-11-28 15:00:53 +03:00
|
|
|
|
2001-12-01 00:56:03 +03:00
|
|
|
#ifndef ELFSIZE
|
|
|
|
#define ELFSIZE 32
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* round up and down to page boundaries. Borrowed from sys/kern/exec_elf32.c */
|
|
|
|
#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
|
|
|
|
#define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/malloc.h>
|
2001-11-28 15:00:53 +03:00
|
|
|
#include <sys/systm.h>
|
2001-12-01 00:56:03 +03:00
|
|
|
#include <sys/filedesc.h>
|
|
|
|
#include <sys/buf.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/file.h>
|
2002-02-24 01:35:15 +03:00
|
|
|
#include <sys/resourcevar.h>
|
2001-12-08 14:17:37 +03:00
|
|
|
#include <sys/sysctl.h>
|
2001-12-27 01:18:25 +03:00
|
|
|
#include <sys/exec.h>
|
2001-12-01 00:56:03 +03:00
|
|
|
#include <sys/exec_elf.h>
|
2002-02-17 23:44:17 +03:00
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/syscallargs.h>
|
2001-12-01 00:56:03 +03:00
|
|
|
|
|
|
|
#include <uvm/uvm_extern.h>
|
2001-11-28 15:00:53 +03:00
|
|
|
|
2002-02-24 01:35:15 +03:00
|
|
|
#include <compat/common/compat_util.h>
|
|
|
|
|
2001-11-28 15:00:53 +03:00
|
|
|
#include <compat/svr4/svr4_types.h>
|
|
|
|
|
|
|
|
#include <compat/irix/irix_types.h>
|
2001-12-25 22:04:18 +03:00
|
|
|
#include <compat/irix/irix_signal.h>
|
- Introduce a e_fault field in struct proc to provide emulation specific
memory fault handler. IRIX uses irix_vm_fault, and all other emulation
use NULL, which means to use uvm_fault.
- While we are there, explicitely set to NULL the uninitialized fields in
struct emul: e_fault and e_sysctl on most ports
- e_fault is used by the trap handler, for now only on mips. In order to avoid
intrusive modifications in UVM, the function pointed by e_fault does not
has exactly the same protoype as uvm_fault:
int uvm_fault __P((struct vm_map *, vaddr_t, vm_fault_t, vm_prot_t));
int e_fault __P((struct proc *, vaddr_t, vm_fault_t, vm_prot_t));
- In IRIX share groups, all the VM space is shared, except one page.
This bounds us to have different VM spaces and synchronize modifications
to the VM space accross share group members. We need an IRIX specific hook
to the page fault handler in order to propagate VM space modifications
caused by page faults.
2002-09-22 01:14:54 +04:00
|
|
|
#include <compat/irix/irix_exec.h>
|
2002-06-13 00:33:20 +04:00
|
|
|
#include <compat/irix/irix_prctl.h>
|
2001-11-28 15:00:53 +03:00
|
|
|
#include <compat/irix/irix_syscall.h>
|
|
|
|
#include <compat/irix/irix_syscallargs.h>
|
|
|
|
#include <compat/irix/irix_syssgi.h>
|
|
|
|
|
2001-12-27 01:18:25 +03:00
|
|
|
/* In sys/kern/exec_elf32.c */
|
|
|
|
void ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
|
|
|
|
const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
|
|
|
|
|
2007-12-04 21:40:07 +03:00
|
|
|
static int irix_syssgi_mapelf(int, Elf_Phdr *, int,
|
|
|
|
struct lwp *, register_t *);
|
|
|
|
static int irix_syssgi_sysconf(int name, struct lwp *, register_t *);
|
|
|
|
static int irix_syssgi_pathconf(char *, int, struct lwp *, register_t *);
|
2001-12-01 00:56:03 +03:00
|
|
|
|
2001-11-28 15:00:53 +03:00
|
|
|
int
|
2007-12-21 02:02:38 +03:00
|
|
|
irix_sys_syssgi(struct lwp *l, const struct irix_sys_syssgi_args *uap, register_t *retval)
|
2001-11-28 15:00:53 +03:00
|
|
|
{
|
2007-12-21 02:02:38 +03:00
|
|
|
/* {
|
2001-11-28 15:00:53 +03:00
|
|
|
syscallarg(int) request;
|
|
|
|
syscallarg(void *) arg1;
|
|
|
|
syscallarg(void *) arg2;
|
|
|
|
syscallarg(void *) arg3;
|
2005-02-27 01:58:54 +03:00
|
|
|
syscallarg(void *) arg4;
|
|
|
|
syscallarg(void *) arg5;
|
2007-12-21 02:02:38 +03:00
|
|
|
} */
|
2003-01-22 15:58:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
2001-12-01 00:56:03 +03:00
|
|
|
int request = SCARG(uap, request);
|
2005-02-27 01:58:54 +03:00
|
|
|
void *arg1, *arg2, *arg3;
|
2001-11-28 15:00:53 +03:00
|
|
|
|
|
|
|
#ifdef DEBUG_IRIX
|
2001-12-02 01:19:38 +03:00
|
|
|
printf("irix_sys_syssgi(): request = %d\n", request);
|
2001-11-28 15:00:53 +03:00
|
|
|
#endif
|
2001-12-01 00:56:03 +03:00
|
|
|
switch(request) {
|
|
|
|
case IRIX_SGI_SYSID: /* Get HostID */
|
|
|
|
*retval = (register_t)hostid;
|
|
|
|
break;
|
|
|
|
|
2002-03-11 01:36:28 +03:00
|
|
|
case IRIX_SGI_SETGROUPS: { /* setgroups(2) */
|
|
|
|
struct sys_setgroups_args cup;
|
|
|
|
|
|
|
|
SCARG(&cup, gidsetsize) = (int)SCARG(uap, arg1);
|
|
|
|
SCARG(&cup, gidset) = (gid_t *)SCARG(uap, arg2);
|
2003-01-22 15:58:22 +03:00
|
|
|
return (sys_setgroups(l, &cup, retval));
|
2002-03-11 01:36:28 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case IRIX_SGI_GETGROUPS: { /* getgroups(2) */
|
|
|
|
struct sys_getgroups_args cup;
|
|
|
|
|
|
|
|
SCARG(&cup, gidsetsize) = (int)SCARG(uap, arg1);
|
|
|
|
SCARG(&cup, gidset) = (gid_t *)SCARG(uap, arg2);
|
2003-01-22 15:58:22 +03:00
|
|
|
return (sys_getgroups(l, &cup, retval));
|
2002-03-11 01:36:28 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-03-28 15:59:35 +03:00
|
|
|
case IRIX_SGI_SETSID: /* Set session ID: setsid(2) */
|
2005-02-27 01:58:54 +03:00
|
|
|
return (sys_setsid(l, NULL, retval));
|
2002-03-28 15:59:35 +03:00
|
|
|
break;
|
|
|
|
|
2002-02-17 23:44:17 +03:00
|
|
|
case IRIX_SGI_GETSID: { /* Get session ID: getsid(2) */
|
|
|
|
struct sys_getsid_args cup;
|
2001-12-27 12:31:09 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
SCARG(&cup, pid) = (pid_t)SCARG(uap, arg1);
|
|
|
|
return (sys_getsid(l, &cup, retval));
|
2002-02-17 23:44:17 +03:00
|
|
|
break;
|
|
|
|
}
|
2001-12-27 12:31:09 +03:00
|
|
|
|
2002-02-17 23:44:17 +03:00
|
|
|
case IRIX_SGI_GETPGID: {/* Get parent process GID: getpgid(2) */
|
|
|
|
struct sys_getpgid_args cup;
|
2001-12-27 12:31:09 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
SCARG(&cup, pid) = (pid_t)SCARG(uap, arg1);
|
|
|
|
return (sys_getpgid(l, &cup, retval));
|
2002-02-17 23:44:17 +03:00
|
|
|
break;
|
2001-12-27 12:31:09 +03:00
|
|
|
}
|
|
|
|
|
2002-03-25 23:42:50 +03:00
|
|
|
case IRIX_SGI_SETPGID: {/* Get parent process GID: setpgid(2) */
|
|
|
|
struct sys_setpgid_args cup;
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
SCARG(&cup, pid) = (pid_t)SCARG(uap, arg1);
|
|
|
|
SCARG(&cup, pgid) = (pid_t)SCARG(uap, arg2);
|
|
|
|
return (sys_setpgid(l, &cup, retval));
|
2002-03-25 23:42:50 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
case IRIX_SGI_PATHCONF: /* Get file limits: pathconf(3) */
|
2002-03-25 23:42:50 +03:00
|
|
|
return irix_syssgi_pathconf((char *)SCARG(uap, arg1),
|
2003-01-22 15:58:22 +03:00
|
|
|
(int)SCARG(uap, arg2), l, retval);
|
2002-03-25 23:42:50 +03:00
|
|
|
break;
|
|
|
|
|
2002-10-12 12:53:46 +04:00
|
|
|
case IRIX_SGI_RUSAGE: { /* BSD getrusage(2) */
|
|
|
|
struct sys_getrusage_args cup;
|
|
|
|
|
|
|
|
SCARG(&cup, who) = (int)SCARG(uap, arg1);
|
|
|
|
SCARG(&cup, rusage) = (struct rusage *)SCARG(uap, arg2);
|
2003-01-22 15:58:22 +03:00
|
|
|
return sys_getrusage(l, &cup, retval);
|
2002-10-12 12:53:46 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-10-14 02:13:47 +04:00
|
|
|
case IRIX_SGI_NUM_MODULES: /* <sys/systeminfo.h> get_num_modules() */
|
|
|
|
*retval = 1;
|
|
|
|
return 0;
|
|
|
|
break;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
2002-10-14 02:13:47 +04:00
|
|
|
case IRIX_SGI_MODULE_INFO: { /* <sys/systeminfo.h> get_module_info() */
|
|
|
|
int module_num = (int)SCARG(uap, arg1);
|
|
|
|
struct irix_module_info_s *imip = SCARG(uap, arg2);
|
|
|
|
int mss = (int)SCARG(uap, arg3);
|
|
|
|
struct irix_module_info_s imi;
|
|
|
|
char *idx;
|
|
|
|
|
|
|
|
if (module_num != 0)
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
imi.serial_num = (u_int64_t)hostid;
|
|
|
|
imi.mod_num = 0;
|
2005-02-27 01:58:54 +03:00
|
|
|
(void)snprintf(imi.serial_str, IRIX_MAX_SERIAL_SIZE,
|
2002-10-14 02:13:47 +04:00
|
|
|
"0800%08x", (u_int32_t)hostid);
|
|
|
|
|
|
|
|
/* Convert to upper case */
|
|
|
|
for (idx = imi.serial_str; *idx; idx++)
|
|
|
|
if (*idx >= 'a' && *idx <= 'f')
|
|
|
|
*idx += ('A' - 'a');
|
|
|
|
|
|
|
|
/* Don't copyout irrelevant data on user request */
|
|
|
|
if (mss > sizeof(struct irix_module_info_s))
|
|
|
|
mss = sizeof(struct irix_module_info_s);
|
|
|
|
|
|
|
|
return copyout(&imi, imip, mss);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-12-01 00:56:03 +03:00
|
|
|
case IRIX_SGI_RDNAME: { /* Read Processes' name */
|
|
|
|
struct proc *tp;
|
|
|
|
|
|
|
|
arg1 = SCARG(uap, arg1); /* PID of the process */
|
2001-12-27 12:31:09 +03:00
|
|
|
arg2 = SCARG(uap, arg2); /* Address of user buffer */
|
2001-12-01 00:56:03 +03:00
|
|
|
arg3 = SCARG(uap, arg3); /* Length of user buffer */
|
|
|
|
tp = pfind((pid_t)arg1);
|
|
|
|
if (tp == NULL || \
|
|
|
|
tp->p_psstr == NULL || \
|
|
|
|
tp->p_psstr->ps_argvstr == NULL || \
|
2005-02-27 01:58:54 +03:00
|
|
|
tp->p_psstr->ps_argvstr[0] == NULL)
|
2001-12-01 00:56:03 +03:00
|
|
|
return 0;
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
*retval = (register_t)copyout(tp->p_psstr->ps_argvstr[0],
|
2001-12-01 00:56:03 +03:00
|
|
|
(void *)arg2, (size_t)arg3);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IRIX_SGI_TUNE: /* Tune system variables */
|
|
|
|
case IRIX_SGI_IDBG: /* Kernel debugging */
|
|
|
|
case IRIX_SGI_INVENT: /* Get system inventory */
|
|
|
|
case IRIX_SGI_SETLED: /* Turn on/off LEDs */
|
|
|
|
case IRIX_SGI_SETNVRAM: /* Sets a NVRAM variable value */
|
|
|
|
case IRIX_SGI_GETNVRAM: /* Gets a NVRAM variable value */
|
|
|
|
return EINVAL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRIX_SGI_ELFMAP: /* Maps an ELF image */
|
|
|
|
arg1 = SCARG(uap, arg1); /* file descriptor */
|
|
|
|
arg2 = SCARG(uap, arg2); /* ptr to ELF program header array */
|
|
|
|
arg3 = SCARG(uap, arg3); /* array's length */
|
2005-02-27 01:58:54 +03:00
|
|
|
return irix_syssgi_mapelf((int)arg1, (Elf_Phdr *)arg2,
|
2005-12-11 15:16:03 +03:00
|
|
|
(int)arg3, l, retval);
|
2001-12-01 00:56:03 +03:00
|
|
|
break;
|
|
|
|
|
2001-12-02 12:22:39 +03:00
|
|
|
case IRIX_SGI_USE_FP_BCOPY: /* bcopy and bzero can use FPU or not */
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2001-12-02 12:22:39 +03:00
|
|
|
* Our kernel does not use FPU, hence we do nothing.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRIX_SGI_TOSSTSAVE: /* Kill saved pregions */
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2001-12-02 12:22:39 +03:00
|
|
|
* Our kernel does not seem to save such "pregions",
|
|
|
|
* therefore we do not have to do anything.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
|
2001-12-08 14:17:37 +03:00
|
|
|
case IRIX_SGI_SYSCONF: /* POSIX sysconf */
|
|
|
|
arg1 = SCARG(uap, arg1); /* system variable name */
|
2005-02-27 01:58:54 +03:00
|
|
|
return irix_syssgi_sysconf((int)arg1, l, retval);
|
2001-12-08 14:17:37 +03:00
|
|
|
break;
|
|
|
|
|
2002-04-20 11:43:35 +04:00
|
|
|
case IRIX_SGI_SATCTL: /* control audit stream */
|
2001-12-22 12:35:11 +03:00
|
|
|
case IRIX_SGI_RXEV_GET: /* Trusted IRIX call */
|
|
|
|
/* Undocumented (?) and unimplemented */
|
2002-01-22 00:51:31 +03:00
|
|
|
return 0;
|
2001-12-22 12:35:11 +03:00
|
|
|
break;
|
|
|
|
|
2002-03-13 23:33:41 +03:00
|
|
|
case IRIX_SGI_FDHI: /* getdtablehi(3): get higher open fd + 1 */
|
2002-03-13 10:54:18 +03:00
|
|
|
*retval = (register_t)(p->p_fd->fd_lastfile + 1);
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
2001-12-01 00:56:03 +03:00
|
|
|
default:
|
|
|
|
printf("Warning: call to unimplemented syssgi() command %d\n",
|
|
|
|
request);
|
|
|
|
return EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-11-28 15:00:53 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2001-12-01 00:56:03 +03:00
|
|
|
|
|
|
|
static int
|
2007-12-08 21:35:53 +03:00
|
|
|
irix_syssgi_mapelf(int fd, Elf_Phdr *ph, int count, struct lwp *l, register_t *retval)
|
2001-12-01 00:56:03 +03:00
|
|
|
{
|
|
|
|
Elf_Phdr *kph;
|
|
|
|
Elf_Phdr *pht;
|
|
|
|
int error = 0;
|
|
|
|
int i,j;
|
|
|
|
int prot;
|
|
|
|
int flags;
|
|
|
|
u_long size;
|
2001-12-27 01:18:25 +03:00
|
|
|
Elf_Addr uaddr;
|
2002-02-03 20:28:19 +03:00
|
|
|
Elf_Addr reloc_offset;
|
2008-03-22 00:54:58 +03:00
|
|
|
file_t *fp;
|
2001-12-01 00:56:03 +03:00
|
|
|
struct exec_vmcmd_set vcset;
|
|
|
|
struct exec_vmcmd *base_vcp = NULL;
|
|
|
|
struct vnode *vp;
|
2002-01-19 17:56:02 +03:00
|
|
|
struct vm_map_entry *ret;
|
|
|
|
struct exec_vmcmd *vcp;
|
2002-02-03 20:28:19 +03:00
|
|
|
int need_relocation;
|
2001-12-01 00:56:03 +03:00
|
|
|
|
2001-12-27 01:18:25 +03:00
|
|
|
vcset.evs_cnt = 0;
|
|
|
|
vcset.evs_used = 0;
|
|
|
|
|
2003-11-13 06:09:28 +03:00
|
|
|
kph = (Elf_Phdr *)malloc(sizeof(Elf_Phdr) * count, M_TEMP, M_WAITOK);
|
2001-12-01 00:56:03 +03:00
|
|
|
error = copyin(ph, kph, sizeof(Elf_Phdr) * count);
|
|
|
|
if (error)
|
|
|
|
goto bad;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
2001-12-01 00:56:03 +03:00
|
|
|
pht = kph;
|
2002-02-03 20:28:19 +03:00
|
|
|
need_relocation = 0;
|
2001-12-01 00:56:03 +03:00
|
|
|
for (i = 0; i < count; i++) {
|
2002-02-03 20:28:19 +03:00
|
|
|
/* Check that each ELF sections is loadable */
|
2001-12-01 00:56:03 +03:00
|
|
|
if (pht->p_type != PT_LOAD) {
|
|
|
|
error = ENOEXEC;
|
|
|
|
goto bad;
|
|
|
|
}
|
2002-02-03 20:28:19 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2002-02-03 20:28:19 +03:00
|
|
|
* Check that the section load addresses are increasing
|
2005-02-27 01:58:54 +03:00
|
|
|
* with the section in the program header array. We do
|
2002-02-03 20:28:19 +03:00
|
|
|
* not support any other situation.
|
|
|
|
*/
|
|
|
|
if (pht->p_vaddr < kph->p_vaddr) {
|
|
|
|
#ifdef DEBUG_IRIX
|
|
|
|
printf("mapelf: unsupported psection order\n");
|
2002-01-22 00:51:31 +03:00
|
|
|
#endif
|
2002-02-03 20:28:19 +03:00
|
|
|
error = EINVAL;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2002-02-03 20:28:19 +03:00
|
|
|
* Check that the default load addresses are free.
|
|
|
|
* If not, we will have to perform a relocation
|
|
|
|
*/
|
2005-12-11 15:16:03 +03:00
|
|
|
ret = uvm_map_findspace(&l->l_proc->p_vmspace->vm_map,
|
2003-07-29 20:18:54 +04:00
|
|
|
pht->p_vaddr, pht->p_memsz, (vaddr_t *)(void *)&uaddr,
|
2002-02-03 20:28:19 +03:00
|
|
|
NULL, 0, 0, UVM_FLAG_FIXED);
|
|
|
|
if (ret == NULL)
|
|
|
|
need_relocation = 1;
|
2001-12-01 00:56:03 +03:00
|
|
|
pht++;
|
|
|
|
}
|
|
|
|
|
2002-02-03 20:28:19 +03:00
|
|
|
/*
|
|
|
|
* Perform a relocation
|
|
|
|
*/
|
2005-02-27 01:58:54 +03:00
|
|
|
if (need_relocation) {
|
|
|
|
/*
|
2002-02-03 20:28:19 +03:00
|
|
|
* compute the size needed by the section union. This
|
|
|
|
* assumes that the section load addresses are increasing.
|
|
|
|
* (And also that the sections are not overlapping)
|
|
|
|
*/
|
|
|
|
pht--;
|
2002-03-10 22:03:08 +03:00
|
|
|
size = ELF_ROUND((pht->p_vaddr + pht->p_memsz), pht->p_align) -
|
|
|
|
ELF_TRUNC(kph->p_vaddr, kph->p_align);
|
2002-02-03 20:28:19 +03:00
|
|
|
|
|
|
|
/* Find a free place for the sections */
|
2005-12-11 15:16:03 +03:00
|
|
|
ret = uvm_map_findspace(&l->l_proc->p_vmspace->vm_map,
|
2003-07-29 20:18:54 +04:00
|
|
|
IRIX_MAPELF_RELOCATE, size, (vaddr_t *)(void *)&uaddr,
|
2002-02-03 20:28:19 +03:00
|
|
|
NULL, 0, kph->p_align, 0);
|
|
|
|
|
|
|
|
if (ret == NULL) {
|
|
|
|
error = ENOMEM;
|
|
|
|
goto bad;
|
|
|
|
}
|
2005-02-27 01:58:54 +03:00
|
|
|
|
|
|
|
/*
|
2002-02-03 20:28:19 +03:00
|
|
|
* Relocate the sections, all with the same offset.
|
|
|
|
*/
|
|
|
|
reloc_offset = uaddr - kph->p_vaddr;
|
|
|
|
pht = kph;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
#ifdef DEBUG_IRIX
|
|
|
|
printf("mapelf: relocating section %d from %p to %p\n",
|
2005-02-27 01:58:54 +03:00
|
|
|
i, (void *)pht->p_vaddr,
|
2002-02-03 20:28:19 +03:00
|
|
|
(void *)(pht->p_vaddr + reloc_offset));
|
|
|
|
#endif
|
|
|
|
pht->p_vaddr += reloc_offset;
|
|
|
|
pht++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-01 00:56:03 +03:00
|
|
|
/* Find the file's vnode */
|
2008-03-22 00:54:58 +03:00
|
|
|
fp = fd_getfile(fd);
|
2001-12-01 00:56:03 +03:00
|
|
|
if (fp == NULL) {
|
|
|
|
error = EBADF;
|
|
|
|
goto bad;
|
|
|
|
}
|
2008-03-22 00:54:58 +03:00
|
|
|
vp = fp->f_data;
|
2001-12-01 00:56:03 +03:00
|
|
|
|
2003-02-28 05:12:55 +03:00
|
|
|
error = vn_marktext(vp);
|
|
|
|
if (error)
|
|
|
|
goto bad_unuse;
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
|
|
|
* Load the sections
|
2002-02-03 20:28:19 +03:00
|
|
|
*/
|
2001-12-01 00:56:03 +03:00
|
|
|
pht = kph;
|
|
|
|
for (i = 0; i < count; i++) {
|
2002-02-03 20:28:19 +03:00
|
|
|
#ifdef DEBUG_IRIX
|
2005-02-27 01:58:54 +03:00
|
|
|
printf("mapelf: loading section %d (len 0x%08lx) at %p\n",
|
2002-02-03 20:28:19 +03:00
|
|
|
i, (long)pht->p_memsz, (void *)pht->p_vaddr);
|
2002-01-22 00:51:31 +03:00
|
|
|
#endif
|
2002-02-03 20:28:19 +03:00
|
|
|
/* Build the vmcmds for loading the section */
|
2002-01-22 00:51:31 +03:00
|
|
|
kill_vmcmds(&vcset);
|
2002-02-02 22:27:18 +03:00
|
|
|
uaddr = pht->p_vaddr;
|
2001-12-27 01:18:25 +03:00
|
|
|
size = 0;
|
|
|
|
prot = 0;
|
|
|
|
flags = VMCMD_BASE;
|
2001-12-01 00:56:03 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
ELFNAME(load_psection)(&vcset, vp, pht, &uaddr,
|
2001-12-27 01:18:25 +03:00
|
|
|
&size, &prot, flags);
|
2001-12-01 00:56:03 +03:00
|
|
|
|
2002-02-03 20:28:19 +03:00
|
|
|
/* Execute the vmcmds */
|
2002-01-22 00:51:31 +03:00
|
|
|
for (j = 0; j < vcset.evs_used && !error; j++) {
|
|
|
|
vcp = &vcset.evs_cmds[j];
|
|
|
|
if (vcp->ev_flags & VMCMD_RELATIVE) {
|
|
|
|
if (base_vcp == NULL)
|
2002-09-27 19:35:29 +04:00
|
|
|
panic("irix_syssgi_mapelf(): bad vmcmd base");
|
2005-02-27 01:58:54 +03:00
|
|
|
|
2002-01-22 00:51:31 +03:00
|
|
|
vcp->ev_addr += base_vcp->ev_addr;
|
|
|
|
}
|
2005-12-11 15:16:03 +03:00
|
|
|
IRIX_VM_SYNC(l->l_proc, error = (*vcp->ev_proc)(l, vcp));
|
- Introduce a e_fault field in struct proc to provide emulation specific
memory fault handler. IRIX uses irix_vm_fault, and all other emulation
use NULL, which means to use uvm_fault.
- While we are there, explicitely set to NULL the uninitialized fields in
struct emul: e_fault and e_sysctl on most ports
- e_fault is used by the trap handler, for now only on mips. In order to avoid
intrusive modifications in UVM, the function pointed by e_fault does not
has exactly the same protoype as uvm_fault:
int uvm_fault __P((struct vm_map *, vaddr_t, vm_fault_t, vm_prot_t));
int e_fault __P((struct proc *, vaddr_t, vm_fault_t, vm_prot_t));
- In IRIX share groups, all the VM space is shared, except one page.
This bounds us to have different VM spaces and synchronize modifications
to the VM space accross share group members. We need an IRIX specific hook
to the page fault handler in order to propagate VM space modifications
caused by page faults.
2002-09-22 01:14:54 +04:00
|
|
|
if (error)
|
2003-02-28 05:12:55 +03:00
|
|
|
goto bad_unuse;
|
2002-01-19 17:56:02 +03:00
|
|
|
}
|
|
|
|
pht++;
|
2001-12-01 00:56:03 +03:00
|
|
|
}
|
|
|
|
|
2002-01-22 00:51:31 +03:00
|
|
|
*retval = (register_t)kph->p_vaddr;
|
2003-02-28 05:12:55 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
bad_unuse:
|
2008-03-22 00:54:58 +03:00
|
|
|
fd_putfile(fd);
|
2001-12-01 00:56:03 +03:00
|
|
|
bad:
|
|
|
|
free(kph, M_TEMP);
|
|
|
|
return error;
|
|
|
|
}
|
2001-12-08 14:17:37 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2007-12-08 21:35:53 +03:00
|
|
|
irix_syssgi_sysconf(int name, struct lwp *l, register_t *retval)
|
2001-12-08 14:17:37 +03:00
|
|
|
{
|
2003-01-22 15:58:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
2001-12-08 14:17:37 +03:00
|
|
|
int error = 0;
|
|
|
|
int mib[2], value;
|
2004-03-09 06:18:03 +03:00
|
|
|
size_t len = sizeof(value);
|
2001-12-08 14:17:37 +03:00
|
|
|
|
|
|
|
switch (name) {
|
2001-12-08 22:29:03 +03:00
|
|
|
case IRIX_SC_ARG_MAX:
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_ARGMAX;
|
|
|
|
break;
|
|
|
|
case IRIX_SC_CHILD_MAX:
|
2002-02-24 01:35:15 +03:00
|
|
|
*retval = (register_t)p->p_rlimit[RLIMIT_NPROC].rlim_cur;
|
|
|
|
return 0;
|
2001-12-08 22:29:03 +03:00
|
|
|
break;
|
2001-12-08 14:17:37 +03:00
|
|
|
case IRIX_SC_CLK_TCK:
|
|
|
|
*retval = hz;
|
|
|
|
return 0;
|
|
|
|
break;
|
2001-12-08 22:29:03 +03:00
|
|
|
case IRIX_SC_NGROUPS_MAX:
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_NGROUPS;
|
|
|
|
break;
|
|
|
|
case IRIX_SC_OPEN_MAX:
|
2002-02-24 01:35:15 +03:00
|
|
|
*retval = (register_t)p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
|
|
|
|
return 0;
|
2001-12-08 22:29:03 +03:00
|
|
|
break;
|
|
|
|
case IRIX_SC_JOB_CONTROL:
|
2002-02-24 01:35:15 +03:00
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_JOB_CONTROL;
|
2001-12-08 22:29:03 +03:00
|
|
|
break;
|
|
|
|
case IRIX_SC_SAVED_IDS:
|
2002-02-24 01:35:15 +03:00
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_SAVED_IDS;
|
2001-12-08 22:29:03 +03:00
|
|
|
break;
|
2002-04-17 00:15:03 +04:00
|
|
|
case IRIX_SC_IP_SECOPTS:/* IP security options */
|
2001-12-22 12:35:11 +03:00
|
|
|
/* Trusted IRIX capabilities are unsupported */
|
|
|
|
case IRIX_SC_ACL: /* ACcess Lists */
|
|
|
|
case IRIX_SC_AUDIT: /* Audit */
|
|
|
|
case IRIX_SC_INF: /* Information labels */
|
|
|
|
case IRIX_SC_MAC: /* Mandatory Access Control */
|
|
|
|
case IRIX_SC_CAP: /* Capabilities */
|
|
|
|
*retval = 0;
|
|
|
|
return 0;
|
|
|
|
break;
|
2001-12-08 14:17:37 +03:00
|
|
|
case IRIX_SC_PAGESIZE:
|
|
|
|
mib[0] = CTL_HW;
|
|
|
|
mib[1] = HW_PAGESIZE;
|
|
|
|
break;
|
|
|
|
|
2001-12-08 22:29:03 +03:00
|
|
|
case IRIX_SC_PASS_MAX:
|
|
|
|
case IRIX_SC_VERSION:
|
2001-12-08 14:17:37 +03:00
|
|
|
default:
|
|
|
|
printf("Warning: syssgi(SYSCONF) unsupported variable %d\n",
|
|
|
|
name);
|
2002-05-29 01:15:41 +04:00
|
|
|
return EINVAL;
|
2001-12-08 14:17:37 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-03-09 06:18:03 +03:00
|
|
|
/*
|
|
|
|
* calling into sysctl with superuser privs, but we don't mind
|
|
|
|
* 'cause we're only querying a value.
|
|
|
|
*/
|
|
|
|
error = old_sysctl(&mib[0], 2, &value, &len, NULL, 0, NULL);
|
|
|
|
if (error == 0)
|
|
|
|
*retval = value;
|
|
|
|
return (error);
|
2001-12-08 14:17:37 +03:00
|
|
|
}
|
2002-03-25 23:42:50 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
static int
|
2007-12-08 21:35:53 +03:00
|
|
|
irix_syssgi_pathconf(char *path, int name, struct lwp *l, register_t *retval)
|
2002-03-25 23:42:50 +03:00
|
|
|
{
|
|
|
|
struct sys_pathconf_args cup;
|
|
|
|
int bname;
|
|
|
|
|
|
|
|
switch (name) {
|
|
|
|
case IRIX_PC_LINK_MAX:
|
|
|
|
case IRIX_PC_MAX_CANON:
|
|
|
|
case IRIX_PC_MAX_INPUT:
|
|
|
|
case IRIX_PC_NAME_MAX:
|
|
|
|
case IRIX_PC_PATH_MAX:
|
|
|
|
case IRIX_PC_PIPE_BUF:
|
|
|
|
case IRIX_PC_CHOWN_RESTRICTED:
|
|
|
|
case IRIX_PC_NO_TRUNC:
|
|
|
|
case IRIX_PC_VDISABLE:
|
|
|
|
case IRIX_PC_SYNC_IO:
|
|
|
|
bname = name;
|
|
|
|
break;
|
|
|
|
case IRIX_PC_FILESIZEBITS:
|
|
|
|
bname = _PC_FILESIZEBITS;
|
|
|
|
break;
|
|
|
|
case IRIX_PC_PRIO_IO:
|
|
|
|
case IRIX_PC_ASYNC_IO:
|
|
|
|
case IRIX_PC_ABI_ASYNC_IO:
|
|
|
|
case IRIX_PC_ABI_AIO_XFER_MAX:
|
|
|
|
default:
|
|
|
|
printf("Warning: unimplemented IRIX pathconf() command %d\n",
|
|
|
|
name);
|
|
|
|
*retval = 0;
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SCARG(&cup, path) = path;
|
|
|
|
SCARG(&cup, name) = bname;
|
2003-01-22 15:58:22 +03:00
|
|
|
return sys_pathconf(l, &cup, retval);
|
2002-03-25 23:42:50 +03:00
|
|
|
}
|