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