Do some major performance tuning of the userland scheduler.
[dragonfly.git] / sys / i386 / i386 / trap.c
1 /*-
2  * Copyright (C) 1994, David Greenman
3  * Copyright (c) 1990, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the University of Utah, and William Jolitz.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *      from: @(#)trap.c        7.4 (Berkeley) 5/13/91
38  * $FreeBSD: src/sys/i386/i386/trap.c,v 1.147.2.11 2003/02/27 19:09:59 luoqi Exp $
39  * $DragonFly: src/sys/i386/i386/Attic/trap.c,v 1.47 2004/03/28 08:03:05 dillon Exp $
40  */
41
42 /*
43  * 386 Trap and System call handling
44  */
45
46 #include "use_isa.h"
47 #include "use_npx.h"
48
49 #include "opt_cpu.h"
50 #include "opt_ddb.h"
51 #include "opt_ktrace.h"
52 #include "opt_clock.h"
53 #include "opt_trap.h"
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/proc.h>
58 #include <sys/pioctl.h>
59 #include <sys/kernel.h>
60 #include <sys/resourcevar.h>
61 #include <sys/signalvar.h>
62 #include <sys/syscall.h>
63 #include <sys/sysctl.h>
64 #include <sys/sysent.h>
65 #include <sys/uio.h>
66 #include <sys/vmmeter.h>
67 #include <sys/malloc.h>
68 #ifdef KTRACE
69 #include <sys/ktrace.h>
70 #endif
71 #include <sys/upcall.h>
72 #include <sys/sysproto.h>
73 #include <sys/sysunion.h>
74
75 #include <vm/vm.h>
76 #include <vm/vm_param.h>
77 #include <sys/lock.h>
78 #include <vm/pmap.h>
79 #include <vm/vm_kern.h>
80 #include <vm/vm_map.h>
81 #include <vm/vm_page.h>
82 #include <vm/vm_extern.h>
83
84 #include <machine/cpu.h>
85 #include <machine/ipl.h>
86 #include <machine/md_var.h>
87 #include <machine/pcb.h>
88 #ifdef SMP
89 #include <machine/smp.h>
90 #endif
91 #include <machine/tss.h>
92 #include <machine/globaldata.h>
93
94 #include <i386/isa/intr_machdep.h>
95
96 #ifdef POWERFAIL_NMI
97 #include <sys/syslog.h>
98 #include <machine/clock.h>
99 #endif
100
101 #include <machine/vm86.h>
102
103 #include <ddb/ddb.h>
104 #include <sys/msgport2.h>
105 #include <sys/thread2.h>
106
107 int (*pmath_emulate) (struct trapframe *);
108
109 extern void trap (struct trapframe frame);
110 extern int trapwrite (unsigned addr);
111 extern void syscall2 (struct trapframe frame);
112 extern void sendsys2 (struct trapframe frame);
113
114 static int trap_pfault (struct trapframe *, int, vm_offset_t);
115 static void trap_fatal (struct trapframe *, vm_offset_t);
116 void dblfault_handler (void);
117
118 extern inthand_t IDTVEC(syscall);
119
120 #define MAX_TRAP_MSG            28
121 static char *trap_msg[] = {
122         "",                                     /*  0 unused */
123         "privileged instruction fault",         /*  1 T_PRIVINFLT */
124         "",                                     /*  2 unused */
125         "breakpoint instruction fault",         /*  3 T_BPTFLT */
126         "",                                     /*  4 unused */
127         "",                                     /*  5 unused */
128         "arithmetic trap",                      /*  6 T_ARITHTRAP */
129         "system forced exception",              /*  7 T_ASTFLT */
130         "",                                     /*  8 unused */
131         "general protection fault",             /*  9 T_PROTFLT */
132         "trace trap",                           /* 10 T_TRCTRAP */
133         "",                                     /* 11 unused */
134         "page fault",                           /* 12 T_PAGEFLT */
135         "",                                     /* 13 unused */
136         "alignment fault",                      /* 14 T_ALIGNFLT */
137         "",                                     /* 15 unused */
138         "",                                     /* 16 unused */
139         "",                                     /* 17 unused */
140         "integer divide fault",                 /* 18 T_DIVIDE */
141         "non-maskable interrupt trap",          /* 19 T_NMI */
142         "overflow trap",                        /* 20 T_OFLOW */
143         "FPU bounds check fault",               /* 21 T_BOUND */
144         "FPU device not available",             /* 22 T_DNA */
145         "double fault",                         /* 23 T_DOUBLEFLT */
146         "FPU operand fetch fault",              /* 24 T_FPOPFLT */
147         "invalid TSS fault",                    /* 25 T_TSSFLT */
148         "segment not present fault",            /* 26 T_SEGNPFLT */
149         "stack fault",                          /* 27 T_STKFLT */
150         "machine check trap",                   /* 28 T_MCHK */
151 };
152
153 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
154 extern int has_f00f_bug;
155 #endif
156
157 #ifdef DDB
158 static int ddb_on_nmi = 1;
159 SYSCTL_INT(_machdep, OID_AUTO, ddb_on_nmi, CTLFLAG_RW,
160         &ddb_on_nmi, 0, "Go to DDB on NMI");
161 #endif
162 static int panic_on_nmi = 1;
163 SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
164         &panic_on_nmi, 0, "Panic on NMI");
165 static int fast_release;
166 SYSCTL_INT(_machdep, OID_AUTO, fast_release, CTLFLAG_RW,
167         &fast_release, 0, "Passive Release was optimal");
168 static int slow_release;
169 SYSCTL_INT(_machdep, OID_AUTO, slow_release, CTLFLAG_RW,
170         &slow_release, 0, "Passive Release was nonoptimal");
171 static int pass_release;
172 SYSCTL_INT(_machdep, OID_AUTO, pass_release, CTLFLAG_RW,
173         &pass_release, 0, "Passive Release on switch");
174
175 MALLOC_DEFINE(M_SYSMSG, "sysmsg", "sysmsg structure");
176
177 /*
178  * USER->KERNEL transition.  Do not transition us out of userland from the
179  * point of view of the userland scheduler unless we actually have to
180  * switch.  Switching typically occurs when a process blocks in the kernel.
181  *
182  * passive_release is called from within a critical section and the BGL will
183  * still be held.  This function is NOT called for preemptions, only for
184  * switchouts.  Note that other elements of the system (uio_yield()) assume
185  * that the user cruft will be released when lwkt_switch() is called.
186  */
187 static void
188 passive_release(struct thread *td)
189 {
190         struct proc *p = td->td_proc;
191
192         td->td_release = NULL;
193
194         /*
195          * P_CP_RELEASED prevents the userland scheduler from messing with
196          * this proc.
197          */
198         if ((p->p_flag & P_CP_RELEASED) == 0) {
199                 p->p_flag |= P_CP_RELEASED;
200                 lwkt_setpri_self(TDPRI_KERN_USER);
201         }
202
203         /*
204          * Only one process will have a P_CURPROC designation for each cpu
205          * in the system.  Releasing it allows another userland process to
206          * be scheduled in case our thread blocks in the kernel.
207          */
208         if (p->p_flag & P_CURPROC) {
209                 release_curproc(p);
210                 ++pass_release;
211         }
212 }
213
214 /*
215  * userenter() passively intercepts the thread switch function to increase
216  * the thread priority from a user priority to a kernel priority, reducing
217  * syscall and trap overhead for the case where no switch occurs.
218  */
219
220 static __inline void
221 userenter(struct thread *curtd)
222 {
223         curtd->td_release = passive_release;
224 }
225
226 static __inline void
227 userexit(struct proc *p)
228 {
229         struct thread *td = p->p_thread;
230
231         /*
232          * Reacquire our P_CURPROC status and adjust the LWKT priority
233          * for our return to userland.  We can fast path the case where
234          * td_release was not called by checking particular proc flags.
235          * Otherwise we do it the slow way.
236          *
237          * Lowering our priority may make other higher priority threads
238          * runnable. lwkt_setpri_self() does not switch away, so call
239          * lwkt_maybe_switch() to deal with it.  We do this *before* we
240          * acquire P_CURPROC because another thread may also be intending
241          * to return to userland and if it has a higher user priority then
242          * us it will have to block and force us to reschedule, resulting in
243          * unnecessary extra context switches.
244          *
245          * WARNING!  Once our priority is lowered to a user level priority
246          * it is possible, once we return to user mode (or if we were to
247          * block) for a cpu-bound user process to prevent us from getting cpu
248          * again.  This is always the last step.
249          */
250         td->td_release = NULL;
251         if ((p->p_flag & (P_CP_RELEASED|P_CURPROC)) == P_CURPROC) {
252                 ++fast_release;
253                 lwkt_maybe_switch();
254         } else {
255                 ++slow_release;
256                 lwkt_setpri_self(TDPRI_USER_NORM);
257                 lwkt_maybe_switch();
258                 acquire_curproc(p);
259 #if 0
260                 /* POSSIBLE FUTURE */
261                 switch(p->p_rtprio.type) {
262                 case RTP_PRIO_IDLE:
263                         lwkt_setpri_self(TDPRI_USER_IDLE);
264                         break;
265                 case RTP_PRIO_REALTIME:
266                 case RTP_PRIO_FIFO:
267                         lwkt_setpri_self(TDPRI_USER_REAL);
268                         break;
269                 default:
270                         lwkt_setpri_self(TDPRI_USER_NORM);
271                         break;
272                 }
273 #endif
274         }
275 }
276
277
278 static void
279 userret(struct proc *p, struct trapframe *frame, u_quad_t oticks)
280 {
281         int sig;
282
283         /*
284          * Post any pending upcalls
285          */
286         if (p->p_flag & P_UPCALLPEND) {
287                 p->p_flag &= ~P_UPCALLPEND;
288                 postupcall(p);
289         }
290
291         /*
292          * Post any pending signals
293          */
294         while ((sig = CURSIG(p)) != 0) {
295                 postsig(sig);
296         }
297
298         /*
299          * If a reschedule has been requested then we release the current
300          * process in order to shift our P_CURPROC designation to another
301          * user process.  userexit() will reacquire P_CURPROC and block
302          * there.
303          */
304         if (resched_wanted()) {
305                 p->p_thread->td_release = NULL;
306                 if ((p->p_flag & P_CP_RELEASED) == 0) {
307                         p->p_flag |= P_CP_RELEASED;
308                         lwkt_setpri_self(TDPRI_KERN_USER);
309                 }
310                 if (p->p_flag & P_CURPROC) {
311                         release_curproc(p);
312                 } else {
313                         clear_resched();
314                 }
315         }
316
317         /*
318          * Charge system time if profiling.  Note: times are in microseconds.
319          */
320         if (p->p_flag & P_PROFIL) {
321                 addupc_task(p, frame->tf_eip, 
322                     (u_int)(curthread->td_sticks - oticks));
323         }
324
325         /*
326          * Post any pending signals XXX
327          */
328         while ((sig = CURSIG(p)) != 0)
329                 postsig(sig);
330 }
331
332 #ifdef DEVICE_POLLING
333 extern u_int32_t poll_in_trap;
334 extern int ether_poll (int count);
335 #endif /* DEVICE_POLLING */
336
337 /*
338  * Exception, fault, and trap interface to the FreeBSD kernel.
339  * This common code is called from assembly language IDT gate entry
340  * routines that prepare a suitable stack frame, and restore this
341  * frame after the exception has been processed.
342  *
343  * This function is also called from doreti in an interlock to handle ASTs.
344  * For example:  hardwareint->INTROUTINE->(set ast)->doreti->trap
345  *
346  * NOTE!  We have to retrieve the fault address prior to obtaining the
347  * MP lock because get_mplock() may switch out.  YYY cr2 really ought
348  * to be retrieved by the assembly code, not here.
349  */
350 void
351 trap(frame)
352         struct trapframe frame;
353 {
354         struct thread *td = curthread;
355         struct proc *p;
356         u_quad_t sticks = 0;
357         int i = 0, ucode = 0, type, code;
358         vm_offset_t eva;
359
360         p = td->td_proc;
361 #ifdef DDB
362         if (db_active) {
363                 eva = (frame.tf_trapno == T_PAGEFLT ? rcr2() : 0);
364                 get_mplock();
365                 trap_fatal(&frame, eva);
366                 goto out2;
367         }
368 #endif
369
370         eva = 0;
371         if (frame.tf_trapno == T_PAGEFLT) {
372                 /*
373                  * For some Cyrix CPUs, %cr2 is clobbered by interrupts.
374                  * This problem is worked around by using an interrupt
375                  * gate for the pagefault handler.  We are finally ready
376                  * to read %cr2 and then must reenable interrupts.
377                  *
378                  * XXX this should be in the switch statement, but the
379                  * NO_FOOF_HACK and VM86 goto and ifdefs obfuscate the
380                  * flow of control too much for this to be obviously
381                  * correct.
382                  */
383                 eva = rcr2();
384                 get_mplock();
385                 cpu_enable_intr();
386         } else {
387                 get_mplock();
388         }
389         /*
390          * MP lock is held at this point
391          */
392
393         if (!(frame.tf_eflags & PSL_I)) {
394                 /*
395                  * Buggy application or kernel code has disabled interrupts
396                  * and then trapped.  Enabling interrupts now is wrong, but
397                  * it is better than running with interrupts disabled until
398                  * they are accidentally enabled later.
399                  */
400                 type = frame.tf_trapno;
401                 if (ISPL(frame.tf_cs)==SEL_UPL || (frame.tf_eflags & PSL_VM)) {
402                         printf(
403                             "pid %ld (%s): trap %d with interrupts disabled\n",
404                             (long)curproc->p_pid, curproc->p_comm, type);
405                 } else if (type != T_BPTFLT && type != T_TRCTRAP) {
406                         /*
407                          * XXX not quite right, since this may be for a
408                          * multiple fault in user mode.
409                          */
410                         printf("kernel trap %d with interrupts disabled\n",
411                             type);
412                 }
413                 cpu_enable_intr();
414         }
415
416
417 #ifdef DEVICE_POLLING
418         if (poll_in_trap)
419                 ether_poll(poll_in_trap);
420 #endif /* DEVICE_POLLING */
421
422 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
423 restart:
424 #endif
425         type = frame.tf_trapno;
426         code = frame.tf_err;
427
428         if (in_vm86call) {
429                 if (frame.tf_eflags & PSL_VM &&
430                     (type == T_PROTFLT || type == T_STKFLT)) {
431 #ifdef SMP
432                         KKASSERT(curthread->td_mpcount > 0);
433 #endif
434                         i = vm86_emulate((struct vm86frame *)&frame);
435 #ifdef SMP
436                         KKASSERT(curthread->td_mpcount > 0);
437 #endif
438                         if (i != 0) {
439                                 /*
440                                  * returns to original process
441                                  */
442                                 vm86_trap((struct vm86frame *)&frame);
443                                 KKASSERT(0);
444                         }
445                         goto out2;
446                 }
447                 switch (type) {
448                         /*
449                          * these traps want either a process context, or
450                          * assume a normal userspace trap.
451                          */
452                 case T_PROTFLT:
453                 case T_SEGNPFLT:
454                         trap_fatal(&frame, eva);
455                         goto out2;
456                 case T_TRCTRAP:
457                         type = T_BPTFLT;        /* kernel breakpoint */
458                         /* FALL THROUGH */
459                 }
460                 goto kernel_trap;       /* normal kernel trap handling */
461         }
462
463         if ((ISPL(frame.tf_cs) == SEL_UPL) || (frame.tf_eflags & PSL_VM)) {
464                 /* user trap */
465
466                 userenter(td);
467
468                 sticks = curthread->td_sticks;
469                 p->p_md.md_regs = &frame;
470
471                 switch (type) {
472                 case T_PRIVINFLT:       /* privileged instruction fault */
473                         ucode = type;
474                         i = SIGILL;
475                         break;
476
477                 case T_BPTFLT:          /* bpt instruction fault */
478                 case T_TRCTRAP:         /* trace trap */
479                         frame.tf_eflags &= ~PSL_T;
480                         i = SIGTRAP;
481                         break;
482
483                 case T_ARITHTRAP:       /* arithmetic trap */
484                         ucode = code;
485                         i = SIGFPE;
486                         break;
487
488                 case T_ASTFLT:          /* Allow process switch */
489                         mycpu->gd_cnt.v_soft++;
490                         if (mycpu->gd_reqflags & RQF_AST_OWEUPC) {
491                                 atomic_clear_int_nonlocked(&mycpu->gd_reqflags,
492                                             RQF_AST_OWEUPC);
493                                 addupc_task(p, p->p_stats->p_prof.pr_addr,
494                                             p->p_stats->p_prof.pr_ticks);
495                         }
496                         goto out;
497
498                         /*
499                          * The following two traps can happen in
500                          * vm86 mode, and, if so, we want to handle
501                          * them specially.
502                          */
503                 case T_PROTFLT:         /* general protection fault */
504                 case T_STKFLT:          /* stack fault */
505                         if (frame.tf_eflags & PSL_VM) {
506                                 i = vm86_emulate((struct vm86frame *)&frame);
507                                 if (i == 0)
508                                         goto out;
509                                 break;
510                         }
511                         /* FALL THROUGH */
512
513                 case T_SEGNPFLT:        /* segment not present fault */
514                 case T_TSSFLT:          /* invalid TSS fault */
515                 case T_DOUBLEFLT:       /* double fault */
516                 default:
517                         ucode = code + BUS_SEGM_FAULT ;
518                         i = SIGBUS;
519                         break;
520
521                 case T_PAGEFLT:         /* page fault */
522                         i = trap_pfault(&frame, TRUE, eva);
523                         if (i == -1)
524                                 goto out;
525 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
526                         if (i == -2)
527                                 goto restart;
528 #endif
529                         if (i == 0)
530                                 goto out;
531
532                         ucode = T_PAGEFLT;
533                         break;
534
535                 case T_DIVIDE:          /* integer divide fault */
536                         ucode = FPE_INTDIV;
537                         i = SIGFPE;
538                         break;
539
540 #if NISA > 0
541                 case T_NMI:
542 #ifdef POWERFAIL_NMI
543                         goto handle_powerfail;
544 #else /* !POWERFAIL_NMI */
545                         /* machine/parity/power fail/"kitchen sink" faults */
546                         if (isa_nmi(code) == 0) {
547 #ifdef DDB
548                                 /*
549                                  * NMI can be hooked up to a pushbutton
550                                  * for debugging.
551                                  */
552                                 if (ddb_on_nmi) {
553                                         printf ("NMI ... going to debugger\n");
554                                         kdb_trap (type, 0, &frame);
555                                 }
556 #endif /* DDB */
557                                 goto out2;
558                         } else if (panic_on_nmi)
559                                 panic("NMI indicates hardware failure");
560                         break;
561 #endif /* POWERFAIL_NMI */
562 #endif /* NISA > 0 */
563
564                 case T_OFLOW:           /* integer overflow fault */
565                         ucode = FPE_INTOVF;
566                         i = SIGFPE;
567                         break;
568
569                 case T_BOUND:           /* bounds check fault */
570                         ucode = FPE_FLTSUB;
571                         i = SIGFPE;
572                         break;
573
574                 case T_DNA:
575 #if NNPX > 0
576                         /* if a transparent fault (due to context switch "late") */
577                         if (npxdna())
578                                 goto out;
579 #endif
580                         if (!pmath_emulate) {
581                                 i = SIGFPE;
582                                 ucode = FPE_FPU_NP_TRAP;
583                                 break;
584                         }
585                         i = (*pmath_emulate)(&frame);
586                         if (i == 0) {
587                                 if (!(frame.tf_eflags & PSL_T))
588                                         goto out2;
589                                 frame.tf_eflags &= ~PSL_T;
590                                 i = SIGTRAP;
591                         }
592                         /* else ucode = emulator_only_knows() XXX */
593                         break;
594
595                 case T_FPOPFLT:         /* FPU operand fetch fault */
596                         ucode = T_FPOPFLT;
597                         i = SIGILL;
598                         break;
599
600                 case T_XMMFLT:          /* SIMD floating-point exception */
601                         ucode = 0; /* XXX */
602                         i = SIGFPE;
603                         break;
604                 }
605         } else {
606 kernel_trap:
607                 /* kernel trap */
608
609                 switch (type) {
610                 case T_PAGEFLT:                 /* page fault */
611                         (void) trap_pfault(&frame, FALSE, eva);
612                         goto out2;
613
614                 case T_DNA:
615 #if NNPX > 0
616                         /*
617                          * The kernel is apparently using npx for copying.
618                          * XXX this should be fatal unless the kernel has
619                          * registered such use.
620                          */
621                         if (npxdna())
622                                 goto out2;
623 #endif
624                         break;
625
626                 case T_PROTFLT:         /* general protection fault */
627                 case T_SEGNPFLT:        /* segment not present fault */
628                         /*
629                          * Invalid segment selectors and out of bounds
630                          * %eip's and %esp's can be set up in user mode.
631                          * This causes a fault in kernel mode when the
632                          * kernel tries to return to user mode.  We want
633                          * to get this fault so that we can fix the
634                          * problem here and not have to check all the
635                          * selectors and pointers when the user changes
636                          * them.
637                          */
638 #define MAYBE_DORETI_FAULT(where, whereto)                              \
639         do {                                                            \
640                 if (frame.tf_eip == (int)where) {                       \
641                         frame.tf_eip = (int)whereto;                    \
642                         goto out2;                                      \
643                 }                                                       \
644         } while (0)
645                         /*
646                          * Since we don't save %gs across an interrupt
647                          * frame this check must occur outside the intr
648                          * nesting level check.
649                          */
650                         if (frame.tf_eip == (int)cpu_switch_load_gs) {
651                                 curthread->td_pcb->pcb_gs = 0;
652                                 psignal(p, SIGBUS);
653                                 goto out2;
654                         }
655                         if (mycpu->gd_intr_nesting_level == 0) {
656                                 /*
657                                  * Invalid %fs's and %gs's can be created using
658                                  * procfs or PT_SETREGS or by invalidating the
659                                  * underlying LDT entry.  This causes a fault
660                                  * in kernel mode when the kernel attempts to
661                                  * switch contexts.  Lose the bad context
662                                  * (XXX) so that we can continue, and generate
663                                  * a signal.
664                                  */
665                                 MAYBE_DORETI_FAULT(doreti_iret,
666                                                    doreti_iret_fault);
667                                 MAYBE_DORETI_FAULT(doreti_popl_ds,
668                                                    doreti_popl_ds_fault);
669                                 MAYBE_DORETI_FAULT(doreti_popl_es,
670                                                    doreti_popl_es_fault);
671                                 MAYBE_DORETI_FAULT(doreti_popl_fs,
672                                                    doreti_popl_fs_fault);
673                                 if (curthread->td_pcb->pcb_onfault) {
674                                         frame.tf_eip = (int)curthread->td_pcb->pcb_onfault;
675                                         goto out2;
676                                 }
677                         }
678                         break;
679
680                 case T_TSSFLT:
681                         /*
682                          * PSL_NT can be set in user mode and isn't cleared
683                          * automatically when the kernel is entered.  This
684                          * causes a TSS fault when the kernel attempts to
685                          * `iret' because the TSS link is uninitialized.  We
686                          * want to get this fault so that we can fix the
687                          * problem here and not every time the kernel is
688                          * entered.
689                          */
690                         if (frame.tf_eflags & PSL_NT) {
691                                 frame.tf_eflags &= ~PSL_NT;
692                                 goto out2;
693                         }
694                         break;
695
696                 case T_TRCTRAP:  /* trace trap */
697                         if (frame.tf_eip == (int)IDTVEC(syscall)) {
698                                 /*
699                                  * We've just entered system mode via the
700                                  * syscall lcall.  Continue single stepping
701                                  * silently until the syscall handler has
702                                  * saved the flags.
703                                  */
704                                 goto out2;
705                         }
706                         if (frame.tf_eip == (int)IDTVEC(syscall) + 1) {
707                                 /*
708                                  * The syscall handler has now saved the
709                                  * flags.  Stop single stepping it.
710                                  */
711                                 frame.tf_eflags &= ~PSL_T;
712                                 goto out2;
713                         }
714                         /*
715                          * Ignore debug register trace traps due to
716                          * accesses in the user's address space, which
717                          * can happen under several conditions such as
718                          * if a user sets a watchpoint on a buffer and
719                          * then passes that buffer to a system call.
720                          * We still want to get TRCTRAPS for addresses
721                          * in kernel space because that is useful when
722                          * debugging the kernel.
723                          */
724                         if (user_dbreg_trap()) {
725                                 /*
726                                  * Reset breakpoint bits because the
727                                  * processor doesn't
728                                  */
729                                 load_dr6(rdr6() & 0xfffffff0);
730                                 goto out2;
731                         }
732                         /*
733                          * Fall through (TRCTRAP kernel mode, kernel address)
734                          */
735                 case T_BPTFLT:
736                         /*
737                          * If DDB is enabled, let it handle the debugger trap.
738                          * Otherwise, debugger traps "can't happen".
739                          */
740 #ifdef DDB
741                         if (kdb_trap (type, 0, &frame))
742                                 goto out2;
743 #endif
744                         break;
745
746 #if NISA > 0
747                 case T_NMI:
748 #ifdef POWERFAIL_NMI
749 #ifndef TIMER_FREQ
750 #  define TIMER_FREQ 1193182
751 #endif
752         handle_powerfail:
753                 {
754                   static unsigned lastalert = 0;
755
756                   if(time_second - lastalert > 10)
757                     {
758                       log(LOG_WARNING, "NMI: power fail\n");
759                       sysbeep(TIMER_FREQ/880, hz);
760                       lastalert = time_second;
761                     }
762                     /* YYY mp count */
763                   goto out2;
764                 }
765 #else /* !POWERFAIL_NMI */
766                         /* machine/parity/power fail/"kitchen sink" faults */
767                         if (isa_nmi(code) == 0) {
768 #ifdef DDB
769                                 /*
770                                  * NMI can be hooked up to a pushbutton
771                                  * for debugging.
772                                  */
773                                 if (ddb_on_nmi) {
774                                         printf ("NMI ... going to debugger\n");
775                                         kdb_trap (type, 0, &frame);
776                                 }
777 #endif /* DDB */
778                                 goto out2;
779                         } else if (panic_on_nmi == 0)
780                                 goto out2;
781                         /* FALL THROUGH */
782 #endif /* POWERFAIL_NMI */
783 #endif /* NISA > 0 */
784                 }
785
786                 trap_fatal(&frame, eva);
787                 goto out2;
788         }
789
790         /* Translate fault for emulators (e.g. Linux) */
791         if (*p->p_sysent->sv_transtrap)
792                 i = (*p->p_sysent->sv_transtrap)(i, type);
793
794         trapsignal(p, i, ucode);
795
796 #ifdef DEBUG
797         if (type <= MAX_TRAP_MSG) {
798                 uprintf("fatal process exception: %s",
799                         trap_msg[type]);
800                 if ((type == T_PAGEFLT) || (type == T_PROTFLT))
801                         uprintf(", fault VA = 0x%lx", (u_long)eva);
802                 uprintf("\n");
803         }
804 #endif
805
806 out:
807 #ifdef SMP
808         if (ISPL(frame.tf_cs) == SEL_UPL)
809                 KASSERT(curthread->td_mpcount == 1, ("badmpcount trap from %p", (void *)frame.tf_eip));
810 #endif
811         userret(p, &frame, sticks);
812         userexit(p);
813 out2:
814 #ifdef SMP
815         KKASSERT(curthread->td_mpcount > 0);
816 #endif
817         rel_mplock();
818 }
819
820 #ifdef notyet
821 /*
822  * This version doesn't allow a page fault to user space while
823  * in the kernel. The rest of the kernel needs to be made "safe"
824  * before this can be used. I think the only things remaining
825  * to be made safe are the iBCS2 code and the process tracing/
826  * debugging code.
827  */
828 static int
829 trap_pfault(frame, usermode, eva)
830         struct trapframe *frame;
831         int usermode;
832         vm_offset_t eva;
833 {
834         vm_offset_t va;
835         struct vmspace *vm = NULL;
836         vm_map_t map = 0;
837         int rv = 0;
838         vm_prot_t ftype;
839         struct proc *p = curproc;
840
841         if (frame->tf_err & PGEX_W)
842                 ftype = VM_PROT_WRITE;
843         else
844                 ftype = VM_PROT_READ;
845
846         va = trunc_page(eva);
847         if (va < VM_MIN_KERNEL_ADDRESS) {
848                 vm_offset_t v;
849                 vm_page_t mpte;
850
851                 if (p == NULL ||
852                     (!usermode && va < VM_MAXUSER_ADDRESS &&
853                      (mycpu->gd_intr_nesting_level != 0 || 
854                       curthread->td_pcb->pcb_onfault == NULL))) {
855                         trap_fatal(frame, eva);
856                         return (-1);
857                 }
858
859                 /*
860                  * This is a fault on non-kernel virtual memory.
861                  * vm is initialized above to NULL. If curproc is NULL
862                  * or curproc->p_vmspace is NULL the fault is fatal.
863                  */
864                 vm = p->p_vmspace;
865                 if (vm == NULL)
866                         goto nogo;
867
868                 map = &vm->vm_map;
869
870                 /*
871                  * Keep swapout from messing with us during this
872                  *      critical time.
873                  */
874                 ++p->p_lock;
875
876                 /*
877                  * Grow the stack if necessary
878                  */
879                 /* grow_stack returns false only if va falls into
880                  * a growable stack region and the stack growth
881                  * fails.  It returns true if va was not within
882                  * a growable stack region, or if the stack 
883                  * growth succeeded.
884                  */
885                 if (!grow_stack (p, va)) {
886                         rv = KERN_FAILURE;
887                         --p->p_lock;
888                         goto nogo;
889                 }
890                 
891                 /* Fault in the user page: */
892                 rv = vm_fault(map, va, ftype,
893                               (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY
894                                                       : VM_FAULT_NORMAL);
895
896                 --p->p_lock;
897         } else {
898                 /*
899                  * Don't allow user-mode faults in kernel address space.
900                  */
901                 if (usermode)
902                         goto nogo;
903
904                 /*
905                  * Since we know that kernel virtual address addresses
906                  * always have pte pages mapped, we just have to fault
907                  * the page.
908                  */
909                 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
910         }
911
912         if (rv == KERN_SUCCESS)
913                 return (0);
914 nogo:
915         if (!usermode) {
916                 if (mycpu->gd_intr_nesting_level == 0 && curthread->td_pcb->pcb_onfault) {
917                         frame->tf_eip = (int)curthread->td_pcb->pcb_onfault;
918                         return (0);
919                 }
920                 trap_fatal(frame, eva);
921                 return (-1);
922         }
923
924         /* kludge to pass faulting virtual address to sendsig */
925         frame->tf_err = eva;
926
927         return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
928 }
929 #endif
930
931 int
932 trap_pfault(frame, usermode, eva)
933         struct trapframe *frame;
934         int usermode;
935         vm_offset_t eva;
936 {
937         vm_offset_t va;
938         struct vmspace *vm = NULL;
939         vm_map_t map = 0;
940         int rv = 0;
941         vm_prot_t ftype;
942         struct proc *p = curproc;
943
944         va = trunc_page(eva);
945         if (va >= KERNBASE) {
946                 /*
947                  * Don't allow user-mode faults in kernel address space.
948                  * An exception:  if the faulting address is the invalid
949                  * instruction entry in the IDT, then the Intel Pentium
950                  * F00F bug workaround was triggered, and we need to
951                  * treat it is as an illegal instruction, and not a page
952                  * fault.
953                  */
954 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
955                 if ((eva == (unsigned int)&idt[6]) && has_f00f_bug) {
956                         frame->tf_trapno = T_PRIVINFLT;
957                         return -2;
958                 }
959 #endif
960                 if (usermode)
961                         goto nogo;
962
963                 map = kernel_map;
964         } else {
965                 /*
966                  * This is a fault on non-kernel virtual memory.
967                  * vm is initialized above to NULL. If curproc is NULL
968                  * or curproc->p_vmspace is NULL the fault is fatal.
969                  */
970                 if (p != NULL)
971                         vm = p->p_vmspace;
972
973                 if (vm == NULL)
974                         goto nogo;
975
976                 map = &vm->vm_map;
977         }
978
979         if (frame->tf_err & PGEX_W)
980                 ftype = VM_PROT_WRITE;
981         else
982                 ftype = VM_PROT_READ;
983
984         if (map != kernel_map) {
985                 /*
986                  * Keep swapout from messing with us during this
987                  *      critical time.
988                  */
989                 ++p->p_lock;
990
991                 /*
992                  * Grow the stack if necessary
993                  */
994                 /* grow_stack returns false only if va falls into
995                  * a growable stack region and the stack growth
996                  * fails.  It returns true if va was not within
997                  * a growable stack region, or if the stack 
998                  * growth succeeded.
999                  */
1000                 if (!grow_stack (p, va)) {
1001                         rv = KERN_FAILURE;
1002                         --p->p_lock;
1003                         goto nogo;
1004                 }
1005
1006                 /* Fault in the user page: */
1007                 rv = vm_fault(map, va, ftype,
1008                               (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY
1009                                                       : VM_FAULT_NORMAL);
1010
1011                 --p->p_lock;
1012         } else {
1013                 /*
1014                  * Don't have to worry about process locking or stacks in the kernel.
1015                  */
1016                 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
1017         }
1018
1019         if (rv == KERN_SUCCESS)
1020                 return (0);
1021 nogo:
1022         if (!usermode) {
1023                 if (mycpu->gd_intr_nesting_level == 0 && curthread->td_pcb->pcb_onfault) {
1024                         frame->tf_eip = (int)curthread->td_pcb->pcb_onfault;
1025                         return (0);
1026                 }
1027                 trap_fatal(frame, eva);
1028                 return (-1);
1029         }
1030
1031         /* kludge to pass faulting virtual address to sendsig */
1032         frame->tf_err = eva;
1033
1034         return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
1035 }
1036
1037 static void
1038 trap_fatal(frame, eva)
1039         struct trapframe *frame;
1040         vm_offset_t eva;
1041 {
1042         int code, type, ss, esp;
1043         struct soft_segment_descriptor softseg;
1044
1045         code = frame->tf_err;
1046         type = frame->tf_trapno;
1047         sdtossd(&gdt[mycpu->gd_cpuid * NGDT + IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
1048
1049         if (type <= MAX_TRAP_MSG)
1050                 printf("\n\nFatal trap %d: %s while in %s mode\n",
1051                         type, trap_msg[type],
1052                         frame->tf_eflags & PSL_VM ? "vm86" :
1053                         ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
1054 #ifdef SMP
1055         /* three separate prints in case of a trap on an unmapped page */
1056         printf("mp_lock = %08x; ", mp_lock);
1057         printf("cpuid = %d; ", mycpu->gd_cpuid);
1058         printf("lapic.id = %08x\n", lapic.id);
1059 #endif
1060         if (type == T_PAGEFLT) {
1061                 printf("fault virtual address   = 0x%x\n", eva);
1062                 printf("fault code              = %s %s, %s\n",
1063                         code & PGEX_U ? "user" : "supervisor",
1064                         code & PGEX_W ? "write" : "read",
1065                         code & PGEX_P ? "protection violation" : "page not present");
1066         }
1067         printf("instruction pointer     = 0x%x:0x%x\n",
1068                frame->tf_cs & 0xffff, frame->tf_eip);
1069         if ((ISPL(frame->tf_cs) == SEL_UPL) || (frame->tf_eflags & PSL_VM)) {
1070                 ss = frame->tf_ss & 0xffff;
1071                 esp = frame->tf_esp;
1072         } else {
1073                 ss = GSEL(GDATA_SEL, SEL_KPL);
1074                 esp = (int)&frame->tf_esp;
1075         }
1076         printf("stack pointer           = 0x%x:0x%x\n", ss, esp);
1077         printf("frame pointer           = 0x%x:0x%x\n", ss, frame->tf_ebp);
1078         printf("code segment            = base 0x%x, limit 0x%x, type 0x%x\n",
1079                softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
1080         printf("                        = DPL %d, pres %d, def32 %d, gran %d\n",
1081                softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32,
1082                softseg.ssd_gran);
1083         printf("processor eflags        = ");
1084         if (frame->tf_eflags & PSL_T)
1085                 printf("trace trap, ");
1086         if (frame->tf_eflags & PSL_I)
1087                 printf("interrupt enabled, ");
1088         if (frame->tf_eflags & PSL_NT)
1089                 printf("nested task, ");
1090         if (frame->tf_eflags & PSL_RF)
1091                 printf("resume, ");
1092         if (frame->tf_eflags & PSL_VM)
1093                 printf("vm86, ");
1094         printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12);
1095         printf("current process         = ");
1096         if (curproc) {
1097                 printf("%lu (%s)\n",
1098                     (u_long)curproc->p_pid, curproc->p_comm ?
1099                     curproc->p_comm : "");
1100         } else {
1101                 printf("Idle\n");
1102         }
1103         printf("current thread          = pri %d ", curthread->td_pri);
1104         if (curthread->td_pri >= TDPRI_CRIT)
1105                 printf("(CRIT)");
1106         printf("\n");
1107         printf("interrupt mask          = ");
1108         if ((curthread->td_cpl & net_imask) == net_imask)
1109                 printf("net ");
1110         if ((curthread->td_cpl & tty_imask) == tty_imask)
1111                 printf("tty ");
1112         if ((curthread->td_cpl & bio_imask) == bio_imask)
1113                 printf("bio ");
1114         if ((curthread->td_cpl & cam_imask) == cam_imask)
1115                 printf("cam ");
1116         if (curthread->td_cpl == 0)
1117                 printf("none");
1118 #ifdef SMP
1119 /**
1120  *  XXX FIXME:
1121  *      we probably SHOULD have stopped the other CPUs before now!
1122  *      another CPU COULD have been touching cpl at this moment...
1123  */
1124         printf(" <- SMP: XXX");
1125 #endif
1126         printf("\n");
1127
1128 #ifdef KDB
1129         if (kdb_trap(&psl))
1130                 return;
1131 #endif
1132 #ifdef DDB
1133         if ((debugger_on_panic || db_active) && kdb_trap(type, code, frame))
1134                 return;
1135 #endif
1136         printf("trap number             = %d\n", type);
1137         if (type <= MAX_TRAP_MSG)
1138                 panic("%s", trap_msg[type]);
1139         else
1140                 panic("unknown/reserved trap");
1141 }
1142
1143 /*
1144  * Double fault handler. Called when a fault occurs while writing
1145  * a frame for a trap/exception onto the stack. This usually occurs
1146  * when the stack overflows (such is the case with infinite recursion,
1147  * for example).
1148  *
1149  * XXX Note that the current PTD gets replaced by IdlePTD when the
1150  * task switch occurs. This means that the stack that was active at
1151  * the time of the double fault is not available at <kstack> unless
1152  * the machine was idle when the double fault occurred. The downside
1153  * of this is that "trace <ebp>" in ddb won't work.
1154  */
1155 void
1156 dblfault_handler()
1157 {
1158         struct mdglobaldata *gd = mdcpu;
1159
1160         printf("\nFatal double fault:\n");
1161         printf("eip = 0x%x\n", gd->gd_common_tss.tss_eip);
1162         printf("esp = 0x%x\n", gd->gd_common_tss.tss_esp);
1163         printf("ebp = 0x%x\n", gd->gd_common_tss.tss_ebp);
1164 #ifdef SMP
1165         /* three separate prints in case of a trap on an unmapped page */
1166         printf("mp_lock = %08x; ", mp_lock);
1167         printf("cpuid = %d; ", mycpu->gd_cpuid);
1168         printf("lapic.id = %08x\n", lapic.id);
1169 #endif
1170         panic("double fault");
1171 }
1172
1173 /*
1174  * Compensate for 386 brain damage (missing URKR).
1175  * This is a little simpler than the pagefault handler in trap() because
1176  * it the page tables have already been faulted in and high addresses
1177  * are thrown out early for other reasons.
1178  */
1179 int trapwrite(addr)
1180         unsigned addr;
1181 {
1182         struct proc *p;
1183         vm_offset_t va;
1184         struct vmspace *vm;
1185         int rv;
1186
1187         va = trunc_page((vm_offset_t)addr);
1188         /*
1189          * XXX - MAX is END.  Changed > to >= for temp. fix.
1190          */
1191         if (va >= VM_MAXUSER_ADDRESS)
1192                 return (1);
1193
1194         p = curproc;
1195         vm = p->p_vmspace;
1196
1197         ++p->p_lock;
1198
1199         if (!grow_stack (p, va)) {
1200                 --p->p_lock;
1201                 return (1);
1202         }
1203
1204         /*
1205          * fault the data page
1206          */
1207         rv = vm_fault(&vm->vm_map, va, VM_PROT_WRITE, VM_FAULT_DIRTY);
1208
1209         --p->p_lock;
1210
1211         if (rv != KERN_SUCCESS)
1212                 return 1;
1213
1214         return (0);
1215 }
1216
1217 /*
1218  *      syscall2 -      MP aware system call request C handler
1219  *
1220  *      A system call is essentially treated as a trap except that the
1221  *      MP lock is not held on entry or return.  We are responsible for
1222  *      obtaining the MP lock if necessary and for handling ASTs
1223  *      (e.g. a task switch) prior to return.
1224  *
1225  *      In general, only simple access and manipulation of curproc and
1226  *      the current stack is allowed without having to hold MP lock.
1227  */
1228 void
1229 syscall2(struct trapframe frame)
1230 {
1231         struct thread *td = curthread;
1232         struct proc *p = td->td_proc;
1233         caddr_t params;
1234         int i;
1235         struct sysent *callp;
1236         register_t orig_tf_eflags;
1237         u_quad_t sticks;
1238         int error;
1239         int narg;
1240         u_int code;
1241         union sysunion args;
1242
1243 #ifdef DIAGNOSTIC
1244         if (ISPL(frame.tf_cs) != SEL_UPL) {
1245                 get_mplock();
1246                 panic("syscall");
1247                 /* NOT REACHED */
1248         }
1249 #endif
1250
1251 #ifdef SMP
1252         KASSERT(curthread->td_mpcount == 0, ("badmpcount syscall from %p", (void *)frame.tf_eip));
1253         get_mplock();
1254 #endif
1255         /*
1256          * access non-atomic field from critical section.  p_sticks is
1257          * updated by the clock interrupt.  Also use this opportunity
1258          * to lazy-raise our LWKT priority.
1259          */
1260         userenter(td);
1261         crit_enter_quick(td);
1262         sticks = curthread->td_sticks;
1263         crit_exit_quick(td);
1264
1265         p->p_md.md_regs = &frame;
1266         params = (caddr_t)frame.tf_esp + sizeof(int);
1267         code = frame.tf_eax;
1268         orig_tf_eflags = frame.tf_eflags;
1269
1270         if (p->p_sysent->sv_prepsyscall) {
1271                 /*
1272                  * The prep code is not MP aware.
1273                  */
1274                 (*p->p_sysent->sv_prepsyscall)(&frame, (int *)(&args.nosys.usrmsg + 1), &code, &params);
1275         } else {
1276                 /*
1277                  * Need to check if this is a 32 bit or 64 bit syscall.
1278                  * fuword is MP aware.
1279                  */
1280                 if (code == SYS_syscall) {
1281                         /*
1282                          * Code is first argument, followed by actual args.
1283                          */
1284                         code = fuword(params);
1285                         params += sizeof(int);
1286                 } else if (code == SYS___syscall) {
1287                         /*
1288                          * Like syscall, but code is a quad, so as to maintain
1289                          * quad alignment for the rest of the arguments.
1290                          */
1291                         code = fuword(params);
1292                         params += sizeof(quad_t);
1293                 }
1294         }
1295
1296         if (p->p_sysent->sv_mask)
1297                 code &= p->p_sysent->sv_mask;
1298
1299         if (code >= p->p_sysent->sv_size)
1300                 callp = &p->p_sysent->sv_table[0];
1301         else
1302                 callp = &p->p_sysent->sv_table[code];
1303
1304         narg = callp->sy_narg & SYF_ARGMASK;
1305
1306         /*
1307          * copyin is MP aware, but the tracing code is not
1308          */
1309         if (params && (i = narg * sizeof(register_t)) &&
1310             (error = copyin(params, (caddr_t)(&args.nosys.usrmsg + 1), (u_int)i))) {
1311 #ifdef KTRACE
1312                 if (KTRPOINT(td, KTR_SYSCALL))
1313                         ktrsyscall(p->p_tracep, code, narg, (void *)(&args.nosys.usrmsg + 1));
1314 #endif
1315                 goto bad;
1316         }
1317
1318 #if 0
1319         /*
1320          * Try to run the syscall without the MP lock if the syscall
1321          * is MP safe.  We have to obtain the MP lock no matter what if 
1322          * we are ktracing
1323          */
1324         if ((callp->sy_narg & SYF_MPSAFE) == 0) {
1325                 get_mplock();
1326                 have_mplock = 1;
1327         }
1328 #endif
1329
1330 #ifdef KTRACE
1331         if (KTRPOINT(td, KTR_SYSCALL)) {
1332                 ktrsyscall(p->p_tracep, code, narg, (void *)(&args.nosys.usrmsg + 1));
1333         }
1334 #endif
1335
1336         /*
1337          * For traditional syscall code edx is left untouched when 32 bit
1338          * results are returned.  Since edx is loaded from fds[1] when the 
1339          * system call returns we pre-set it here.
1340          */
1341         lwkt_initmsg_rp(&args.lmsg, &td->td_msgport, code);
1342         args.sysmsg_copyout = NULL;
1343         args.sysmsg_fds[0] = 0;
1344         args.sysmsg_fds[1] = frame.tf_edx;
1345
1346         STOPEVENT(p, S_SCE, narg);      /* MP aware */
1347
1348         error = (*callp->sy_call)(&args);
1349
1350         /*
1351          * MP SAFE (we may or may not have the MP lock at this point)
1352          */
1353         switch (error) {
1354         case 0:
1355                 /*
1356                  * Reinitialize proc pointer `p' as it may be different
1357                  * if this is a child returning from fork syscall.
1358                  */
1359                 p = curproc;
1360                 frame.tf_eax = args.sysmsg_fds[0];
1361                 frame.tf_edx = args.sysmsg_fds[1];
1362                 frame.tf_eflags &= ~PSL_C;
1363                 break;
1364         case ERESTART:
1365                 /*
1366                  * Reconstruct pc, assuming lcall $X,y is 7 bytes,
1367                  * int 0x80 is 2 bytes. We saved this in tf_err.
1368                  */
1369                 frame.tf_eip -= frame.tf_err;
1370                 break;
1371         case EJUSTRETURN:
1372                 break;
1373         case EASYNC:
1374                 panic("Unexpected EASYNC return value (for now)");
1375         default:
1376 bad:
1377                 if (p->p_sysent->sv_errsize) {
1378                         if (error >= p->p_sysent->sv_errsize)
1379                                 error = -1;     /* XXX */
1380                         else
1381                                 error = p->p_sysent->sv_errtbl[error];
1382                 }
1383                 frame.tf_eax = error;
1384                 frame.tf_eflags |= PSL_C;
1385                 break;
1386         }
1387
1388         /*
1389          * Traced syscall.  trapsignal() is not MP aware.
1390          */
1391         if ((orig_tf_eflags & PSL_T) && !(orig_tf_eflags & PSL_VM)) {
1392                 frame.tf_eflags &= ~PSL_T;
1393                 trapsignal(p, SIGTRAP, 0);
1394         }
1395
1396         /*
1397          * Handle reschedule and other end-of-syscall issues
1398          */
1399         userret(p, &frame, sticks);
1400
1401 #ifdef KTRACE
1402         if (KTRPOINT(td, KTR_SYSRET)) {
1403                 ktrsysret(p->p_tracep, code, error, args.sysmsg_result);
1404         }
1405 #endif
1406
1407         /*
1408          * This works because errno is findable through the
1409          * register set.  If we ever support an emulation where this
1410          * is not the case, this code will need to be revisited.
1411          */
1412         STOPEVENT(p, S_SCX, code);
1413
1414         userexit(p);
1415 #ifdef SMP
1416         /*
1417          * Release the MP lock if we had to get it
1418          */
1419         KASSERT(curthread->td_mpcount == 1, ("badmpcount syscall from %p", (void *)frame.tf_eip));
1420         rel_mplock();
1421 #endif
1422 }
1423
1424 /*
1425  *      sendsys2 -      MP aware system message request C handler
1426  */
1427 void
1428 sendsys2(struct trapframe frame)
1429 {
1430         struct globaldata *gd;
1431         struct thread *td = curthread;
1432         struct proc *p = td->td_proc;
1433         register_t orig_tf_eflags;
1434         struct sysent *callp;
1435         union sysunion *sysun;
1436         lwkt_msg_t umsg;
1437         u_quad_t sticks;
1438         int error;
1439         int narg;
1440         u_int code = 0;
1441         int msgsize;
1442         int result;
1443
1444 #ifdef DIAGNOSTIC
1445         if (ISPL(frame.tf_cs) != SEL_UPL) {
1446                 get_mplock();
1447                 panic("syscall");
1448                 /* NOT REACHED */
1449         }
1450 #endif
1451
1452 #ifdef SMP
1453         KASSERT(curthread->td_mpcount == 0, ("badmpcount syscall from %p", (void *)frame.tf_eip));
1454         get_mplock();
1455 #endif
1456         /*
1457          * access non-atomic field from critical section.  p_sticks is
1458          * updated by the clock interrupt.  Also use this opportunity
1459          * to lazy-raise our LWKT priority.
1460          */
1461         userenter(td);
1462         crit_enter_quick(td);
1463         sticks = curthread->td_sticks;
1464         crit_exit_quick(td);
1465
1466         p->p_md.md_regs = &frame;
1467         orig_tf_eflags = frame.tf_eflags;
1468         result = 0;
1469
1470         /*
1471          * Handle the waitport/waitmsg/checkport/checkmsg case
1472          *
1473          * YYY MOVE THIS TO INT 0x82!  We don't really need to combine it
1474          * with sendsys().
1475          */
1476         if ((msgsize = frame.tf_edx) <= 0) {
1477                 if (frame.tf_ecx) {
1478                         printf("waitmsg/checkmsg not yet supported: %08x\n",
1479                                 frame.tf_ecx);
1480                         error = ENOTSUP;
1481                         goto bad2;
1482                 }
1483                 if (frame.tf_eax) {
1484                         printf("waitport/checkport only the default port is supported at the moment\n");
1485                         error = ENOTSUP;
1486                         goto bad2;
1487                 }
1488                 switch(msgsize) {
1489                 case 0:
1490                         /*
1491                          * Wait on port for message
1492                          */
1493                         sysun = lwkt_getport(&td->td_msgport);
1494                         /* XXX block */
1495                         break;
1496                 case -1:
1497                         /*
1498                          * Test port for message
1499                          */
1500                         sysun = lwkt_getport(&td->td_msgport);
1501                         break;
1502                 default:
1503                         error = ENOSYS;
1504                         goto bad2;
1505                 }
1506                 if (sysun) {
1507                         gd = td->td_gd;
1508                         umsg = sysun->lmsg.opaque.ms_umsg;
1509                         frame.tf_eax = (register_t)umsg;
1510                         if (sysun->sysmsg_copyout)
1511                                 sysun->sysmsg_copyout(sysun);
1512                         atomic_add_int_nonlocked(&td->td_msgport.mp_refs, -1);
1513                         sysun->nosys.usrmsg.umsg.u.ms_fds[0] = sysun->lmsg.u.ms_fds[0];
1514                         sysun->nosys.usrmsg.umsg.u.ms_fds[1] = sysun->lmsg.u.ms_fds[1];
1515                         sysun->nosys.usrmsg.umsg.ms_error = sysun->lmsg.ms_error;
1516                         error = sysun->lmsg.ms_error;
1517                         result = sysun->lmsg.u.ms_fds[0]; /* for ktrace */
1518                         if (error != 0 || code != SYS_execve) {
1519                                 error = copyout(
1520                                             &sysun->nosys.usrmsg.umsg.ms_copyout_start,
1521                                             &umsg->ms_copyout_start,
1522                                             ms_copyout_size);
1523                         }
1524                         crit_enter_quick(td);
1525                         sysun->lmsg.opaque.ms_sysunnext = gd->gd_freesysun;
1526                         gd->gd_freesysun = sysun;
1527                         crit_exit_quick(td);
1528                 } else {
1529                         frame.tf_eax = 0;
1530                 }
1531                 frame.tf_edx = 0;
1532                 code = 0;
1533                 error = 0;
1534                 goto good;
1535         }
1536
1537         /*
1538          * Extract the system call message.  If msgsize is zero we are 
1539          * blocking on a message and/or message port.  If msgsize is -1 
1540          * we are testing a message for completion or a message port for
1541          * activity.
1542          *
1543          * The userland system call message size includes the size of the
1544          * userland lwkt_msg plus arguments.  We load it into the userland
1545          * portion of our sysunion structure then we initialize the kerneland
1546          * portion and go.
1547          */
1548
1549         /*
1550          * Bad message size
1551          */
1552         if (msgsize < sizeof(struct lwkt_msg) ||
1553             msgsize > sizeof(union sysunion) - sizeof(struct sysmsg)
1554         ) {
1555                 error = ENOSYS;
1556                 goto bad2;
1557         }
1558
1559         /*
1560          * Obtain a sysun from our per-cpu cache or allocate a new one.  Use
1561          * the opaque field to store the original (user) message pointer.
1562          * A critical section is necessary to interlock against interrupts
1563          * returning system messages to the thread cache.
1564          */
1565         gd = td->td_gd;
1566         crit_enter_quick(td);
1567         if ((sysun = gd->gd_freesysun) != NULL) {
1568                 gd->gd_freesysun = sysun->lmsg.opaque.ms_sysunnext;
1569                 crit_exit_quick(td);
1570         } else {
1571                 crit_exit_quick(td);
1572                 sysun = malloc(sizeof(union sysunion), M_SYSMSG, M_WAITOK);
1573         }
1574         atomic_add_int_nonlocked(&td->td_msgport.mp_refs, 1);
1575
1576         /*
1577          * Copy the user request into the kernel copy of the user request.
1578          */
1579         umsg = (void *)frame.tf_ecx;
1580         error = copyin(umsg, &sysun->nosys.usrmsg, msgsize);
1581         if (error)
1582                 goto bad1;
1583         if ((sysun->nosys.usrmsg.umsg.ms_flags & MSGF_ASYNC) &&
1584             (error = suser(td)) != 0
1585         ) {
1586                 goto bad1;
1587         }
1588
1589         /*
1590          * Initialize the kernel message from the copied-in data and
1591          * pull in appropriate flags from the userland message.
1592          */
1593         lwkt_initmsg_rp(&sysun->lmsg, &td->td_msgport, 
1594             sysun->nosys.usrmsg.umsg.ms_cmd);
1595         sysun->sysmsg_copyout = NULL;
1596         sysun->lmsg.opaque.ms_umsg = umsg;
1597         sysun->lmsg.ms_flags |= sysun->nosys.usrmsg.umsg.ms_flags & MSGF_ASYNC;
1598
1599         /*
1600          * Extract the system call number, lookup the system call, and
1601          * set the default return value.
1602          */
1603         code = (u_int)sysun->lmsg.ms_cmd;
1604         if (code >= p->p_sysent->sv_size) {
1605                 error = ENOSYS;
1606                 goto bad1;
1607         }
1608
1609         callp = &p->p_sysent->sv_table[code];
1610
1611         narg = (msgsize - sizeof(struct lwkt_msg)) / sizeof(register_t);
1612
1613 #ifdef KTRACE
1614         if (KTRPOINT(td, KTR_SYSCALL)) {
1615                 ktrsyscall(p->p_tracep, code, narg, (void *)(&sysun->nosys.usrmsg + 1));
1616         }
1617 #endif
1618         sysun->lmsg.u.ms_fds[0] = 0;
1619         sysun->lmsg.u.ms_fds[1] = 0;
1620
1621         STOPEVENT(p, S_SCE, narg);      /* MP aware */
1622
1623         /*
1624          * Make the system call.  An error code is always returned, results
1625          * are copied back via ms_result32 or ms_result64.  YYY temporary
1626          * stage copy p_retval[] into ms_result32/64
1627          *
1628          * NOTE!  XXX if this is a child returning from a fork curproc
1629          * might be different.  YYY huh? a child returning from a fork
1630          * should never 'return' from this call, it should go right to the
1631          * fork_trampoline function.
1632          */
1633         error = (*callp->sy_call)(sysun);
1634         gd = td->td_gd; /* RELOAD, might have switched cpus */
1635
1636 bad1:
1637         /*
1638          * If a synchronous return copy p_retval to ms_result64 and return
1639          * the sysmsg to the free pool.
1640          *
1641          * YYY Don't writeback message if execve() YYY
1642          */
1643         if (error != EASYNC) {
1644                 atomic_add_int_nonlocked(&td->td_msgport.mp_refs, -1);
1645                 sysun->nosys.usrmsg.umsg.u.ms_fds[0] = sysun->lmsg.u.ms_fds[0];
1646                 sysun->nosys.usrmsg.umsg.u.ms_fds[1] = sysun->lmsg.u.ms_fds[1];
1647                 result = sysun->nosys.usrmsg.umsg.u.ms_fds[0]; /* for ktrace */
1648                 if (error != 0 || code != SYS_execve) {
1649                         int error2;
1650                         error2 = copyout(&sysun->nosys.usrmsg.umsg.ms_copyout_start,
1651                                         &umsg->ms_copyout_start,
1652                                         ms_copyout_size);
1653                         if (error == 0)
1654                                 error2 = error;
1655                 }
1656                 crit_enter_quick(td);
1657                 sysun->lmsg.opaque.ms_sysunnext = gd->gd_freesysun;
1658                 gd->gd_freesysun = sysun;
1659                 crit_exit_quick(td);
1660         }
1661 bad2:
1662         frame.tf_eax = error;
1663 good:
1664
1665         /*
1666          * Traced syscall.  trapsignal() is not MP aware.
1667          */
1668         if ((orig_tf_eflags & PSL_T) && !(orig_tf_eflags & PSL_VM)) {
1669                 frame.tf_eflags &= ~PSL_T;
1670                 trapsignal(p, SIGTRAP, 0);
1671         }
1672
1673         /*
1674          * Handle reschedule and other end-of-syscall issues
1675          */
1676         userret(p, &frame, sticks);
1677
1678 #ifdef KTRACE
1679         if (KTRPOINT(td, KTR_SYSRET)) {
1680                 ktrsysret(p->p_tracep, code, error, result);
1681         }
1682 #endif
1683
1684         /*
1685          * This works because errno is findable through the
1686          * register set.  If we ever support an emulation where this
1687          * is not the case, this code will need to be revisited.
1688          */
1689         STOPEVENT(p, S_SCX, code);
1690
1691         userexit(p);
1692 #ifdef SMP
1693         /*
1694          * Release the MP lock if we had to get it
1695          */
1696         KASSERT(curthread->td_mpcount == 1, ("badmpcount syscall from %p", (void *)frame.tf_eip));
1697         rel_mplock();
1698 #endif
1699 }
1700
1701 /*
1702  * Simplified back end of syscall(), used when returning from fork()
1703  * directly into user mode.  MP lock is held on entry and should be
1704  * released on return.  This code will return back into the fork
1705  * trampoline code which then runs doreti.
1706  */
1707 void
1708 fork_return(p, frame)
1709         struct proc *p;
1710         struct trapframe frame;
1711 {
1712         frame.tf_eax = 0;               /* Child returns zero */
1713         frame.tf_eflags &= ~PSL_C;      /* success */
1714         frame.tf_edx = 1;
1715
1716         userret(p, &frame, 0);
1717 #ifdef KTRACE
1718         if (KTRPOINT(p->p_thread, KTR_SYSRET))
1719                 ktrsysret(p->p_tracep, SYS_fork, 0, 0);
1720 #endif
1721         p->p_flag |= P_PASSIVE_ACQ;
1722         userexit(p);
1723         p->p_flag &= ~P_PASSIVE_ACQ;
1724 #ifdef SMP
1725         KKASSERT(curthread->td_mpcount == 1);
1726         rel_mplock();
1727 #endif
1728 }
1729