1/*-
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994 Christos Zoulas
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/types.h>
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/exec.h>
36#include <sys/filedesc.h>
37#include <sys/lock.h>
38#include <sys/mutex.h>
39#include <sys/proc.h>
40#include <sys/signal.h>
41#include <sys/signalvar.h>
42
43#include <machine/cpu.h>
44#include <machine/cpufunc.h>
45#include <machine/psl.h>
46#include <machine/reg.h>
47#include <machine/specialreg.h>
48#include <machine/sysarch.h>
49#include <machine/vm86.h>
50#include <machine/vmparam.h>
51
52#include <vm/vm.h>
53#include <vm/pmap.h>
54
55#include <compat/svr4/svr4.h>
56#include <compat/svr4/svr4_types.h>
57#include <compat/svr4/svr4_signal.h>
58#include <i386/svr4/svr4_machdep.h>
59#include <compat/svr4/svr4_ucontext.h>
60#include <compat/svr4/svr4_proto.h>
61#include <compat/svr4/svr4_util.h>
62
63#undef sigcode
64#undef szsigcode
65
66extern int svr4_szsigcode;
67extern char svr4_sigcode[];
68extern int _udatasel, _ucodesel;
69
70static void svr4_getsiginfo(union svr4_siginfo *, int, u_long, caddr_t);
71
72#if !defined(__NetBSD__)
73  /* taken from /sys/arch/i386/include/psl.h on NetBSD-1.3 */
74# define PSL_MBZ 0xffc08028
75# define PSL_USERSTATIC (PSL_USER | PSL_MBZ | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP)
76# define USERMODE(c, f) (ISPL(c) == SEL_UPL)
77#endif
78
79#if defined(__NetBSD__)
80void
81svr4_setregs(td, epp, stack)
82	struct thread *td;
83	struct exec_package *epp;
84	u_long stack;
85{
86	register struct pcb *pcb = td->td_pcb;
87
88	pcb->pcb_savefpu.sv_env.en_cw = __SVR4_NPXCW__;
89	setregs(td, epp, stack, 0UL);
90}
91#endif /* __NetBSD__ */
92
93void
94svr4_getcontext(td, uc, mask, oonstack)
95	struct thread *td;
96	struct svr4_ucontext *uc;
97	sigset_t *mask;
98	int oonstack;
99{
100	struct proc *p = td->td_proc;
101	struct trapframe *tf = td->td_frame;
102	svr4_greg_t *r = uc->uc_mcontext.greg;
103	struct svr4_sigaltstack *s = &uc->uc_stack;
104#if defined(DONE_MORE_SIGALTSTACK_WORK)
105	struct sigacts *psp;
106	struct sigaltstack *sf;
107#endif
108
109	PROC_LOCK(p);
110#if defined(DONE_MORE_SIGALTSTACK_WORK)
111	psp = p->p_sigacts;
112	sf = &p->p_sigstk;
113#endif
114
115	memset(uc, 0, sizeof(struct svr4_ucontext));
116
117	uc->uc_link = p->p_emuldata;
118	/*
119	 * Set the general purpose registers
120	 */
121#ifdef VM86
122	if (tf->tf_eflags & PSL_VM) {
123		r[SVR4_X86_GS] = tf->tf_vm86_gs;
124		r[SVR4_X86_FS] = tf->tf_vm86_fs;
125		r[SVR4_X86_ES] = tf->tf_vm86_es;
126		r[SVR4_X86_DS] = tf->tf_vm86_ds;
127		r[SVR4_X86_EFL] = get_vflags(td);
128	} else
129#endif
130	{
131#if defined(__NetBSD__)
132	        __asm("movl %%gs,%w0" : "=r" (r[SVR4_X86_GS]));
133		__asm("movl %%fs,%w0" : "=r" (r[SVR4_X86_FS]));
134#else
135	        r[SVR4_X86_GS] = rgs();
136		r[SVR4_X86_FS] = tf->tf_fs;
137#endif
138		r[SVR4_X86_ES] = tf->tf_es;
139		r[SVR4_X86_DS] = tf->tf_ds;
140		r[SVR4_X86_EFL] = tf->tf_eflags;
141	}
142	r[SVR4_X86_EDI] = tf->tf_edi;
143	r[SVR4_X86_ESI] = tf->tf_esi;
144	r[SVR4_X86_EBP] = tf->tf_ebp;
145	r[SVR4_X86_ESP] = tf->tf_esp;
146	r[SVR4_X86_EBX] = tf->tf_ebx;
147	r[SVR4_X86_EDX] = tf->tf_edx;
148	r[SVR4_X86_ECX] = tf->tf_ecx;
149	r[SVR4_X86_EAX] = tf->tf_eax;
150	r[SVR4_X86_TRAPNO] = tf->tf_trapno;
151	r[SVR4_X86_ERR] = tf->tf_err;
152	r[SVR4_X86_EIP] = tf->tf_eip;
153	r[SVR4_X86_CS] = tf->tf_cs;
154	r[SVR4_X86_UESP] = 0;
155	r[SVR4_X86_SS] = tf->tf_ss;
156
157	/*
158	 * Set the signal stack
159	 */
160#if defined(DONE_MORE_SIGALTSTACK_WORK)
161	bsd_to_svr4_sigaltstack(sf, s);
162#else
163	s->ss_sp = (void *)(((u_long) tf->tf_esp) & ~(16384 - 1));
164	s->ss_size = 16384;
165	s->ss_flags = 0;
166#endif
167	PROC_UNLOCK(p);
168
169	/*
170	 * Set the signal mask
171	 */
172	bsd_to_svr4_sigset(mask, &uc->uc_sigmask);
173
174	/*
175	 * Set the flags
176	 */
177	uc->uc_flags = SVR4_UC_SIGMASK|SVR4_UC_CPU|SVR4_UC_STACK;
178}
179
180
181/*
182 * Set to ucontext specified. Reset signal mask and
183 * stack state from context.
184 * Return to previous pc and psl as specified by
185 * context left by sendsig. Check carefully to
186 * make sure that the user has not modified the
187 * psl to gain improper privileges or to cause
188 * a machine fault.
189 */
190int
191svr4_setcontext(td, uc)
192	struct thread *td;
193	struct svr4_ucontext *uc;
194{
195#if defined(DONE_MORE_SIGALTSTACK_WORK)
196	struct sigacts *psp;
197#endif
198	struct proc *p = td->td_proc;
199	register struct trapframe *tf;
200	svr4_greg_t *r = uc->uc_mcontext.greg;
201	struct svr4_sigaltstack *s = &uc->uc_stack;
202	struct sigaltstack *sf;
203	sigset_t mask;
204
205	PROC_LOCK(p);
206#if defined(DONE_MORE_SIGALTSTACK_WORK)
207	psp = p->p_sigacts;
208#endif
209	sf = &td->td_sigstk;
210
211	/*
212	 * XXX:
213	 * Should we check the value of flags to determine what to restore?
214	 * What to do with uc_link?
215	 * What to do with floating point stuff?
216	 * Should we bother with the rest of the registers that we
217	 * set to 0 right now?
218	 */
219
220	if ((uc->uc_flags & SVR4_UC_CPU) == 0) {
221		PROC_UNLOCK(p);
222		return 0;
223	}
224
225	DPRINTF(("svr4_setcontext(%d)\n", p->p_pid));
226
227	tf = td->td_frame;
228
229	/*
230	 * Restore register context.
231	 */
232#ifdef VM86
233#warning "VM86 doesn't work yet, please don't try to use it."
234	if (r[SVR4_X86_EFL] & PSL_VM) {
235		tf->tf_vm86_gs = r[SVR4_X86_GS];
236		tf->tf_vm86_fs = r[SVR4_X86_FS];
237		tf->tf_vm86_es = r[SVR4_X86_ES];
238		tf->tf_vm86_ds = r[SVR4_X86_DS];
239		set_vflags(td, r[SVR4_X86_EFL]);
240	} else
241#endif
242	{
243		/*
244		 * Check for security violations.  If we're returning to
245		 * protected mode, the CPU will validate the segment registers
246		 * automatically and generate a trap on violations.  We handle
247		 * the trap, rather than doing all of the checking here.
248		 */
249		if (((r[SVR4_X86_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
250		    !USERMODE(r[SVR4_X86_CS], r[SVR4_X86_EFL])) {
251			PROC_UNLOCK(p);
252			return (EINVAL);
253		}
254
255#if defined(__NetBSD__)
256		/* %fs and %gs were restored by the trampoline. */
257#else
258		/* %gs was restored by the trampoline. */
259		tf->tf_fs = r[SVR4_X86_FS];
260#endif
261		tf->tf_es = r[SVR4_X86_ES];
262		tf->tf_ds = r[SVR4_X86_DS];
263		tf->tf_eflags = r[SVR4_X86_EFL];
264	}
265	tf->tf_edi = r[SVR4_X86_EDI];
266	tf->tf_esi = r[SVR4_X86_ESI];
267	tf->tf_ebp = r[SVR4_X86_EBP];
268	tf->tf_ebx = r[SVR4_X86_EBX];
269	tf->tf_edx = r[SVR4_X86_EDX];
270	tf->tf_ecx = r[SVR4_X86_ECX];
271	tf->tf_eax = r[SVR4_X86_EAX];
272	tf->tf_trapno = r[SVR4_X86_TRAPNO];
273	tf->tf_err = r[SVR4_X86_ERR];
274	tf->tf_eip = r[SVR4_X86_EIP];
275	tf->tf_cs = r[SVR4_X86_CS];
276	tf->tf_ss = r[SVR4_X86_SS];
277	tf->tf_esp = r[SVR4_X86_ESP];
278
279	p->p_emuldata = uc->uc_link;
280	/*
281	 * restore signal stack
282	 */
283	if (uc->uc_flags & SVR4_UC_STACK) {
284		svr4_to_bsd_sigaltstack(s, sf);
285	}
286
287	/*
288	 * restore signal mask
289	 */
290	if (uc->uc_flags & SVR4_UC_SIGMASK) {
291#if defined(DEBUG_SVR4)
292		{
293			int i;
294			for (i = 0; i < 4; i++)
295				DPRINTF(("\tuc_sigmask[%d] = %lx\n", i,
296						uc->uc_sigmask.bits[i]));
297		}
298#endif
299		svr4_to_bsd_sigset(&uc->uc_sigmask, &mask);
300		SIG_CANTMASK(mask);
301		td->td_sigmask = mask;
302		signotify(td);
303	}
304	PROC_UNLOCK(p);
305
306	return 0; /*EJUSTRETURN;*/
307}
308
309
310static void
311svr4_getsiginfo(si, sig, code, addr)
312	union svr4_siginfo	*si;
313	int			 sig;
314	u_long			 code;
315	caddr_t			 addr;
316{
317	si->svr4_si_signo = bsd_to_svr4_sig[sig];
318	si->svr4_si_errno = 0;
319	si->svr4_si_addr  = addr;
320
321	switch (code) {
322	case T_PRIVINFLT:
323		si->svr4_si_code = SVR4_ILL_PRVOPC;
324		si->svr4_si_trap = SVR4_T_PRIVINFLT;
325		break;
326
327	case T_BPTFLT:
328		si->svr4_si_code = SVR4_TRAP_BRKPT;
329		si->svr4_si_trap = SVR4_T_BPTFLT;
330		break;
331
332	case T_ARITHTRAP:
333		si->svr4_si_code = SVR4_FPE_INTOVF;
334		si->svr4_si_trap = SVR4_T_DIVIDE;
335		break;
336
337	case T_PROTFLT:
338		si->svr4_si_code = SVR4_SEGV_ACCERR;
339		si->svr4_si_trap = SVR4_T_PROTFLT;
340		break;
341
342	case T_TRCTRAP:
343		si->svr4_si_code = SVR4_TRAP_TRACE;
344		si->svr4_si_trap = SVR4_T_TRCTRAP;
345		break;
346
347	case T_PAGEFLT:
348		si->svr4_si_code = SVR4_SEGV_ACCERR;
349		si->svr4_si_trap = SVR4_T_PAGEFLT;
350		break;
351
352	case T_ALIGNFLT:
353		si->svr4_si_code = SVR4_BUS_ADRALN;
354		si->svr4_si_trap = SVR4_T_ALIGNFLT;
355		break;
356
357	case T_DIVIDE:
358		si->svr4_si_code = SVR4_FPE_FLTDIV;
359		si->svr4_si_trap = SVR4_T_DIVIDE;
360		break;
361
362	case T_OFLOW:
363		si->svr4_si_code = SVR4_FPE_FLTOVF;
364		si->svr4_si_trap = SVR4_T_DIVIDE;
365		break;
366
367	case T_BOUND:
368		si->svr4_si_code = SVR4_FPE_FLTSUB;
369		si->svr4_si_trap = SVR4_T_BOUND;
370		break;
371
372	case T_DNA:
373		si->svr4_si_code = SVR4_FPE_FLTINV;
374		si->svr4_si_trap = SVR4_T_DNA;
375		break;
376
377	case T_FPOPFLT:
378		si->svr4_si_code = SVR4_FPE_FLTINV;
379		si->svr4_si_trap = SVR4_T_FPOPFLT;
380		break;
381
382	case T_SEGNPFLT:
383		si->svr4_si_code = SVR4_SEGV_MAPERR;
384		si->svr4_si_trap = SVR4_T_SEGNPFLT;
385		break;
386
387	case T_STKFLT:
388		si->svr4_si_code = SVR4_ILL_BADSTK;
389		si->svr4_si_trap = SVR4_T_STKFLT;
390		break;
391
392	default:
393		si->svr4_si_code = 0;
394		si->svr4_si_trap = 0;
395#if defined(DEBUG_SVR4)
396		printf("sig %d code %ld\n", sig, code);
397/*		panic("svr4_getsiginfo");*/
398#endif
399		break;
400	}
401}
402
403
404/*
405 * Send an interrupt to process.
406 *
407 * Stack is set up to allow sigcode stored
408 * in u. to call routine. After the handler is
409 * done svr4 will call setcontext for us
410 * with the user context we just set up, and we
411 * will return to the user pc, psl.
412 */
413void
414svr4_sendsig(catcher, ksi, mask)
415	sig_t catcher;
416	ksiginfo_t *ksi;
417	sigset_t *mask;
418{
419	register struct thread *td = curthread;
420	struct proc *p = td->td_proc;
421	register struct trapframe *tf;
422	struct svr4_sigframe *fp, frame;
423	struct sigacts *psp;
424	int oonstack;
425	int sig;
426	int code;
427
428	PROC_LOCK_ASSERT(p, MA_OWNED);
429	sig = ksi->ksi_signo;
430#if defined(DEBUG_SVR4)
431	printf("svr4_sendsig(%d)\n", sig);
432#endif
433	code = ksi->ksi_trapno; /* use trap No. */
434	psp = p->p_sigacts;
435	mtx_assert(&psp->ps_mtx, MA_OWNED);
436
437	tf = td->td_frame;
438	oonstack = sigonstack(tf->tf_esp);
439
440	/*
441	 * Allocate space for the signal handler context.
442	 */
443	if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
444	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
445		fp = (struct svr4_sigframe *)(td->td_sigstk.ss_sp +
446		    td->td_sigstk.ss_size - sizeof(struct svr4_sigframe));
447		td->td_sigstk.ss_flags |= SS_ONSTACK;
448	} else {
449		fp = (struct svr4_sigframe *)tf->tf_esp - 1;
450	}
451	mtx_unlock(&psp->ps_mtx);
452	PROC_UNLOCK(p);
453
454	/*
455	 * Build the argument list for the signal handler.
456	 * Notes:
457	 * 	- we always build the whole argument list, even when we
458	 *	  don't need to [when SA_SIGINFO is not set, we don't need
459	 *	  to pass all sf_si and sf_uc]
460	 *	- we don't pass the correct signal address [we need to
461	 *	  modify many kernel files to enable that]
462	 */
463
464	svr4_getcontext(td, &frame.sf_uc, mask, oonstack);
465#if defined(DEBUG_SVR4)
466	printf("obtained ucontext\n");
467#endif
468	svr4_getsiginfo(&frame.sf_si, sig, code, (caddr_t) tf->tf_eip);
469#if defined(DEBUG_SVR4)
470	printf("obtained siginfo\n");
471#endif
472	frame.sf_signum = frame.sf_si.svr4_si_signo;
473	frame.sf_sip = &fp->sf_si;
474	frame.sf_ucp = &fp->sf_uc;
475	frame.sf_handler = catcher;
476#if defined(DEBUG_SVR4)
477	printf("sig = %d, sip %p, ucp = %p, handler = %p\n",
478	       frame.sf_signum, frame.sf_sip, frame.sf_ucp, frame.sf_handler);
479#endif
480
481	if (copyout(&frame, fp, sizeof(frame)) != 0) {
482		/*
483		 * Process has trashed its stack; give it an illegal
484		 * instruction to halt it in its tracks.
485		 */
486		PROC_LOCK(p);
487		sigexit(td, SIGILL);
488		/* NOTREACHED */
489	}
490#if defined(__NetBSD__)
491	/*
492	 * Build context to run handler in.
493	 */
494	tf->tf_es = GSEL(GUSERLDT_SEL, SEL_UPL);
495	tf->tf_ds = GSEL(GUSERLDT_SEL, SEL_UPL);
496	tf->tf_eip = (int)(((char *)PS_STRINGS) -
497	     svr4_szsigcode);
498	tf->tf_cs = GSEL(GUSERLDT_SEL, SEL_UPL);
499
500	tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC|PSL_D);
501	tf->tf_esp = (int)fp;
502	tf->tf_ss = GSEL(GUSERLDT_SEL, SEL_UPL);
503#else
504	tf->tf_esp = (int)fp;
505	tf->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode));
506	tf->tf_eflags &= ~(PSL_T | PSL_D);
507	tf->tf_cs = _ucodesel;
508	tf->tf_ds = _udatasel;
509	tf->tf_es = _udatasel;
510	tf->tf_fs = _udatasel;
511	load_gs(_udatasel);
512	tf->tf_ss = _udatasel;
513	PROC_LOCK(p);
514	mtx_lock(&psp->ps_mtx);
515#endif
516}
517
518
519
520int
521svr4_sys_sysarch(td, v)
522	struct thread *td;
523	struct svr4_sys_sysarch_args *v;
524{
525	struct svr4_sys_sysarch_args *uap = v;
526#if 0	/* USER_LDT */
527#if defined(__NetBSD__)
528	caddr_t sg = stackgap_init(p->p_emul);
529#else
530	caddr_t sg = stackgap_init();
531#endif
532	int error;
533#endif
534
535	switch (uap->op) {
536	case SVR4_SYSARCH_FPHW:
537		return 0;
538
539	case SVR4_SYSARCH_DSCR:
540#if 0	/* USER_LDT */
541#warning "USER_LDT doesn't work - are you sure you want this?"
542		{
543			struct i386_set_ldt_args sa, *sap;
544			struct sys_sysarch_args ua;
545
546			struct svr4_ssd ssd;
547			union descriptor bsd;
548
549			if ((error = copyin(uap->a1, &ssd,
550					    sizeof(ssd))) != 0) {
551				printf("Cannot copy arg1\n");
552				return error;
553			}
554
555			printf("s=%x, b=%x, l=%x, a1=%x a2=%x\n",
556			       ssd.selector, ssd.base, ssd.limit,
557			       ssd.access1, ssd.access2);
558
559			/* We can only set ldt's for now. */
560			if (!ISLDT(ssd.selector)) {
561				printf("Not an ldt\n");
562				return EPERM;
563			}
564
565			/* Oh, well we don't cleanup either */
566			if (ssd.access1 == 0)
567				return 0;
568
569			bsd.sd.sd_lobase = ssd.base & 0xffffff;
570			bsd.sd.sd_hibase = (ssd.base >> 24) & 0xff;
571
572			bsd.sd.sd_lolimit = ssd.limit & 0xffff;
573			bsd.sd.sd_hilimit = (ssd.limit >> 16) & 0xf;
574
575			bsd.sd.sd_type = ssd.access1 & 0x1f;
576			bsd.sd.sd_dpl =  (ssd.access1 >> 5) & 0x3;
577			bsd.sd.sd_p = (ssd.access1 >> 7) & 0x1;
578
579			bsd.sd.sd_xx = ssd.access2 & 0x3;
580			bsd.sd.sd_def32 = (ssd.access2 >> 2) & 0x1;
581			bsd.sd.sd_gran = (ssd.access2 >> 3)& 0x1;
582
583			sa.start = IDXSEL(ssd.selector);
584			sa.desc = stackgap_alloc(&sg, sizeof(union descriptor));
585			sa.num = 1;
586			sap = stackgap_alloc(&sg,
587					     sizeof(struct i386_set_ldt_args));
588
589			if ((error = copyout(&sa, sap, sizeof(sa))) != 0) {
590				printf("Cannot copyout args\n");
591				return error;
592			}
593
594			ua.op = I386_SET_LDT;
595			ua.parms = (char *) sap;
596
597			if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) {
598				printf("Cannot copyout desc\n");
599				return error;
600			}
601
602			return sys_sysarch(td, &ua, retval);
603		}
604#endif
605
606	default:
607		printf("svr4_sysarch(%d), a1 %p\n", uap->op,
608		       uap->a1);
609		return 0;
610	}
611}
612