1139790Simp/*-
243412Snewton * Copyright (c) 1998 Mark Newton
343412Snewton * Copyright (c) 1994 Christos Zoulas
443412Snewton * All rights reserved.
543412Snewton *
643412Snewton * Redistribution and use in source and binary forms, with or without
743412Snewton * modification, are permitted provided that the following conditions
843412Snewton * are met:
943412Snewton * 1. Redistributions of source code must retain the above copyright
1043412Snewton *    notice, this list of conditions and the following disclaimer.
1143412Snewton * 2. Redistributions in binary form must reproduce the above copyright
1243412Snewton *    notice, this list of conditions and the following disclaimer in the
1343412Snewton *    documentation and/or other materials provided with the distribution.
1443412Snewton * 3. The name of the author may not be used to endorse or promote products
1543412Snewton *    derived from this software without specific prior written permission
1643412Snewton *
1743412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1843412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1943412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2043412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2143412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2243412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2343412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2443412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2643412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2743412Snewton */
2843412Snewton
29116145Sobrien#include <sys/cdefs.h>
30116145Sobrien__FBSDID("$FreeBSD$");
31116145Sobrien
3243412Snewton#include <sys/types.h>
3343412Snewton#include <sys/param.h>
3443412Snewton#include <sys/systm.h>
3543412Snewton#include <sys/exec.h>
3676166Smarkm#include <sys/filedesc.h>
3743412Snewton#include <sys/lock.h>
3876166Smarkm#include <sys/mutex.h>
3976166Smarkm#include <sys/proc.h>
4043412Snewton#include <sys/signal.h>
4143412Snewton#include <sys/signalvar.h>
4243412Snewton
4343412Snewton#include <machine/cpu.h>
4443412Snewton#include <machine/cpufunc.h>
4543412Snewton#include <machine/psl.h>
4643412Snewton#include <machine/reg.h>
4743412Snewton#include <machine/specialreg.h>
4843412Snewton#include <machine/sysarch.h>
4943412Snewton#include <machine/vm86.h>
5043412Snewton#include <machine/vmparam.h>
5143412Snewton
5276166Smarkm#include <vm/vm.h>
5376166Smarkm#include <vm/pmap.h>
5476166Smarkm
5565302Sobrien#include <compat/svr4/svr4.h>
5665302Sobrien#include <compat/svr4/svr4_types.h>
5765302Sobrien#include <compat/svr4/svr4_signal.h>
5843412Snewton#include <i386/svr4/svr4_machdep.h>
5965302Sobrien#include <compat/svr4/svr4_ucontext.h>
6065302Sobrien#include <compat/svr4/svr4_proto.h>
6165302Sobrien#include <compat/svr4/svr4_util.h>
6243412Snewton
6343412Snewton#undef sigcode
6443412Snewton#undef szsigcode
6543412Snewton
6643412Snewtonextern int svr4_szsigcode;
6743412Snewtonextern char svr4_sigcode[];
6843412Snewton
6992765Salfredstatic void svr4_getsiginfo(union svr4_siginfo *, int, u_long, caddr_t);
7043412Snewton
7143412Snewton#if !defined(__NetBSD__)
7243412Snewton  /* taken from /sys/arch/i386/include/psl.h on NetBSD-1.3 */
7343412Snewton# define PSL_MBZ 0xffc08028
7443412Snewton# define PSL_USERSTATIC (PSL_USER | PSL_MBZ | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP)
7543412Snewton# define USERMODE(c, f) (ISPL(c) == SEL_UPL)
7643412Snewton#endif
7743412Snewton
7843412Snewton#if defined(__NetBSD__)
7943412Snewtonvoid
8083366Sjuliansvr4_setregs(td, epp, stack)
8183366Sjulian	struct thread *td;
8243412Snewton	struct exec_package *epp;
8343412Snewton	u_long stack;
8443412Snewton{
8583366Sjulian	register struct pcb *pcb = td->td_pcb;
8643412Snewton
8743412Snewton	pcb->pcb_savefpu.sv_env.en_cw = __SVR4_NPXCW__;
8883366Sjulian	setregs(td, epp, stack, 0UL);
8943412Snewton}
9043412Snewton#endif /* __NetBSD__ */
9143412Snewton
9243412Snewtonvoid
9383366Sjuliansvr4_getcontext(td, uc, mask, oonstack)
9483366Sjulian	struct thread *td;
9543412Snewton	struct svr4_ucontext *uc;
9651793Smarcel	sigset_t *mask;
9751793Smarcel	int oonstack;
9843412Snewton{
9983366Sjulian	struct proc *p = td->td_proc;
10083366Sjulian	struct trapframe *tf = td->td_frame;
10143412Snewton	svr4_greg_t *r = uc->uc_mcontext.greg;
10243412Snewton	struct svr4_sigaltstack *s = &uc->uc_stack;
10356044Snewton#if defined(DONE_MORE_SIGALTSTACK_WORK)
10471495Sjhb	struct sigacts *psp;
10571495Sjhb	struct sigaltstack *sf;
10649270Snewton#endif
10743412Snewton
10883641Sjhb	PROC_LOCK(p);
10971495Sjhb#if defined(DONE_MORE_SIGALTSTACK_WORK)
11071495Sjhb	psp = p->p_sigacts;
11171495Sjhb	sf = &p->p_sigstk;
11271495Sjhb#endif
11371495Sjhb
11443412Snewton	memset(uc, 0, sizeof(struct svr4_ucontext));
11543412Snewton
11644270Snewton	uc->uc_link = p->p_emuldata;
11743412Snewton	/*
11843412Snewton	 * Set the general purpose registers
11943412Snewton	 */
12047694Snewton#ifdef VM86
12143412Snewton	if (tf->tf_eflags & PSL_VM) {
12243412Snewton		r[SVR4_X86_GS] = tf->tf_vm86_gs;
12343412Snewton		r[SVR4_X86_FS] = tf->tf_vm86_fs;
12443412Snewton		r[SVR4_X86_ES] = tf->tf_vm86_es;
12543412Snewton		r[SVR4_X86_DS] = tf->tf_vm86_ds;
12683366Sjulian		r[SVR4_X86_EFL] = get_vflags(td);
12743412Snewton	} else
12847694Snewton#endif
12943412Snewton	{
13046129Sluoqi#if defined(__NetBSD__)
13143412Snewton	        __asm("movl %%gs,%w0" : "=r" (r[SVR4_X86_GS]));
13243412Snewton		__asm("movl %%fs,%w0" : "=r" (r[SVR4_X86_FS]));
13346129Sluoqi#else
13446129Sluoqi	        r[SVR4_X86_GS] = rgs();
13546129Sluoqi		r[SVR4_X86_FS] = tf->tf_fs;
13646129Sluoqi#endif
13743412Snewton		r[SVR4_X86_ES] = tf->tf_es;
13843412Snewton		r[SVR4_X86_DS] = tf->tf_ds;
13943412Snewton		r[SVR4_X86_EFL] = tf->tf_eflags;
14043412Snewton	}
14143412Snewton	r[SVR4_X86_EDI] = tf->tf_edi;
14243412Snewton	r[SVR4_X86_ESI] = tf->tf_esi;
14343412Snewton	r[SVR4_X86_EBP] = tf->tf_ebp;
14443412Snewton	r[SVR4_X86_ESP] = tf->tf_esp;
14543412Snewton	r[SVR4_X86_EBX] = tf->tf_ebx;
14643412Snewton	r[SVR4_X86_EDX] = tf->tf_edx;
14743412Snewton	r[SVR4_X86_ECX] = tf->tf_ecx;
14843412Snewton	r[SVR4_X86_EAX] = tf->tf_eax;
14944270Snewton	r[SVR4_X86_TRAPNO] = tf->tf_trapno;
15044270Snewton	r[SVR4_X86_ERR] = tf->tf_err;
15143412Snewton	r[SVR4_X86_EIP] = tf->tf_eip;
15243412Snewton	r[SVR4_X86_CS] = tf->tf_cs;
15343412Snewton	r[SVR4_X86_UESP] = 0;
15443412Snewton	r[SVR4_X86_SS] = tf->tf_ss;
15543412Snewton
15643412Snewton	/*
15743412Snewton	 * Set the signal stack
15843412Snewton	 */
15956044Snewton#if defined(DONE_MORE_SIGALTSTACK_WORK)
16043412Snewton	bsd_to_svr4_sigaltstack(sf, s);
16144270Snewton#else
162298433Spfg	s->ss_sp = (void *)rounddown2((u_long)tf->tf_esp, 16384);
16344270Snewton	s->ss_size = 16384;
16444270Snewton	s->ss_flags = 0;
16544270Snewton#endif
16683641Sjhb	PROC_UNLOCK(p);
16743412Snewton
16843412Snewton	/*
16943412Snewton	 * Set the signal mask
17043412Snewton	 */
17151793Smarcel	bsd_to_svr4_sigset(mask, &uc->uc_sigmask);
17243412Snewton
17343412Snewton	/*
17443412Snewton	 * Set the flags
17543412Snewton	 */
17656044Snewton	uc->uc_flags = SVR4_UC_SIGMASK|SVR4_UC_CPU|SVR4_UC_STACK;
17743412Snewton}
17843412Snewton
17943412Snewton
18043412Snewton/*
18156044Snewton * Set to ucontext specified. Reset signal mask and
18243412Snewton * stack state from context.
18343412Snewton * Return to previous pc and psl as specified by
18443412Snewton * context left by sendsig. Check carefully to
18543412Snewton * make sure that the user has not modified the
18643412Snewton * psl to gain improper privileges or to cause
18743412Snewton * a machine fault.
18843412Snewton */
18943412Snewtonint
19083366Sjuliansvr4_setcontext(td, uc)
19183366Sjulian	struct thread *td;
19243412Snewton	struct svr4_ucontext *uc;
19343412Snewton{
19456044Snewton#if defined(DONE_MORE_SIGALTSTACK_WORK)
19571495Sjhb	struct sigacts *psp;
19656044Snewton#endif
19783366Sjulian	struct proc *p = td->td_proc;
19843412Snewton	register struct trapframe *tf;
19943412Snewton	svr4_greg_t *r = uc->uc_mcontext.greg;
20043412Snewton	struct svr4_sigaltstack *s = &uc->uc_stack;
20171495Sjhb	struct sigaltstack *sf;
20251793Smarcel	sigset_t mask;
20343412Snewton
20483641Sjhb	PROC_LOCK(p);
20571495Sjhb#if defined(DONE_MORE_SIGALTSTACK_WORK)
20683641Sjhb	psp = p->p_sigacts;
20771495Sjhb#endif
208124141Sobrien	sf = &td->td_sigstk;
20971495Sjhb
21043412Snewton	/*
21143412Snewton	 * XXX:
21243412Snewton	 * Should we check the value of flags to determine what to restore?
21343412Snewton	 * What to do with uc_link?
21443412Snewton	 * What to do with floating point stuff?
21543412Snewton	 * Should we bother with the rest of the registers that we
21643412Snewton	 * set to 0 right now?
21743412Snewton	 */
21843412Snewton
219113623Sjhb	if ((uc->uc_flags & SVR4_UC_CPU) == 0) {
220113623Sjhb		PROC_UNLOCK(p);
22144270Snewton		return 0;
222113623Sjhb	}
22344270Snewton
22456044Snewton	DPRINTF(("svr4_setcontext(%d)\n", p->p_pid));
22556044Snewton
22683366Sjulian	tf = td->td_frame;
22743412Snewton
22843412Snewton	/*
22943412Snewton	 * Restore register context.
23043412Snewton	 */
23147694Snewton#ifdef VM86
23256044Snewton#warning "VM86 doesn't work yet, please don't try to use it."
23343412Snewton	if (r[SVR4_X86_EFL] & PSL_VM) {
23443412Snewton		tf->tf_vm86_gs = r[SVR4_X86_GS];
23543412Snewton		tf->tf_vm86_fs = r[SVR4_X86_FS];
23643412Snewton		tf->tf_vm86_es = r[SVR4_X86_ES];
23743412Snewton		tf->tf_vm86_ds = r[SVR4_X86_DS];
23883366Sjulian		set_vflags(td, r[SVR4_X86_EFL]);
23943412Snewton	} else
24047694Snewton#endif
24143412Snewton	{
24243412Snewton		/*
24343412Snewton		 * Check for security violations.  If we're returning to
24443412Snewton		 * protected mode, the CPU will validate the segment registers
24543412Snewton		 * automatically and generate a trap on violations.  We handle
24643412Snewton		 * the trap, rather than doing all of the checking here.
24743412Snewton		 */
24843412Snewton		if (((r[SVR4_X86_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
249113623Sjhb		    !USERMODE(r[SVR4_X86_CS], r[SVR4_X86_EFL])) {
250113623Sjhb			PROC_UNLOCK(p);
25143412Snewton			return (EINVAL);
252113623Sjhb		}
25343412Snewton
25446129Sluoqi#if defined(__NetBSD__)
25543412Snewton		/* %fs and %gs were restored by the trampoline. */
25646129Sluoqi#else
25746129Sluoqi		/* %gs was restored by the trampoline. */
25846129Sluoqi		tf->tf_fs = r[SVR4_X86_FS];
25946129Sluoqi#endif
26043412Snewton		tf->tf_es = r[SVR4_X86_ES];
26143412Snewton		tf->tf_ds = r[SVR4_X86_DS];
26243412Snewton		tf->tf_eflags = r[SVR4_X86_EFL];
26343412Snewton	}
26443412Snewton	tf->tf_edi = r[SVR4_X86_EDI];
26543412Snewton	tf->tf_esi = r[SVR4_X86_ESI];
26643412Snewton	tf->tf_ebp = r[SVR4_X86_EBP];
26743412Snewton	tf->tf_ebx = r[SVR4_X86_EBX];
26843412Snewton	tf->tf_edx = r[SVR4_X86_EDX];
26943412Snewton	tf->tf_ecx = r[SVR4_X86_ECX];
27043412Snewton	tf->tf_eax = r[SVR4_X86_EAX];
27144270Snewton	tf->tf_trapno = r[SVR4_X86_TRAPNO];
27244270Snewton	tf->tf_err = r[SVR4_X86_ERR];
27343412Snewton	tf->tf_eip = r[SVR4_X86_EIP];
27443412Snewton	tf->tf_cs = r[SVR4_X86_CS];
27543412Snewton	tf->tf_ss = r[SVR4_X86_SS];
27643412Snewton	tf->tf_esp = r[SVR4_X86_ESP];
27743412Snewton
27844270Snewton	p->p_emuldata = uc->uc_link;
27943412Snewton	/*
28043412Snewton	 * restore signal stack
28143412Snewton	 */
28244270Snewton	if (uc->uc_flags & SVR4_UC_STACK) {
28344270Snewton		svr4_to_bsd_sigaltstack(s, sf);
28444270Snewton	}
28543412Snewton
28643412Snewton	/*
28743412Snewton	 * restore signal mask
28843412Snewton	 */
28944270Snewton	if (uc->uc_flags & SVR4_UC_SIGMASK) {
29056044Snewton#if defined(DEBUG_SVR4)
29156044Snewton		{
29256044Snewton			int i;
29356044Snewton			for (i = 0; i < 4; i++)
29456044Snewton				DPRINTF(("\tuc_sigmask[%d] = %lx\n", i,
29556044Snewton						uc->uc_sigmask.bits[i]));
29656044Snewton		}
29756044Snewton#endif
29844270Snewton		svr4_to_bsd_sigset(&uc->uc_sigmask, &mask);
29952140Sluoqi		SIG_CANTMASK(mask);
300112888Sjeff		td->td_sigmask = mask;
301112888Sjeff		signotify(td);
30244270Snewton	}
30383641Sjhb	PROC_UNLOCK(p);
30443412Snewton
30543412Snewton	return 0; /*EJUSTRETURN;*/
30643412Snewton}
30743412Snewton
30843412Snewton
30943412Snewtonstatic void
31043412Snewtonsvr4_getsiginfo(si, sig, code, addr)
31143412Snewton	union svr4_siginfo	*si;
31243412Snewton	int			 sig;
31343412Snewton	u_long			 code;
31443412Snewton	caddr_t			 addr;
31543412Snewton{
316151467Srwatson	si->svr4_si_signo = bsd_to_svr4_sig[sig];
317151467Srwatson	si->svr4_si_errno = 0;
318151467Srwatson	si->svr4_si_addr  = addr;
31943412Snewton
32043412Snewton	switch (code) {
32143412Snewton	case T_PRIVINFLT:
322151467Srwatson		si->svr4_si_code = SVR4_ILL_PRVOPC;
323151467Srwatson		si->svr4_si_trap = SVR4_T_PRIVINFLT;
32443412Snewton		break;
32543412Snewton
32643412Snewton	case T_BPTFLT:
327151467Srwatson		si->svr4_si_code = SVR4_TRAP_BRKPT;
328151467Srwatson		si->svr4_si_trap = SVR4_T_BPTFLT;
32943412Snewton		break;
33043412Snewton
33143412Snewton	case T_ARITHTRAP:
332151467Srwatson		si->svr4_si_code = SVR4_FPE_INTOVF;
333151467Srwatson		si->svr4_si_trap = SVR4_T_DIVIDE;
33443412Snewton		break;
33543412Snewton
33643412Snewton	case T_PROTFLT:
337151467Srwatson		si->svr4_si_code = SVR4_SEGV_ACCERR;
338151467Srwatson		si->svr4_si_trap = SVR4_T_PROTFLT;
33943412Snewton		break;
34043412Snewton
34143412Snewton	case T_TRCTRAP:
342151467Srwatson		si->svr4_si_code = SVR4_TRAP_TRACE;
343151467Srwatson		si->svr4_si_trap = SVR4_T_TRCTRAP;
34443412Snewton		break;
34543412Snewton
34643412Snewton	case T_PAGEFLT:
347151467Srwatson		si->svr4_si_code = SVR4_SEGV_ACCERR;
348151467Srwatson		si->svr4_si_trap = SVR4_T_PAGEFLT;
34943412Snewton		break;
35043412Snewton
35143412Snewton	case T_ALIGNFLT:
352151467Srwatson		si->svr4_si_code = SVR4_BUS_ADRALN;
353151467Srwatson		si->svr4_si_trap = SVR4_T_ALIGNFLT;
35443412Snewton		break;
35543412Snewton
35643412Snewton	case T_DIVIDE:
357151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTDIV;
358151467Srwatson		si->svr4_si_trap = SVR4_T_DIVIDE;
35943412Snewton		break;
36043412Snewton
36143412Snewton	case T_OFLOW:
362151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTOVF;
363151467Srwatson		si->svr4_si_trap = SVR4_T_DIVIDE;
36443412Snewton		break;
36543412Snewton
36643412Snewton	case T_BOUND:
367151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTSUB;
368151467Srwatson		si->svr4_si_trap = SVR4_T_BOUND;
36943412Snewton		break;
37043412Snewton
37143412Snewton	case T_DNA:
372151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTINV;
373151467Srwatson		si->svr4_si_trap = SVR4_T_DNA;
37443412Snewton		break;
37543412Snewton
37643412Snewton	case T_FPOPFLT:
377151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTINV;
378151467Srwatson		si->svr4_si_trap = SVR4_T_FPOPFLT;
37943412Snewton		break;
38043412Snewton
38143412Snewton	case T_SEGNPFLT:
382151467Srwatson		si->svr4_si_code = SVR4_SEGV_MAPERR;
383151467Srwatson		si->svr4_si_trap = SVR4_T_SEGNPFLT;
38443412Snewton		break;
38543412Snewton
38643412Snewton	case T_STKFLT:
387151467Srwatson		si->svr4_si_code = SVR4_ILL_BADSTK;
388151467Srwatson		si->svr4_si_trap = SVR4_T_STKFLT;
38943412Snewton		break;
39043412Snewton
39143412Snewton	default:
392151467Srwatson		si->svr4_si_code = 0;
393151467Srwatson		si->svr4_si_trap = 0;
39456044Snewton#if defined(DEBUG_SVR4)
39543412Snewton		printf("sig %d code %ld\n", sig, code);
39656044Snewton/*		panic("svr4_getsiginfo");*/
39743412Snewton#endif
39843412Snewton		break;
39943412Snewton	}
40043412Snewton}
40143412Snewton
40243412Snewton
40343412Snewton/*
40443412Snewton * Send an interrupt to process.
40543412Snewton *
40643412Snewton * Stack is set up to allow sigcode stored
40743412Snewton * in u. to call routine. After the handler is
40843412Snewton * done svr4 will call setcontext for us
40943412Snewton * with the user context we just set up, and we
41043412Snewton * will return to the user pc, psl.
41143412Snewton */
41243412Snewtonvoid
413151316Sdavidxusvr4_sendsig(catcher, ksi, mask)
41443412Snewton	sig_t catcher;
415151366Sdavidxu	ksiginfo_t *ksi;
41651793Smarcel	sigset_t *mask;
41743412Snewton{
41883366Sjulian	register struct thread *td = curthread;
41983366Sjulian	struct proc *p = td->td_proc;
42043412Snewton	register struct trapframe *tf;
42143412Snewton	struct svr4_sigframe *fp, frame;
42271495Sjhb	struct sigacts *psp;
42343412Snewton	int oonstack;
424151316Sdavidxu	int sig;
425151316Sdavidxu	int code;
42643412Snewton
427151467Srwatson	PROC_LOCK_ASSERT(p, MA_OWNED);
428151467Srwatson	sig = ksi->ksi_signo;
42956044Snewton#if defined(DEBUG_SVR4)
43056044Snewton	printf("svr4_sendsig(%d)\n", sig);
43156044Snewton#endif
432151316Sdavidxu	code = ksi->ksi_trapno; /* use trap No. */
43371495Sjhb	psp = p->p_sigacts;
434114983Sjhb	mtx_assert(&psp->ps_mtx, MA_OWNED);
43556044Snewton
43683366Sjulian	tf = td->td_frame;
43769379Smarcel	oonstack = sigonstack(tf->tf_esp);
43843412Snewton
43943412Snewton	/*
44043412Snewton	 * Allocate space for the signal handler context.
44143412Snewton	 */
442124141Sobrien	if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
44351793Smarcel	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
444294930Sjhb		fp = (struct svr4_sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
445124141Sobrien		    td->td_sigstk.ss_size - sizeof(struct svr4_sigframe));
446124141Sobrien		td->td_sigstk.ss_flags |= SS_ONSTACK;
44743412Snewton	} else {
44843412Snewton		fp = (struct svr4_sigframe *)tf->tf_esp - 1;
44943412Snewton	}
450114983Sjhb	mtx_unlock(&psp->ps_mtx);
45183641Sjhb	PROC_UNLOCK(p);
45243412Snewton
45343412Snewton	/*
45443412Snewton	 * Build the argument list for the signal handler.
45543412Snewton	 * Notes:
45643412Snewton	 * 	- we always build the whole argument list, even when we
45743412Snewton	 *	  don't need to [when SA_SIGINFO is not set, we don't need
45843412Snewton	 *	  to pass all sf_si and sf_uc]
45943412Snewton	 *	- we don't pass the correct signal address [we need to
46043412Snewton	 *	  modify many kernel files to enable that]
46143412Snewton	 */
46243412Snewton
46383366Sjulian	svr4_getcontext(td, &frame.sf_uc, mask, oonstack);
46456044Snewton#if defined(DEBUG_SVR4)
46556044Snewton	printf("obtained ucontext\n");
46656044Snewton#endif
46743412Snewton	svr4_getsiginfo(&frame.sf_si, sig, code, (caddr_t) tf->tf_eip);
46856044Snewton#if defined(DEBUG_SVR4)
46956044Snewton	printf("obtained siginfo\n");
47056044Snewton#endif
471151467Srwatson	frame.sf_signum = frame.sf_si.svr4_si_signo;
47243412Snewton	frame.sf_sip = &fp->sf_si;
47343412Snewton	frame.sf_ucp = &fp->sf_uc;
47443412Snewton	frame.sf_handler = catcher;
47556044Snewton#if defined(DEBUG_SVR4)
47643412Snewton	printf("sig = %d, sip %p, ucp = %p, handler = %p\n",
47743412Snewton	       frame.sf_signum, frame.sf_sip, frame.sf_ucp, frame.sf_handler);
47843412Snewton#endif
47943412Snewton
48043412Snewton	if (copyout(&frame, fp, sizeof(frame)) != 0) {
48143412Snewton		/*
48243412Snewton		 * Process has trashed its stack; give it an illegal
48343412Snewton		 * instruction to halt it in its tracks.
48443412Snewton		 */
48583641Sjhb		PROC_LOCK(p);
48683366Sjulian		sigexit(td, SIGILL);
48743412Snewton		/* NOTREACHED */
48843412Snewton	}
48943412Snewton#if defined(__NetBSD__)
49043412Snewton	/*
49143412Snewton	 * Build context to run handler in.
49243412Snewton	 */
49343412Snewton	tf->tf_es = GSEL(GUSERLDT_SEL, SEL_UPL);
49443412Snewton	tf->tf_ds = GSEL(GUSERLDT_SEL, SEL_UPL);
49543412Snewton	tf->tf_eip = (int)(((char *)PS_STRINGS) -
49643412Snewton	     svr4_szsigcode);
49743412Snewton	tf->tf_cs = GSEL(GUSERLDT_SEL, SEL_UPL);
49843412Snewton
499177145Skib	tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC|PSL_D);
50043412Snewton	tf->tf_esp = (int)fp;
50143412Snewton	tf->tf_ss = GSEL(GUSERLDT_SEL, SEL_UPL);
50243412Snewton#else
50343412Snewton	tf->tf_esp = (int)fp;
50443412Snewton	tf->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode));
505177145Skib	tf->tf_eflags &= ~(PSL_T | PSL_D);
50643412Snewton	tf->tf_cs = _ucodesel;
50743412Snewton	tf->tf_ds = _udatasel;
50843412Snewton	tf->tf_es = _udatasel;
50946129Sluoqi	tf->tf_fs = _udatasel;
51052140Sluoqi	load_gs(_udatasel);
51143412Snewton	tf->tf_ss = _udatasel;
51283163Sjhb	PROC_LOCK(p);
513114983Sjhb	mtx_lock(&psp->ps_mtx);
51443412Snewton#endif
51543412Snewton}
51643412Snewton
51743412Snewton
51843412Snewton
51943412Snewtonint
52083366Sjuliansvr4_sys_sysarch(td, v)
52183366Sjulian	struct thread *td;
52243412Snewton	struct svr4_sys_sysarch_args *v;
52343412Snewton{
52443412Snewton	struct svr4_sys_sysarch_args *uap = v;
52572930Speter#if 0	/* USER_LDT */
52671495Sjhb#if defined(__NetBSD__)
52743412Snewton	caddr_t sg = stackgap_init(p->p_emul);
52871495Sjhb#else
52971495Sjhb	caddr_t sg = stackgap_init();
53071495Sjhb#endif
53143412Snewton	int error;
53243412Snewton#endif
53372930Speter
53443412Snewton	switch (uap->op) {
53543412Snewton	case SVR4_SYSARCH_FPHW:
53643412Snewton		return 0;
53743412Snewton
53843412Snewton	case SVR4_SYSARCH_DSCR:
53972930Speter#if 0	/* USER_LDT */
54056044Snewton#warning "USER_LDT doesn't work - are you sure you want this?"
54143412Snewton		{
54243412Snewton			struct i386_set_ldt_args sa, *sap;
54343412Snewton			struct sys_sysarch_args ua;
54443412Snewton
54543412Snewton			struct svr4_ssd ssd;
54643412Snewton			union descriptor bsd;
54743412Snewton
548107849Salfred			if ((error = copyin(uap->a1, &ssd,
54943412Snewton					    sizeof(ssd))) != 0) {
55043412Snewton				printf("Cannot copy arg1\n");
55143412Snewton				return error;
55243412Snewton			}
55343412Snewton
55443412Snewton			printf("s=%x, b=%x, l=%x, a1=%x a2=%x\n",
55543412Snewton			       ssd.selector, ssd.base, ssd.limit,
55643412Snewton			       ssd.access1, ssd.access2);
55743412Snewton
55843412Snewton			/* We can only set ldt's for now. */
55943412Snewton			if (!ISLDT(ssd.selector)) {
56043412Snewton				printf("Not an ldt\n");
56143412Snewton				return EPERM;
56243412Snewton			}
56343412Snewton
56443412Snewton			/* Oh, well we don't cleanup either */
56543412Snewton			if (ssd.access1 == 0)
56643412Snewton				return 0;
56743412Snewton
56843412Snewton			bsd.sd.sd_lobase = ssd.base & 0xffffff;
56943412Snewton			bsd.sd.sd_hibase = (ssd.base >> 24) & 0xff;
57043412Snewton
57143412Snewton			bsd.sd.sd_lolimit = ssd.limit & 0xffff;
57243412Snewton			bsd.sd.sd_hilimit = (ssd.limit >> 16) & 0xf;
57343412Snewton
57443412Snewton			bsd.sd.sd_type = ssd.access1 & 0x1f;
57543412Snewton			bsd.sd.sd_dpl =  (ssd.access1 >> 5) & 0x3;
57643412Snewton			bsd.sd.sd_p = (ssd.access1 >> 7) & 0x1;
57743412Snewton
57843412Snewton			bsd.sd.sd_xx = ssd.access2 & 0x3;
57943412Snewton			bsd.sd.sd_def32 = (ssd.access2 >> 2) & 0x1;
58043412Snewton			bsd.sd.sd_gran = (ssd.access2 >> 3)& 0x1;
58143412Snewton
58243412Snewton			sa.start = IDXSEL(ssd.selector);
58343412Snewton			sa.desc = stackgap_alloc(&sg, sizeof(union descriptor));
58443412Snewton			sa.num = 1;
58543412Snewton			sap = stackgap_alloc(&sg,
58643412Snewton					     sizeof(struct i386_set_ldt_args));
58743412Snewton
58843412Snewton			if ((error = copyout(&sa, sap, sizeof(sa))) != 0) {
58943412Snewton				printf("Cannot copyout args\n");
59043412Snewton				return error;
59143412Snewton			}
59243412Snewton
593107849Salfred			ua.op = I386_SET_LDT;
594107849Salfred			ua.parms = (char *) sap;
59543412Snewton
59643412Snewton			if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) {
59743412Snewton				printf("Cannot copyout desc\n");
59843412Snewton				return error;
59943412Snewton			}
60043412Snewton
60183366Sjulian			return sys_sysarch(td, &ua, retval);
60243412Snewton		}
60343412Snewton#endif
60443412Snewton
60543412Snewton	default:
60643412Snewton		printf("svr4_sysarch(%d), a1 %p\n", uap->op,
60743412Snewton		       uap->a1);
60843412Snewton		return 0;
60943412Snewton	}
61043412Snewton}
611