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