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[];
6843412Snewtonextern int _udatasel, _ucodesel;
6943412Snewton
7092765Salfredstatic void svr4_getsiginfo(union svr4_siginfo *, int, u_long, caddr_t);
7143412Snewton
7243412Snewton#if !defined(__NetBSD__)
7343412Snewton  /* taken from /sys/arch/i386/include/psl.h on NetBSD-1.3 */
7443412Snewton# define PSL_MBZ 0xffc08028
7543412Snewton# define PSL_USERSTATIC (PSL_USER | PSL_MBZ | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP)
7643412Snewton# define USERMODE(c, f) (ISPL(c) == SEL_UPL)
7743412Snewton#endif
7843412Snewton
7943412Snewton#if defined(__NetBSD__)
8043412Snewtonvoid
8183366Sjuliansvr4_setregs(td, epp, stack)
8283366Sjulian	struct thread *td;
8343412Snewton	struct exec_package *epp;
8443412Snewton	u_long stack;
8543412Snewton{
8683366Sjulian	register struct pcb *pcb = td->td_pcb;
8743412Snewton
8843412Snewton	pcb->pcb_savefpu.sv_env.en_cw = __SVR4_NPXCW__;
8983366Sjulian	setregs(td, epp, stack, 0UL);
9043412Snewton}
9143412Snewton#endif /* __NetBSD__ */
9243412Snewton
9343412Snewtonvoid
9483366Sjuliansvr4_getcontext(td, uc, mask, oonstack)
9583366Sjulian	struct thread *td;
9643412Snewton	struct svr4_ucontext *uc;
9751793Smarcel	sigset_t *mask;
9851793Smarcel	int oonstack;
9943412Snewton{
10083366Sjulian	struct proc *p = td->td_proc;
10183366Sjulian	struct trapframe *tf = td->td_frame;
10243412Snewton	svr4_greg_t *r = uc->uc_mcontext.greg;
10343412Snewton	struct svr4_sigaltstack *s = &uc->uc_stack;
10456044Snewton#if defined(DONE_MORE_SIGALTSTACK_WORK)
10571495Sjhb	struct sigacts *psp;
10671495Sjhb	struct sigaltstack *sf;
10749270Snewton#endif
10843412Snewton
10983641Sjhb	PROC_LOCK(p);
11071495Sjhb#if defined(DONE_MORE_SIGALTSTACK_WORK)
11171495Sjhb	psp = p->p_sigacts;
11271495Sjhb	sf = &p->p_sigstk;
11371495Sjhb#endif
11471495Sjhb
11543412Snewton	memset(uc, 0, sizeof(struct svr4_ucontext));
11643412Snewton
11744270Snewton	uc->uc_link = p->p_emuldata;
11843412Snewton	/*
11943412Snewton	 * Set the general purpose registers
12043412Snewton	 */
12147694Snewton#ifdef VM86
12243412Snewton	if (tf->tf_eflags & PSL_VM) {
12343412Snewton		r[SVR4_X86_GS] = tf->tf_vm86_gs;
12443412Snewton		r[SVR4_X86_FS] = tf->tf_vm86_fs;
12543412Snewton		r[SVR4_X86_ES] = tf->tf_vm86_es;
12643412Snewton		r[SVR4_X86_DS] = tf->tf_vm86_ds;
12783366Sjulian		r[SVR4_X86_EFL] = get_vflags(td);
12843412Snewton	} else
12947694Snewton#endif
13043412Snewton	{
13146129Sluoqi#if defined(__NetBSD__)
13243412Snewton	        __asm("movl %%gs,%w0" : "=r" (r[SVR4_X86_GS]));
13343412Snewton		__asm("movl %%fs,%w0" : "=r" (r[SVR4_X86_FS]));
13446129Sluoqi#else
13546129Sluoqi	        r[SVR4_X86_GS] = rgs();
13646129Sluoqi		r[SVR4_X86_FS] = tf->tf_fs;
13746129Sluoqi#endif
13843412Snewton		r[SVR4_X86_ES] = tf->tf_es;
13943412Snewton		r[SVR4_X86_DS] = tf->tf_ds;
14043412Snewton		r[SVR4_X86_EFL] = tf->tf_eflags;
14143412Snewton	}
14243412Snewton	r[SVR4_X86_EDI] = tf->tf_edi;
14343412Snewton	r[SVR4_X86_ESI] = tf->tf_esi;
14443412Snewton	r[SVR4_X86_EBP] = tf->tf_ebp;
14543412Snewton	r[SVR4_X86_ESP] = tf->tf_esp;
14643412Snewton	r[SVR4_X86_EBX] = tf->tf_ebx;
14743412Snewton	r[SVR4_X86_EDX] = tf->tf_edx;
14843412Snewton	r[SVR4_X86_ECX] = tf->tf_ecx;
14943412Snewton	r[SVR4_X86_EAX] = tf->tf_eax;
15044270Snewton	r[SVR4_X86_TRAPNO] = tf->tf_trapno;
15144270Snewton	r[SVR4_X86_ERR] = tf->tf_err;
15243412Snewton	r[SVR4_X86_EIP] = tf->tf_eip;
15343412Snewton	r[SVR4_X86_CS] = tf->tf_cs;
15443412Snewton	r[SVR4_X86_UESP] = 0;
15543412Snewton	r[SVR4_X86_SS] = tf->tf_ss;
15643412Snewton
15743412Snewton	/*
15843412Snewton	 * Set the signal stack
15943412Snewton	 */
16056044Snewton#if defined(DONE_MORE_SIGALTSTACK_WORK)
16143412Snewton	bsd_to_svr4_sigaltstack(sf, s);
16244270Snewton#else
16344270Snewton	s->ss_sp = (void *)(((u_long) tf->tf_esp) & ~(16384 - 1));
16444270Snewton	s->ss_size = 16384;
16544270Snewton	s->ss_flags = 0;
16644270Snewton#endif
16783641Sjhb	PROC_UNLOCK(p);
16843412Snewton
16943412Snewton	/*
17043412Snewton	 * Set the signal mask
17143412Snewton	 */
17251793Smarcel	bsd_to_svr4_sigset(mask, &uc->uc_sigmask);
17343412Snewton
17443412Snewton	/*
17543412Snewton	 * Set the flags
17643412Snewton	 */
17756044Snewton	uc->uc_flags = SVR4_UC_SIGMASK|SVR4_UC_CPU|SVR4_UC_STACK;
17843412Snewton}
17943412Snewton
18043412Snewton
18143412Snewton/*
18256044Snewton * Set to ucontext specified. Reset signal mask and
18343412Snewton * stack state from context.
18443412Snewton * Return to previous pc and psl as specified by
18543412Snewton * context left by sendsig. Check carefully to
18643412Snewton * make sure that the user has not modified the
18743412Snewton * psl to gain improper privileges or to cause
18843412Snewton * a machine fault.
18943412Snewton */
19043412Snewtonint
19183366Sjuliansvr4_setcontext(td, uc)
19283366Sjulian	struct thread *td;
19343412Snewton	struct svr4_ucontext *uc;
19443412Snewton{
19556044Snewton#if defined(DONE_MORE_SIGALTSTACK_WORK)
19671495Sjhb	struct sigacts *psp;
19756044Snewton#endif
19883366Sjulian	struct proc *p = td->td_proc;
19943412Snewton	register struct trapframe *tf;
20043412Snewton	svr4_greg_t *r = uc->uc_mcontext.greg;
20143412Snewton	struct svr4_sigaltstack *s = &uc->uc_stack;
20271495Sjhb	struct sigaltstack *sf;
20351793Smarcel	sigset_t mask;
20443412Snewton
20583641Sjhb	PROC_LOCK(p);
20671495Sjhb#if defined(DONE_MORE_SIGALTSTACK_WORK)
20783641Sjhb	psp = p->p_sigacts;
20871495Sjhb#endif
209124141Sobrien	sf = &td->td_sigstk;
21071495Sjhb
21143412Snewton	/*
21243412Snewton	 * XXX:
21343412Snewton	 * Should we check the value of flags to determine what to restore?
21443412Snewton	 * What to do with uc_link?
21543412Snewton	 * What to do with floating point stuff?
21643412Snewton	 * Should we bother with the rest of the registers that we
21743412Snewton	 * set to 0 right now?
21843412Snewton	 */
21943412Snewton
220113623Sjhb	if ((uc->uc_flags & SVR4_UC_CPU) == 0) {
221113623Sjhb		PROC_UNLOCK(p);
22244270Snewton		return 0;
223113623Sjhb	}
22444270Snewton
22556044Snewton	DPRINTF(("svr4_setcontext(%d)\n", p->p_pid));
22656044Snewton
22783366Sjulian	tf = td->td_frame;
22843412Snewton
22943412Snewton	/*
23043412Snewton	 * Restore register context.
23143412Snewton	 */
23247694Snewton#ifdef VM86
23356044Snewton#warning "VM86 doesn't work yet, please don't try to use it."
23443412Snewton	if (r[SVR4_X86_EFL] & PSL_VM) {
23543412Snewton		tf->tf_vm86_gs = r[SVR4_X86_GS];
23643412Snewton		tf->tf_vm86_fs = r[SVR4_X86_FS];
23743412Snewton		tf->tf_vm86_es = r[SVR4_X86_ES];
23843412Snewton		tf->tf_vm86_ds = r[SVR4_X86_DS];
23983366Sjulian		set_vflags(td, r[SVR4_X86_EFL]);
24043412Snewton	} else
24147694Snewton#endif
24243412Snewton	{
24343412Snewton		/*
24443412Snewton		 * Check for security violations.  If we're returning to
24543412Snewton		 * protected mode, the CPU will validate the segment registers
24643412Snewton		 * automatically and generate a trap on violations.  We handle
24743412Snewton		 * the trap, rather than doing all of the checking here.
24843412Snewton		 */
24943412Snewton		if (((r[SVR4_X86_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
250113623Sjhb		    !USERMODE(r[SVR4_X86_CS], r[SVR4_X86_EFL])) {
251113623Sjhb			PROC_UNLOCK(p);
25243412Snewton			return (EINVAL);
253113623Sjhb		}
25443412Snewton
25546129Sluoqi#if defined(__NetBSD__)
25643412Snewton		/* %fs and %gs were restored by the trampoline. */
25746129Sluoqi#else
25846129Sluoqi		/* %gs was restored by the trampoline. */
25946129Sluoqi		tf->tf_fs = r[SVR4_X86_FS];
26046129Sluoqi#endif
26143412Snewton		tf->tf_es = r[SVR4_X86_ES];
26243412Snewton		tf->tf_ds = r[SVR4_X86_DS];
26343412Snewton		tf->tf_eflags = r[SVR4_X86_EFL];
26443412Snewton	}
26543412Snewton	tf->tf_edi = r[SVR4_X86_EDI];
26643412Snewton	tf->tf_esi = r[SVR4_X86_ESI];
26743412Snewton	tf->tf_ebp = r[SVR4_X86_EBP];
26843412Snewton	tf->tf_ebx = r[SVR4_X86_EBX];
26943412Snewton	tf->tf_edx = r[SVR4_X86_EDX];
27043412Snewton	tf->tf_ecx = r[SVR4_X86_ECX];
27143412Snewton	tf->tf_eax = r[SVR4_X86_EAX];
27244270Snewton	tf->tf_trapno = r[SVR4_X86_TRAPNO];
27344270Snewton	tf->tf_err = r[SVR4_X86_ERR];
27443412Snewton	tf->tf_eip = r[SVR4_X86_EIP];
27543412Snewton	tf->tf_cs = r[SVR4_X86_CS];
27643412Snewton	tf->tf_ss = r[SVR4_X86_SS];
27743412Snewton	tf->tf_esp = r[SVR4_X86_ESP];
27843412Snewton
27944270Snewton	p->p_emuldata = uc->uc_link;
28043412Snewton	/*
28143412Snewton	 * restore signal stack
28243412Snewton	 */
28344270Snewton	if (uc->uc_flags & SVR4_UC_STACK) {
28444270Snewton		svr4_to_bsd_sigaltstack(s, sf);
28544270Snewton	}
28643412Snewton
28743412Snewton	/*
28843412Snewton	 * restore signal mask
28943412Snewton	 */
29044270Snewton	if (uc->uc_flags & SVR4_UC_SIGMASK) {
29156044Snewton#if defined(DEBUG_SVR4)
29256044Snewton		{
29356044Snewton			int i;
29456044Snewton			for (i = 0; i < 4; i++)
29556044Snewton				DPRINTF(("\tuc_sigmask[%d] = %lx\n", i,
29656044Snewton						uc->uc_sigmask.bits[i]));
29756044Snewton		}
29856044Snewton#endif
29944270Snewton		svr4_to_bsd_sigset(&uc->uc_sigmask, &mask);
30052140Sluoqi		SIG_CANTMASK(mask);
301112888Sjeff		td->td_sigmask = mask;
302112888Sjeff		signotify(td);
30344270Snewton	}
30483641Sjhb	PROC_UNLOCK(p);
30543412Snewton
30643412Snewton	return 0; /*EJUSTRETURN;*/
30743412Snewton}
30843412Snewton
30943412Snewton
31043412Snewtonstatic void
31143412Snewtonsvr4_getsiginfo(si, sig, code, addr)
31243412Snewton	union svr4_siginfo	*si;
31343412Snewton	int			 sig;
31443412Snewton	u_long			 code;
31543412Snewton	caddr_t			 addr;
31643412Snewton{
317151467Srwatson	si->svr4_si_signo = bsd_to_svr4_sig[sig];
318151467Srwatson	si->svr4_si_errno = 0;
319151467Srwatson	si->svr4_si_addr  = addr;
32043412Snewton
32143412Snewton	switch (code) {
32243412Snewton	case T_PRIVINFLT:
323151467Srwatson		si->svr4_si_code = SVR4_ILL_PRVOPC;
324151467Srwatson		si->svr4_si_trap = SVR4_T_PRIVINFLT;
32543412Snewton		break;
32643412Snewton
32743412Snewton	case T_BPTFLT:
328151467Srwatson		si->svr4_si_code = SVR4_TRAP_BRKPT;
329151467Srwatson		si->svr4_si_trap = SVR4_T_BPTFLT;
33043412Snewton		break;
33143412Snewton
33243412Snewton	case T_ARITHTRAP:
333151467Srwatson		si->svr4_si_code = SVR4_FPE_INTOVF;
334151467Srwatson		si->svr4_si_trap = SVR4_T_DIVIDE;
33543412Snewton		break;
33643412Snewton
33743412Snewton	case T_PROTFLT:
338151467Srwatson		si->svr4_si_code = SVR4_SEGV_ACCERR;
339151467Srwatson		si->svr4_si_trap = SVR4_T_PROTFLT;
34043412Snewton		break;
34143412Snewton
34243412Snewton	case T_TRCTRAP:
343151467Srwatson		si->svr4_si_code = SVR4_TRAP_TRACE;
344151467Srwatson		si->svr4_si_trap = SVR4_T_TRCTRAP;
34543412Snewton		break;
34643412Snewton
34743412Snewton	case T_PAGEFLT:
348151467Srwatson		si->svr4_si_code = SVR4_SEGV_ACCERR;
349151467Srwatson		si->svr4_si_trap = SVR4_T_PAGEFLT;
35043412Snewton		break;
35143412Snewton
35243412Snewton	case T_ALIGNFLT:
353151467Srwatson		si->svr4_si_code = SVR4_BUS_ADRALN;
354151467Srwatson		si->svr4_si_trap = SVR4_T_ALIGNFLT;
35543412Snewton		break;
35643412Snewton
35743412Snewton	case T_DIVIDE:
358151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTDIV;
359151467Srwatson		si->svr4_si_trap = SVR4_T_DIVIDE;
36043412Snewton		break;
36143412Snewton
36243412Snewton	case T_OFLOW:
363151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTOVF;
364151467Srwatson		si->svr4_si_trap = SVR4_T_DIVIDE;
36543412Snewton		break;
36643412Snewton
36743412Snewton	case T_BOUND:
368151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTSUB;
369151467Srwatson		si->svr4_si_trap = SVR4_T_BOUND;
37043412Snewton		break;
37143412Snewton
37243412Snewton	case T_DNA:
373151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTINV;
374151467Srwatson		si->svr4_si_trap = SVR4_T_DNA;
37543412Snewton		break;
37643412Snewton
37743412Snewton	case T_FPOPFLT:
378151467Srwatson		si->svr4_si_code = SVR4_FPE_FLTINV;
379151467Srwatson		si->svr4_si_trap = SVR4_T_FPOPFLT;
38043412Snewton		break;
38143412Snewton
38243412Snewton	case T_SEGNPFLT:
383151467Srwatson		si->svr4_si_code = SVR4_SEGV_MAPERR;
384151467Srwatson		si->svr4_si_trap = SVR4_T_SEGNPFLT;
38543412Snewton		break;
38643412Snewton
38743412Snewton	case T_STKFLT:
388151467Srwatson		si->svr4_si_code = SVR4_ILL_BADSTK;
389151467Srwatson		si->svr4_si_trap = SVR4_T_STKFLT;
39043412Snewton		break;
39143412Snewton
39243412Snewton	default:
393151467Srwatson		si->svr4_si_code = 0;
394151467Srwatson		si->svr4_si_trap = 0;
39556044Snewton#if defined(DEBUG_SVR4)
39643412Snewton		printf("sig %d code %ld\n", sig, code);
39756044Snewton/*		panic("svr4_getsiginfo");*/
39843412Snewton#endif
39943412Snewton		break;
40043412Snewton	}
40143412Snewton}
40243412Snewton
40343412Snewton
40443412Snewton/*
40543412Snewton * Send an interrupt to process.
40643412Snewton *
40743412Snewton * Stack is set up to allow sigcode stored
40843412Snewton * in u. to call routine. After the handler is
40943412Snewton * done svr4 will call setcontext for us
41043412Snewton * with the user context we just set up, and we
41143412Snewton * will return to the user pc, psl.
41243412Snewton */
41343412Snewtonvoid
414151316Sdavidxusvr4_sendsig(catcher, ksi, mask)
41543412Snewton	sig_t catcher;
416151366Sdavidxu	ksiginfo_t *ksi;
41751793Smarcel	sigset_t *mask;
41843412Snewton{
41983366Sjulian	register struct thread *td = curthread;
42083366Sjulian	struct proc *p = td->td_proc;
42143412Snewton	register struct trapframe *tf;
42243412Snewton	struct svr4_sigframe *fp, frame;
42371495Sjhb	struct sigacts *psp;
42443412Snewton	int oonstack;
425151316Sdavidxu	int sig;
426151316Sdavidxu	int code;
42743412Snewton
428151467Srwatson	PROC_LOCK_ASSERT(p, MA_OWNED);
429151467Srwatson	sig = ksi->ksi_signo;
43056044Snewton#if defined(DEBUG_SVR4)
43156044Snewton	printf("svr4_sendsig(%d)\n", sig);
43256044Snewton#endif
433151316Sdavidxu	code = ksi->ksi_trapno; /* use trap No. */
43471495Sjhb	psp = p->p_sigacts;
435114983Sjhb	mtx_assert(&psp->ps_mtx, MA_OWNED);
43656044Snewton
43783366Sjulian	tf = td->td_frame;
43869379Smarcel	oonstack = sigonstack(tf->tf_esp);
43943412Snewton
44043412Snewton	/*
44143412Snewton	 * Allocate space for the signal handler context.
44243412Snewton	 */
443124141Sobrien	if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
44451793Smarcel	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
445124141Sobrien		fp = (struct svr4_sigframe *)(td->td_sigstk.ss_sp +
446124141Sobrien		    td->td_sigstk.ss_size - sizeof(struct svr4_sigframe));
447124141Sobrien		td->td_sigstk.ss_flags |= SS_ONSTACK;
44843412Snewton	} else {
44943412Snewton		fp = (struct svr4_sigframe *)tf->tf_esp - 1;
45043412Snewton	}
451114983Sjhb	mtx_unlock(&psp->ps_mtx);
45283641Sjhb	PROC_UNLOCK(p);
45343412Snewton
45443412Snewton	/*
45543412Snewton	 * Build the argument list for the signal handler.
45643412Snewton	 * Notes:
45743412Snewton	 * 	- we always build the whole argument list, even when we
45843412Snewton	 *	  don't need to [when SA_SIGINFO is not set, we don't need
45943412Snewton	 *	  to pass all sf_si and sf_uc]
46043412Snewton	 *	- we don't pass the correct signal address [we need to
46143412Snewton	 *	  modify many kernel files to enable that]
46243412Snewton	 */
46343412Snewton
46483366Sjulian	svr4_getcontext(td, &frame.sf_uc, mask, oonstack);
46556044Snewton#if defined(DEBUG_SVR4)
46656044Snewton	printf("obtained ucontext\n");
46756044Snewton#endif
46843412Snewton	svr4_getsiginfo(&frame.sf_si, sig, code, (caddr_t) tf->tf_eip);
46956044Snewton#if defined(DEBUG_SVR4)
47056044Snewton	printf("obtained siginfo\n");
47156044Snewton#endif
472151467Srwatson	frame.sf_signum = frame.sf_si.svr4_si_signo;
47343412Snewton	frame.sf_sip = &fp->sf_si;
47443412Snewton	frame.sf_ucp = &fp->sf_uc;
47543412Snewton	frame.sf_handler = catcher;
47656044Snewton#if defined(DEBUG_SVR4)
47743412Snewton	printf("sig = %d, sip %p, ucp = %p, handler = %p\n",
47843412Snewton	       frame.sf_signum, frame.sf_sip, frame.sf_ucp, frame.sf_handler);
47943412Snewton#endif
48043412Snewton
48143412Snewton	if (copyout(&frame, fp, sizeof(frame)) != 0) {
48243412Snewton		/*
48343412Snewton		 * Process has trashed its stack; give it an illegal
48443412Snewton		 * instruction to halt it in its tracks.
48543412Snewton		 */
48683641Sjhb		PROC_LOCK(p);
48783366Sjulian		sigexit(td, SIGILL);
48843412Snewton		/* NOTREACHED */
48943412Snewton	}
49043412Snewton#if defined(__NetBSD__)
49143412Snewton	/*
49243412Snewton	 * Build context to run handler in.
49343412Snewton	 */
49443412Snewton	tf->tf_es = GSEL(GUSERLDT_SEL, SEL_UPL);
49543412Snewton	tf->tf_ds = GSEL(GUSERLDT_SEL, SEL_UPL);
49643412Snewton	tf->tf_eip = (int)(((char *)PS_STRINGS) -
49743412Snewton	     svr4_szsigcode);
49843412Snewton	tf->tf_cs = GSEL(GUSERLDT_SEL, SEL_UPL);
49943412Snewton
500177145Skib	tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC|PSL_D);
50143412Snewton	tf->tf_esp = (int)fp;
50243412Snewton	tf->tf_ss = GSEL(GUSERLDT_SEL, SEL_UPL);
50343412Snewton#else
50443412Snewton	tf->tf_esp = (int)fp;
50543412Snewton	tf->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode));
506177145Skib	tf->tf_eflags &= ~(PSL_T | PSL_D);
50743412Snewton	tf->tf_cs = _ucodesel;
50843412Snewton	tf->tf_ds = _udatasel;
50943412Snewton	tf->tf_es = _udatasel;
51046129Sluoqi	tf->tf_fs = _udatasel;
51152140Sluoqi	load_gs(_udatasel);
51243412Snewton	tf->tf_ss = _udatasel;
51383163Sjhb	PROC_LOCK(p);
514114983Sjhb	mtx_lock(&psp->ps_mtx);
51543412Snewton#endif
51643412Snewton}
51743412Snewton
51843412Snewton
51943412Snewton
52043412Snewtonint
52183366Sjuliansvr4_sys_sysarch(td, v)
52283366Sjulian	struct thread *td;
52343412Snewton	struct svr4_sys_sysarch_args *v;
52443412Snewton{
52543412Snewton	struct svr4_sys_sysarch_args *uap = v;
52672930Speter#if 0	/* USER_LDT */
52771495Sjhb#if defined(__NetBSD__)
52843412Snewton	caddr_t sg = stackgap_init(p->p_emul);
52971495Sjhb#else
53071495Sjhb	caddr_t sg = stackgap_init();
53171495Sjhb#endif
53243412Snewton	int error;
53343412Snewton#endif
53472930Speter
53543412Snewton	switch (uap->op) {
53643412Snewton	case SVR4_SYSARCH_FPHW:
53743412Snewton		return 0;
53843412Snewton
53943412Snewton	case SVR4_SYSARCH_DSCR:
54072930Speter#if 0	/* USER_LDT */
54156044Snewton#warning "USER_LDT doesn't work - are you sure you want this?"
54243412Snewton		{
54343412Snewton			struct i386_set_ldt_args sa, *sap;
54443412Snewton			struct sys_sysarch_args ua;
54543412Snewton
54643412Snewton			struct svr4_ssd ssd;
54743412Snewton			union descriptor bsd;
54843412Snewton
549107849Salfred			if ((error = copyin(uap->a1, &ssd,
55043412Snewton					    sizeof(ssd))) != 0) {
55143412Snewton				printf("Cannot copy arg1\n");
55243412Snewton				return error;
55343412Snewton			}
55443412Snewton
55543412Snewton			printf("s=%x, b=%x, l=%x, a1=%x a2=%x\n",
55643412Snewton			       ssd.selector, ssd.base, ssd.limit,
55743412Snewton			       ssd.access1, ssd.access2);
55843412Snewton
55943412Snewton			/* We can only set ldt's for now. */
56043412Snewton			if (!ISLDT(ssd.selector)) {
56143412Snewton				printf("Not an ldt\n");
56243412Snewton				return EPERM;
56343412Snewton			}
56443412Snewton
56543412Snewton			/* Oh, well we don't cleanup either */
56643412Snewton			if (ssd.access1 == 0)
56743412Snewton				return 0;
56843412Snewton
56943412Snewton			bsd.sd.sd_lobase = ssd.base & 0xffffff;
57043412Snewton			bsd.sd.sd_hibase = (ssd.base >> 24) & 0xff;
57143412Snewton
57243412Snewton			bsd.sd.sd_lolimit = ssd.limit & 0xffff;
57343412Snewton			bsd.sd.sd_hilimit = (ssd.limit >> 16) & 0xf;
57443412Snewton
57543412Snewton			bsd.sd.sd_type = ssd.access1 & 0x1f;
57643412Snewton			bsd.sd.sd_dpl =  (ssd.access1 >> 5) & 0x3;
57743412Snewton			bsd.sd.sd_p = (ssd.access1 >> 7) & 0x1;
57843412Snewton
57943412Snewton			bsd.sd.sd_xx = ssd.access2 & 0x3;
58043412Snewton			bsd.sd.sd_def32 = (ssd.access2 >> 2) & 0x1;
58143412Snewton			bsd.sd.sd_gran = (ssd.access2 >> 3)& 0x1;
58243412Snewton
58343412Snewton			sa.start = IDXSEL(ssd.selector);
58443412Snewton			sa.desc = stackgap_alloc(&sg, sizeof(union descriptor));
58543412Snewton			sa.num = 1;
58643412Snewton			sap = stackgap_alloc(&sg,
58743412Snewton					     sizeof(struct i386_set_ldt_args));
58843412Snewton
58943412Snewton			if ((error = copyout(&sa, sap, sizeof(sa))) != 0) {
59043412Snewton				printf("Cannot copyout args\n");
59143412Snewton				return error;
59243412Snewton			}
59343412Snewton
594107849Salfred			ua.op = I386_SET_LDT;
595107849Salfred			ua.parms = (char *) sap;
59643412Snewton
59743412Snewton			if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) {
59843412Snewton				printf("Cannot copyout desc\n");
59943412Snewton				return error;
60043412Snewton			}
60143412Snewton
60283366Sjulian			return sys_sysarch(td, &ua, retval);
60343412Snewton		}
60443412Snewton#endif
60543412Snewton
60643412Snewton	default:
60743412Snewton		printf("svr4_sysarch(%d), a1 %p\n", uap->op,
60843412Snewton		       uap->a1);
60943412Snewton		return 0;
61043412Snewton	}
61143412Snewton}
612