1 /* $NetBSD: irix_exec.c,v 1.55 2009/12/10 14:13:53 matt Exp $ */
4 * Copyright (c) 2001-2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: irix_exec.c,v 1.55 2009/12/10 14:13:53 matt Exp $");
36 #include "opt_syscall_debug.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
42 #include <sys/rwlock.h>
44 #include <sys/types.h>
45 #include <sys/malloc.h>
47 #include <machine/regnum.h>
48 #include <uvm/uvm_extern.h>
50 #include <compat/irix/irix_syscall.h>
51 #include <compat/irix/irix_types.h>
52 #include <compat/irix/irix_exec.h>
53 #include <compat/irix/irix_prctl.h>
54 #include <compat/irix/irix_signal.h>
55 #include <compat/irix/irix_errno.h>
56 #include <compat/irix/irix_sysctl.h>
57 #include <compat/irix/irix_usema.h>
59 extern const int native_to_svr4_signo
[];
61 static void irix_e_proc_exec(struct proc
*, struct exec_package
*);
62 static void irix_e_proc_fork(struct proc
*, struct proc
*, int);
63 static void irix_e_proc_exit(struct proc
*);
64 static void irix_e_proc_init(struct proc
*, struct vmspace
*);
66 extern struct sysent irix_sysent
[];
67 extern const char * const irix_syscallnames
[];
69 #ifndef __HAVE_SYSCALL_INTERN
70 void irix_syscall(void);
72 void irix_syscall_intern(struct proc
*);
76 * Fake sigcode. COMPAT_IRIX does not use it, since the
77 * signal trampoline is provided by libc. However, some
78 * other part of the kernel will be happier if we still
79 * provide non NULL sigcode and esigcode.
81 char irix_sigcode
[] = { 0 };
83 struct emul emul_irix
= {
86 #ifndef __HAVE_MINIMAL_EMUL
110 #ifdef __HAVE_SYSCALL_INTERN
122 * set registers on exec for N32 applications
125 irix_n32_setregs(struct lwp
*l
, struct exec_package
*pack
, vaddr_t stack
)
127 struct frame
*f
= l
->l_md
.md_regs
;
129 /* Enable 64 bit instructions (eg: sd) */
130 f
->f_regs
[_R_SR
] |= MIPS3_SR_UX
| MIPS3_SR_FR
;
132 f
->f_regs
[_R_SR
] |= MIPS3_SR_KX
;
137 * per-process emuldata allocation
140 irix_e_proc_init(struct proc
*p
, struct vmspace
*vmspace
)
142 struct irix_emuldata
*ied
;
147 p
->p_emuldata
= malloc(sizeof(struct irix_emuldata
),
148 M_EMULDATA
, M_WAITOK
| M_ZERO
);
153 LIST_INIT(&ied
->ied_shared_regions
);
154 vm_min
= vm_map_min(&vmspace
->vm_map
);
155 vm_len
= vm_map_max(&vmspace
->vm_map
) - vm_min
;
156 irix_isrr_insert(vm_min
, vm_len
, IRIX_ISRR_SHARED
, p
);
160 * exec() hook used to allocate per process structures
163 irix_e_proc_exec(struct proc
*p
, struct exec_package
*epp
)
167 irix_e_proc_init(p
, p
->p_vmspace
);
169 /* Initialize the process private area (PRDA) */
170 error
= irix_prda_init(p
);
173 printf("irix_e_proc_exec(): PRDA map failed ");
178 * exit() hook used to free per process data structures
181 irix_e_proc_exit(struct proc
*p
)
184 struct irix_emuldata
*ied
;
185 struct irix_share_group
*isg
;
186 struct irix_shared_regions_rec
*isrr
;
189 * Send SIGHUP to child process as requested using prctl(2)
191 mutex_enter(proc_lock
);
192 PROCLIST_FOREACH(pp
, &allproc
) {
193 if ((pp
->p_flag
& PK_MARKER
) != 0)
195 /* Select IRIX processes */
196 if (irix_check_exec(pp
) == 0)
199 ied
= (struct irix_emuldata
*)(pp
->p_emuldata
);
200 if (ied
->ied_termchild
&& pp
->p_pptr
== p
)
201 psignal(pp
, native_to_svr4_signo
[SIGHUP
]);
203 mutex_exit(proc_lock
);
206 * Remove the process from share group processes list, if relevant.
208 ied
= (struct irix_emuldata
*)(p
->p_emuldata
);
210 if ((isg
= ied
->ied_share_group
) != NULL
) {
211 rw_enter(&isg
->isg_lock
, RW_WRITER
);
212 LIST_REMOVE(ied
, ied_sglist
);
215 if (isg
->isg_refcount
== 0) {
217 * This was the last process in the share group.
218 * Call irix_usema_exit_cleanup() to free in-kernel
219 * structures hold by the share group through
220 * the irix_usync_cntl system call.
222 irix_usema_exit_cleanup(p
, NULL
);
224 * Free the share group structure (no need to free
225 * the lock since we destroy it now).
227 rw_destroy(&isg
->isg_lock
);
228 free(isg
, M_EMULDATA
);
229 ied
->ied_share_group
= NULL
;
232 * There are other processes remaining in the share
233 * group. Call irix_usema_exit_cleanup() to set the
234 * first of them as the owner of the structures
235 * hold in the kernel by the share group.
237 irix_usema_exit_cleanup(p
,
238 LIST_FIRST(&isg
->isg_head
)->ied_p
);
239 rw_exit(&isg
->isg_lock
);
244 * The process is not part of a share group. Call
245 * irix_usema_exit_cleanup() to free in-kernel structures hold
246 * by the process through the irix_usync_cntl system call.
248 irix_usema_exit_cleanup(p
, NULL
);
251 /* Free (un)shared region list */
252 while (!LIST_EMPTY(&ied
->ied_shared_regions
)) {
253 isrr
= LIST_FIRST(&ied
->ied_shared_regions
);
254 LIST_REMOVE(isrr
, isrr_list
);
255 free(isrr
, M_EMULDATA
);
258 free(p
->p_emuldata
, M_EMULDATA
);
259 p
->p_emuldata
= NULL
;
263 * fork() hook used to allocate per process structures
266 irix_e_proc_fork(struct proc
*p
, struct proc
*parent
, int forkflags
)
268 struct irix_emuldata
*ied1
;
269 struct irix_emuldata
*ied2
;
271 p
->p_emuldata
= NULL
;
273 /* Use parent's vmspace because our vmspace may not be setup yet */
274 irix_e_proc_init(p
, parent
->p_vmspace
);
276 ied1
= p
->p_emuldata
;
277 ied2
= parent
->p_emuldata
;
279 (void) memcpy(ied1
, ied2
, (unsigned)
280 ((char *)&ied1
->ied_endcopy
- (char *)&ied1
->ied_startcopy
));