svr4_machdep.c revision 116145
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: head/sys/i386/svr4/svr4_machdep.c 116145 2003-06-10 05:05:54Z obrien $");
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 = &p->p_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->si_signo = bsd_to_svr4_sig[sig];
318	si->si_errno = 0;
319	si->si_addr  = addr;
320
321	switch (code) {
322	case T_PRIVINFLT:
323		si->si_code = SVR4_ILL_PRVOPC;
324		si->si_trap = SVR4_T_PRIVINFLT;
325		break;
326
327	case T_BPTFLT:
328		si->si_code = SVR4_TRAP_BRKPT;
329		si->si_trap = SVR4_T_BPTFLT;
330		break;
331
332	case T_ARITHTRAP:
333		si->si_code = SVR4_FPE_INTOVF;
334		si->si_trap = SVR4_T_DIVIDE;
335		break;
336
337	case T_PROTFLT:
338		si->si_code = SVR4_SEGV_ACCERR;
339		si->si_trap = SVR4_T_PROTFLT;
340		break;
341
342	case T_TRCTRAP:
343		si->si_code = SVR4_TRAP_TRACE;
344		si->si_trap = SVR4_T_TRCTRAP;
345		break;
346
347	case T_PAGEFLT:
348		si->si_code = SVR4_SEGV_ACCERR;
349		si->si_trap = SVR4_T_PAGEFLT;
350		break;
351
352	case T_ALIGNFLT:
353		si->si_code = SVR4_BUS_ADRALN;
354		si->si_trap = SVR4_T_ALIGNFLT;
355		break;
356
357	case T_DIVIDE:
358		si->si_code = SVR4_FPE_FLTDIV;
359		si->si_trap = SVR4_T_DIVIDE;
360		break;
361
362	case T_OFLOW:
363		si->si_code = SVR4_FPE_FLTOVF;
364		si->si_trap = SVR4_T_DIVIDE;
365		break;
366
367	case T_BOUND:
368		si->si_code = SVR4_FPE_FLTSUB;
369		si->si_trap = SVR4_T_BOUND;
370		break;
371
372	case T_DNA:
373		si->si_code = SVR4_FPE_FLTINV;
374		si->si_trap = SVR4_T_DNA;
375		break;
376
377	case T_FPOPFLT:
378		si->si_code = SVR4_FPE_FLTINV;
379		si->si_trap = SVR4_T_FPOPFLT;
380		break;
381
382	case T_SEGNPFLT:
383		si->si_code = SVR4_SEGV_MAPERR;
384		si->si_trap = SVR4_T_SEGNPFLT;
385		break;
386
387	case T_STKFLT:
388		si->si_code = SVR4_ILL_BADSTK;
389		si->si_trap = SVR4_T_STKFLT;
390		break;
391
392	default:
393		si->si_code = 0;
394		si->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, sig, mask, code)
415	sig_t catcher;
416	int sig;
417	sigset_t *mask;
418	u_long code;
419{
420	register struct thread *td = curthread;
421	struct proc *p = td->td_proc;
422	register struct trapframe *tf;
423	struct svr4_sigframe *fp, frame;
424	struct sigacts *psp;
425	int oonstack;
426
427#if defined(DEBUG_SVR4)
428	printf("svr4_sendsig(%d)\n", sig);
429#endif
430	PROC_LOCK_ASSERT(p, MA_OWNED);
431	psp = p->p_sigacts;
432	mtx_assert(&psp->ps_mtx, MA_OWNED);
433
434	tf = td->td_frame;
435	oonstack = sigonstack(tf->tf_esp);
436
437	/*
438	 * Allocate space for the signal handler context.
439	 */
440	if ((p->p_flag & P_ALTSTACK) && !oonstack &&
441	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
442		fp = (struct svr4_sigframe *)(p->p_sigstk.ss_sp +
443		    p->p_sigstk.ss_size - sizeof(struct svr4_sigframe));
444		p->p_sigstk.ss_flags |= SS_ONSTACK;
445	} else {
446		fp = (struct svr4_sigframe *)tf->tf_esp - 1;
447	}
448	mtx_unlock(&psp->ps_mtx);
449	PROC_UNLOCK(p);
450
451	/*
452	 * Build the argument list for the signal handler.
453	 * Notes:
454	 * 	- we always build the whole argument list, even when we
455	 *	  don't need to [when SA_SIGINFO is not set, we don't need
456	 *	  to pass all sf_si and sf_uc]
457	 *	- we don't pass the correct signal address [we need to
458	 *	  modify many kernel files to enable that]
459	 */
460
461	svr4_getcontext(td, &frame.sf_uc, mask, oonstack);
462#if defined(DEBUG_SVR4)
463	printf("obtained ucontext\n");
464#endif
465	svr4_getsiginfo(&frame.sf_si, sig, code, (caddr_t) tf->tf_eip);
466#if defined(DEBUG_SVR4)
467	printf("obtained siginfo\n");
468#endif
469	frame.sf_signum = frame.sf_si.si_signo;
470	frame.sf_sip = &fp->sf_si;
471	frame.sf_ucp = &fp->sf_uc;
472	frame.sf_handler = catcher;
473#if defined(DEBUG_SVR4)
474	printf("sig = %d, sip %p, ucp = %p, handler = %p\n",
475	       frame.sf_signum, frame.sf_sip, frame.sf_ucp, frame.sf_handler);
476#endif
477
478	if (copyout(&frame, fp, sizeof(frame)) != 0) {
479		/*
480		 * Process has trashed its stack; give it an illegal
481		 * instruction to halt it in its tracks.
482		 */
483		PROC_LOCK(p);
484		sigexit(td, SIGILL);
485		/* NOTREACHED */
486	}
487#if defined(__NetBSD__)
488	/*
489	 * Build context to run handler in.
490	 */
491	tf->tf_es = GSEL(GUSERLDT_SEL, SEL_UPL);
492	tf->tf_ds = GSEL(GUSERLDT_SEL, SEL_UPL);
493	tf->tf_eip = (int)(((char *)PS_STRINGS) -
494	     svr4_szsigcode);
495	tf->tf_cs = GSEL(GUSERLDT_SEL, SEL_UPL);
496
497	tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
498	tf->tf_esp = (int)fp;
499	tf->tf_ss = GSEL(GUSERLDT_SEL, SEL_UPL);
500#else
501	tf->tf_esp = (int)fp;
502	tf->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode));
503	tf->tf_eflags &= ~PSL_T;
504	tf->tf_cs = _ucodesel;
505	tf->tf_ds = _udatasel;
506	tf->tf_es = _udatasel;
507	tf->tf_fs = _udatasel;
508	load_gs(_udatasel);
509	tf->tf_ss = _udatasel;
510	PROC_LOCK(p);
511	mtx_lock(&psp->ps_mtx);
512#endif
513}
514
515
516
517int
518svr4_sys_sysarch(td, v)
519	struct thread *td;
520	struct svr4_sys_sysarch_args *v;
521{
522	struct svr4_sys_sysarch_args *uap = v;
523#if 0	/* USER_LDT */
524#if defined(__NetBSD__)
525	caddr_t sg = stackgap_init(p->p_emul);
526#else
527	caddr_t sg = stackgap_init();
528#endif
529	int error;
530#endif
531
532	switch (uap->op) {
533	case SVR4_SYSARCH_FPHW:
534		return 0;
535
536	case SVR4_SYSARCH_DSCR:
537#if 0	/* USER_LDT */
538#warning "USER_LDT doesn't work - are you sure you want this?"
539		{
540			struct i386_set_ldt_args sa, *sap;
541			struct sys_sysarch_args ua;
542
543			struct svr4_ssd ssd;
544			union descriptor bsd;
545
546			if ((error = copyin(uap->a1, &ssd,
547					    sizeof(ssd))) != 0) {
548				printf("Cannot copy arg1\n");
549				return error;
550			}
551
552			printf("s=%x, b=%x, l=%x, a1=%x a2=%x\n",
553			       ssd.selector, ssd.base, ssd.limit,
554			       ssd.access1, ssd.access2);
555
556			/* We can only set ldt's for now. */
557			if (!ISLDT(ssd.selector)) {
558				printf("Not an ldt\n");
559				return EPERM;
560			}
561
562			/* Oh, well we don't cleanup either */
563			if (ssd.access1 == 0)
564				return 0;
565
566			bsd.sd.sd_lobase = ssd.base & 0xffffff;
567			bsd.sd.sd_hibase = (ssd.base >> 24) & 0xff;
568
569			bsd.sd.sd_lolimit = ssd.limit & 0xffff;
570			bsd.sd.sd_hilimit = (ssd.limit >> 16) & 0xf;
571
572			bsd.sd.sd_type = ssd.access1 & 0x1f;
573			bsd.sd.sd_dpl =  (ssd.access1 >> 5) & 0x3;
574			bsd.sd.sd_p = (ssd.access1 >> 7) & 0x1;
575
576			bsd.sd.sd_xx = ssd.access2 & 0x3;
577			bsd.sd.sd_def32 = (ssd.access2 >> 2) & 0x1;
578			bsd.sd.sd_gran = (ssd.access2 >> 3)& 0x1;
579
580			sa.start = IDXSEL(ssd.selector);
581			sa.desc = stackgap_alloc(&sg, sizeof(union descriptor));
582			sa.num = 1;
583			sap = stackgap_alloc(&sg,
584					     sizeof(struct i386_set_ldt_args));
585
586			if ((error = copyout(&sa, sap, sizeof(sa))) != 0) {
587				printf("Cannot copyout args\n");
588				return error;
589			}
590
591			ua.op = I386_SET_LDT;
592			ua.parms = (char *) sap;
593
594			if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) {
595				printf("Cannot copyout desc\n");
596				return error;
597			}
598
599			return sys_sysarch(td, &ua, retval);
600		}
601#endif
602
603	default:
604		printf("svr4_sysarch(%d), a1 %p\n", uap->op,
605		       uap->a1);
606		return 0;
607	}
608}
609