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