]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/i386/svr4/svr4_machdep.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / i386 / svr4 / svr4_machdep.c
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
66 extern int svr4_szsigcode;
67 extern char svr4_sigcode[];
68 extern int _udatasel, _ucodesel;
69
70 static 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__)
80 void
81 svr4_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
93 void
94 svr4_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  */
190 int
191 svr4_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
310 static void
311 svr4_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  */
413 void
414 svr4_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
520 int
521 svr4_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 }