kernel: Use DEVMETHOD_END in the drivers.
[dragonfly.git] / sys / platform / pc32 / isa / npx.c
1 /*-
2  * Copyright (c) 1990 William Jolitz.
3  * Copyright (c) 1991 The Regents of the University of California.
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. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by the University of
17  *      California, Berkeley and its contributors.
18  * 4. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *      from: @(#)npx.c 7.2 (Berkeley) 5/12/91
35  * $FreeBSD: src/sys/i386/isa/npx.c,v 1.80.2.3 2001/10/20 19:04:38 tegge Exp $
36  */
37
38 #include "opt_cpu.h"
39 #include "opt_debug_npx.h"
40 #include "opt_math_emulate.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/bus.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/sysctl.h>
49 #include <sys/proc.h>
50 #include <sys/rman.h>
51 #ifdef NPX_DEBUG
52 #include <sys/syslog.h>
53 #endif
54 #include <sys/signalvar.h>
55
56 #include <sys/thread2.h>
57 #include <sys/mplock2.h>
58
59 #include <machine/cputypes.h>
60 #include <machine/frame.h>
61 #include <machine/ipl.h>
62 #include <machine/md_var.h>
63 #include <machine/pcb.h>
64 #include <machine/psl.h>
65 #include <machine/specialreg.h>
66 #include <machine/segments.h>
67 #include <machine/globaldata.h>
68
69 /*
70  * 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
71  */
72
73 /* Configuration flags. */
74 #define NPX_DISABLE_I586_OPTIMIZED_BCOPY        (1 << 0)
75 #define NPX_DISABLE_I586_OPTIMIZED_BZERO        (1 << 1)
76 #define NPX_DISABLE_I586_OPTIMIZED_COPYIO       (1 << 2)
77 #define NPX_PREFER_EMULATOR                     (1 << 3)
78
79 #ifdef  __GNUC__
80
81 #define fldcw(addr)             __asm("fldcw %0" : : "m" (*(addr)))
82 #define fnclex()                __asm("fnclex")
83 #define fninit()                __asm("fninit")
84 #define fnop()                  __asm("fnop")
85 #define fnsave(addr)            __asm __volatile("fnsave %0" : "=m" (*(addr)))
86 #define fnstcw(addr)            __asm __volatile("fnstcw %0" : "=m" (*(addr)))
87 #define fnstsw(addr)            __asm __volatile("fnstsw %0" : "=m" (*(addr)))
88 #define fp_divide_by_0()        __asm("fldz; fld1; fdiv %st,%st(1); fnop")
89 #define frstor(addr)            __asm("frstor %0" : : "m" (*(addr)))
90 #ifndef CPU_DISABLE_SSE
91 #define fxrstor(addr)           __asm("fxrstor %0" : : "m" (*(addr)))
92 #define fxsave(addr)            __asm __volatile("fxsave %0" : "=m" (*(addr)))
93 #endif
94 #define start_emulating()       __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
95                                       : : "n" (CR0_TS) : "ax")
96 #define stop_emulating()        __asm("clts")
97
98 #else   /* not __GNUC__ */
99
100 void    fldcw           (caddr_t addr);
101 void    fnclex          (void);
102 void    fninit          (void);
103 void    fnop            (void);
104 void    fnsave          (caddr_t addr);
105 void    fnstcw          (caddr_t addr);
106 void    fnstsw          (caddr_t addr);
107 void    fp_divide_by_0  (void);
108 void    frstor          (caddr_t addr);
109 #ifndef CPU_DISABLE_SSE
110 void    fxsave          (caddr_t addr);
111 void    fxrstor         (caddr_t addr);
112 #endif
113 void    start_emulating (void);
114 void    stop_emulating  (void);
115
116 #endif  /* __GNUC__ */
117
118 typedef u_char bool_t;
119 #ifndef CPU_DISABLE_SSE
120 static  void    fpu_clean_state(void);
121 #endif
122
123
124 static  int     npx_attach      (device_t dev);
125         void    npx_intr        (void *);
126 static  int     npx_probe       (device_t dev);
127 static  int     npx_probe1      (device_t dev);
128 static  void    fpusave         (union savefpu *);
129 static  void    fpurstor        (union savefpu *);
130
131 int     hw_float;               /* XXX currently just alias for npx_exists */
132
133 SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
134         CTLFLAG_RD, &hw_float, 0, 
135         "Floatingpoint instructions executed in hardware");
136 #if (defined(I586_CPU) || defined(I686_CPU)) && !defined(CPU_DISABLE_SSE)
137 int mmxopt = 1;
138 SYSCTL_INT(_kern, OID_AUTO, mmxopt, CTLFLAG_RD, &mmxopt, 0,
139         "MMX/XMM optimized bcopy/copyin/copyout support");
140 #endif
141
142 static  bool_t                  npx_ex16;
143 static  bool_t                  npx_exists;
144 static  bool_t                  npx_irq13;
145 static  int                     npx_irq;        /* irq number */
146
147 static struct krate badfprate = { 1 };
148
149 /*
150  * Probe routine.  Initialize cr0 to give correct behaviour for [f]wait
151  * whether the device exists or not (XXX should be elsewhere).  Set flags
152  * to tell npxattach() what to do.  Modify device struct if npx doesn't
153  * need to use interrupts.  Return 1 if device exists.
154  */
155 static int
156 npx_probe(device_t dev)
157 {
158         if (resource_int_value("npx", 0, "irq", &npx_irq) != 0)
159                 npx_irq = 13;
160         return npx_probe1(dev);
161 }
162
163 static int
164 npx_probe1(device_t dev)
165 {
166         /*
167          * Partially reset the coprocessor, if any.  Some BIOS's don't reset
168          * it after a warm boot.
169          */
170         outb(0xf1, 0);          /* full reset on some systems, NOP on others */
171         outb(0xf0, 0);          /* clear BUSY# latch */
172         /*
173          * Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
174          * instructions.  We must set the CR0_MP bit and use the CR0_TS
175          * bit to control the trap, because setting the CR0_EM bit does
176          * not cause WAIT instructions to trap.  It's important to trap
177          * WAIT instructions - otherwise the "wait" variants of no-wait
178          * control instructions would degenerate to the "no-wait" variants
179          * after FP context switches but work correctly otherwise.  It's
180          * particularly important to trap WAITs when there is no NPX -
181          * otherwise the "wait" variants would always degenerate.
182          *
183          * Try setting CR0_NE to get correct error reporting on 486DX's.
184          * Setting it should fail or do nothing on lesser processors.
185          */
186         load_cr0(rcr0() | CR0_MP | CR0_NE);
187         /*
188          * But don't trap while we're probing.
189          */
190         stop_emulating();
191         /*
192          * Finish resetting the coprocessor, if any.  If there is an error
193          * pending, then we may get a bogus IRQ13, but probeintr() will handle
194          * it OK.  Bogus halts have never been observed, but we enabled
195          * IRQ13 and cleared the BUSY# latch early to handle them anyway.
196          */
197         fninit();
198
199         device_set_desc(dev, "math processor");
200         /*
201          * Modern CPUs all have an FPU that uses the INT16 interface
202          * and provide a simple way to verify that, so handle the
203          * common case right away.
204          */
205         if (cpu_feature & CPUID_FPU) {
206                 npx_irq13 = 0;
207                 npx_ex16 = hw_float = npx_exists = 1;
208                 return (0);
209         }
210
211         /*
212          * Probe failed, but we want to get to npxattach to initialize the
213          * emulator and say that it has been installed.  XXX handle devices
214          * that aren't really devices better.
215          */
216         return (0);
217 }
218
219 /*
220  * Attach routine - announce which it is, and wire into system
221  */
222 int
223 npx_attach(device_t dev)
224 {
225         int flags;
226
227         if (resource_int_value("npx", 0, "flags", &flags) != 0)
228                 flags = 0;
229
230         if (flags)
231                 device_printf(dev, "flags 0x%x ", flags);
232         if (npx_irq13) {
233                 device_printf(dev, "using IRQ 13 interface\n");
234         } else {
235 #if defined(MATH_EMULATE)
236                 if (npx_ex16) {
237                         if (!(flags & NPX_PREFER_EMULATOR))
238                                 device_printf(dev, "INT 16 interface\n");
239                         else {
240                                 device_printf(dev, "FPU exists, but flags request "
241                                     "emulator\n");
242                                 hw_float = npx_exists = 0;
243                         }
244                 } else if (npx_exists) {
245                         device_printf(dev, "error reporting broken; using 387 emulator\n");
246                         hw_float = npx_exists = 0;
247                 } else
248                         device_printf(dev, "387 emulator\n");
249 #else
250                 if (npx_ex16) {
251                         device_printf(dev, "INT 16 interface\n");
252                         if (flags & NPX_PREFER_EMULATOR) {
253                                 device_printf(dev, "emulator requested, but none compiled "
254                                     "into kernel, using FPU\n");
255                         }
256                 } else
257                         device_printf(dev, "no 387 emulator in kernel and no FPU!\n");
258 #endif
259         }
260         npxinit(__INITIAL_NPXCW__);
261
262 #if (defined(I586_CPU) || defined(I686_CPU)) && !defined(CPU_DISABLE_SSE)
263         /*
264          * The asm_mmx_*() routines actually use XMM as well, so only 
265          * enable them if we have SSE2 and are using FXSR (fxsave/fxrstore).
266          */
267         TUNABLE_INT_FETCH("kern.mmxopt", &mmxopt);
268         if ((cpu_feature & CPUID_MMX) && (cpu_feature & CPUID_SSE) &&
269             (cpu_feature & CPUID_SSE2) && 
270             npx_ex16 && npx_exists && mmxopt && cpu_fxsr
271         ) {
272                 if ((flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY) == 0) {
273                         bcopy_vector = (void **)asm_xmm_bcopy;
274                         ovbcopy_vector = (void **)asm_xmm_bcopy;
275                         memcpy_vector = (void **)asm_xmm_memcpy;
276                         kprintf("Using XMM optimized bcopy/copyin/copyout\n");
277                 }
278                 if ((flags & NPX_DISABLE_I586_OPTIMIZED_BZERO) == 0) {
279                         /* XXX */
280                 }
281         } else if ((cpu_feature & CPUID_MMX) && (cpu_feature & CPUID_SSE) &&
282             npx_ex16 && npx_exists && mmxopt && cpu_fxsr
283         ) {
284                 if ((flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY) == 0) {
285                         bcopy_vector = (void **)asm_mmx_bcopy;
286                         ovbcopy_vector = (void **)asm_mmx_bcopy;
287                         memcpy_vector = (void **)asm_mmx_memcpy;
288                         kprintf("Using MMX optimized bcopy/copyin/copyout\n");
289                 }
290                 if ((flags & NPX_DISABLE_I586_OPTIMIZED_BZERO) == 0) {
291                         /* XXX */
292                 }
293         }
294
295 #endif
296         return (0);             /* XXX unused */
297 }
298
299 /*
300  * Initialize the floating point unit.
301  */
302 void
303 npxinit(u_short control)
304 {
305         static union savefpu dummy __aligned(16);
306
307         if (!npx_exists)
308                 return;
309         /*
310          * fninit has the same h/w bugs as fnsave.  Use the detoxified
311          * fnsave to throw away any junk in the fpu.  npxsave() initializes
312          * the fpu and sets npxthread = NULL as important side effects.
313          */
314         npxsave(&dummy);
315         crit_enter();
316         stop_emulating();
317         fldcw(&control);
318         fpusave(curthread->td_savefpu);
319         mdcpu->gd_npxthread = NULL;
320         start_emulating();
321         crit_exit();
322 }
323
324 /*
325  * Free coprocessor (if we have it).
326  */
327 void
328 npxexit(void)
329 {
330         if (curthread == mdcpu->gd_npxthread)
331                 npxsave(curthread->td_savefpu);
332 #ifdef NPX_DEBUG
333         if (npx_exists) {
334                 u_int   masked_exceptions;
335
336                 masked_exceptions = 
337                     curthread->td_savefpu->sv_87.sv_env.en_cw
338                     & curthread->td_savefpu->sv_87.sv_env.en_sw & 0x7f;
339                 /*
340                  * Log exceptions that would have trapped with the old
341                  * control word (overflow, divide by 0, and invalid operand).
342                  */
343                 if (masked_exceptions & 0x0d)
344                         log(LOG_ERR,
345         "pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
346                             curproc->p_pid, curproc->p_comm, masked_exceptions);
347         }
348 #endif
349 }
350
351 /* 
352  * The following mechanism is used to ensure that the FPE_... value
353  * that is passed as a trapcode to the signal handler of the user
354  * process does not have more than one bit set.
355  * 
356  * Multiple bits may be set if the user process modifies the control
357  * word while a status word bit is already set.  While this is a sign
358  * of bad coding, we have no choise than to narrow them down to one
359  * bit, since we must not send a trapcode that is not exactly one of
360  * the FPE_ macros.
361  *
362  * The mechanism has a static table with 127 entries.  Each combination
363  * of the 7 FPU status word exception bits directly translates to a
364  * position in this table, where a single FPE_... value is stored.
365  * This FPE_... value stored there is considered the "most important"
366  * of the exception bits and will be sent as the signal code.  The
367  * precedence of the bits is based upon Intel Document "Numerical
368  * Applications", Chapter "Special Computational Situations".
369  *
370  * The macro to choose one of these values does these steps: 1) Throw
371  * away status word bits that cannot be masked.  2) Throw away the bits
372  * currently masked in the control word, assuming the user isn't
373  * interested in them anymore.  3) Reinsert status word bit 7 (stack
374  * fault) if it is set, which cannot be masked but must be presered.
375  * 4) Use the remaining bits to point into the trapcode table.
376  *
377  * The 6 maskable bits in order of their preference, as stated in the
378  * above referenced Intel manual:
379  * 1  Invalid operation (FP_X_INV)
380  * 1a   Stack underflow
381  * 1b   Stack overflow
382  * 1c   Operand of unsupported format
383  * 1d   SNaN operand.
384  * 2  QNaN operand (not an exception, irrelavant here)
385  * 3  Any other invalid-operation not mentioned above or zero divide
386  *      (FP_X_INV, FP_X_DZ)
387  * 4  Denormal operand (FP_X_DNML)
388  * 5  Numeric over/underflow (FP_X_OFL, FP_X_UFL)
389  * 6  Inexact result (FP_X_IMP) 
390  */
391 static char fpetable[128] = {
392         0,
393         FPE_FLTINV,     /*  1 - INV */
394         FPE_FLTUND,     /*  2 - DNML */
395         FPE_FLTINV,     /*  3 - INV | DNML */
396         FPE_FLTDIV,     /*  4 - DZ */
397         FPE_FLTINV,     /*  5 - INV | DZ */
398         FPE_FLTDIV,     /*  6 - DNML | DZ */
399         FPE_FLTINV,     /*  7 - INV | DNML | DZ */
400         FPE_FLTOVF,     /*  8 - OFL */
401         FPE_FLTINV,     /*  9 - INV | OFL */
402         FPE_FLTUND,     /*  A - DNML | OFL */
403         FPE_FLTINV,     /*  B - INV | DNML | OFL */
404         FPE_FLTDIV,     /*  C - DZ | OFL */
405         FPE_FLTINV,     /*  D - INV | DZ | OFL */
406         FPE_FLTDIV,     /*  E - DNML | DZ | OFL */
407         FPE_FLTINV,     /*  F - INV | DNML | DZ | OFL */
408         FPE_FLTUND,     /* 10 - UFL */
409         FPE_FLTINV,     /* 11 - INV | UFL */
410         FPE_FLTUND,     /* 12 - DNML | UFL */
411         FPE_FLTINV,     /* 13 - INV | DNML | UFL */
412         FPE_FLTDIV,     /* 14 - DZ | UFL */
413         FPE_FLTINV,     /* 15 - INV | DZ | UFL */
414         FPE_FLTDIV,     /* 16 - DNML | DZ | UFL */
415         FPE_FLTINV,     /* 17 - INV | DNML | DZ | UFL */
416         FPE_FLTOVF,     /* 18 - OFL | UFL */
417         FPE_FLTINV,     /* 19 - INV | OFL | UFL */
418         FPE_FLTUND,     /* 1A - DNML | OFL | UFL */
419         FPE_FLTINV,     /* 1B - INV | DNML | OFL | UFL */
420         FPE_FLTDIV,     /* 1C - DZ | OFL | UFL */
421         FPE_FLTINV,     /* 1D - INV | DZ | OFL | UFL */
422         FPE_FLTDIV,     /* 1E - DNML | DZ | OFL | UFL */
423         FPE_FLTINV,     /* 1F - INV | DNML | DZ | OFL | UFL */
424         FPE_FLTRES,     /* 20 - IMP */
425         FPE_FLTINV,     /* 21 - INV | IMP */
426         FPE_FLTUND,     /* 22 - DNML | IMP */
427         FPE_FLTINV,     /* 23 - INV | DNML | IMP */
428         FPE_FLTDIV,     /* 24 - DZ | IMP */
429         FPE_FLTINV,     /* 25 - INV | DZ | IMP */
430         FPE_FLTDIV,     /* 26 - DNML | DZ | IMP */
431         FPE_FLTINV,     /* 27 - INV | DNML | DZ | IMP */
432         FPE_FLTOVF,     /* 28 - OFL | IMP */
433         FPE_FLTINV,     /* 29 - INV | OFL | IMP */
434         FPE_FLTUND,     /* 2A - DNML | OFL | IMP */
435         FPE_FLTINV,     /* 2B - INV | DNML | OFL | IMP */
436         FPE_FLTDIV,     /* 2C - DZ | OFL | IMP */
437         FPE_FLTINV,     /* 2D - INV | DZ | OFL | IMP */
438         FPE_FLTDIV,     /* 2E - DNML | DZ | OFL | IMP */
439         FPE_FLTINV,     /* 2F - INV | DNML | DZ | OFL | IMP */
440         FPE_FLTUND,     /* 30 - UFL | IMP */
441         FPE_FLTINV,     /* 31 - INV | UFL | IMP */
442         FPE_FLTUND,     /* 32 - DNML | UFL | IMP */
443         FPE_FLTINV,     /* 33 - INV | DNML | UFL | IMP */
444         FPE_FLTDIV,     /* 34 - DZ | UFL | IMP */
445         FPE_FLTINV,     /* 35 - INV | DZ | UFL | IMP */
446         FPE_FLTDIV,     /* 36 - DNML | DZ | UFL | IMP */
447         FPE_FLTINV,     /* 37 - INV | DNML | DZ | UFL | IMP */
448         FPE_FLTOVF,     /* 38 - OFL | UFL | IMP */
449         FPE_FLTINV,     /* 39 - INV | OFL | UFL | IMP */
450         FPE_FLTUND,     /* 3A - DNML | OFL | UFL | IMP */
451         FPE_FLTINV,     /* 3B - INV | DNML | OFL | UFL | IMP */
452         FPE_FLTDIV,     /* 3C - DZ | OFL | UFL | IMP */
453         FPE_FLTINV,     /* 3D - INV | DZ | OFL | UFL | IMP */
454         FPE_FLTDIV,     /* 3E - DNML | DZ | OFL | UFL | IMP */
455         FPE_FLTINV,     /* 3F - INV | DNML | DZ | OFL | UFL | IMP */
456         FPE_FLTSUB,     /* 40 - STK */
457         FPE_FLTSUB,     /* 41 - INV | STK */
458         FPE_FLTUND,     /* 42 - DNML | STK */
459         FPE_FLTSUB,     /* 43 - INV | DNML | STK */
460         FPE_FLTDIV,     /* 44 - DZ | STK */
461         FPE_FLTSUB,     /* 45 - INV | DZ | STK */
462         FPE_FLTDIV,     /* 46 - DNML | DZ | STK */
463         FPE_FLTSUB,     /* 47 - INV | DNML | DZ | STK */
464         FPE_FLTOVF,     /* 48 - OFL | STK */
465         FPE_FLTSUB,     /* 49 - INV | OFL | STK */
466         FPE_FLTUND,     /* 4A - DNML | OFL | STK */
467         FPE_FLTSUB,     /* 4B - INV | DNML | OFL | STK */
468         FPE_FLTDIV,     /* 4C - DZ | OFL | STK */
469         FPE_FLTSUB,     /* 4D - INV | DZ | OFL | STK */
470         FPE_FLTDIV,     /* 4E - DNML | DZ | OFL | STK */
471         FPE_FLTSUB,     /* 4F - INV | DNML | DZ | OFL | STK */
472         FPE_FLTUND,     /* 50 - UFL | STK */
473         FPE_FLTSUB,     /* 51 - INV | UFL | STK */
474         FPE_FLTUND,     /* 52 - DNML | UFL | STK */
475         FPE_FLTSUB,     /* 53 - INV | DNML | UFL | STK */
476         FPE_FLTDIV,     /* 54 - DZ | UFL | STK */
477         FPE_FLTSUB,     /* 55 - INV | DZ | UFL | STK */
478         FPE_FLTDIV,     /* 56 - DNML | DZ | UFL | STK */
479         FPE_FLTSUB,     /* 57 - INV | DNML | DZ | UFL | STK */
480         FPE_FLTOVF,     /* 58 - OFL | UFL | STK */
481         FPE_FLTSUB,     /* 59 - INV | OFL | UFL | STK */
482         FPE_FLTUND,     /* 5A - DNML | OFL | UFL | STK */
483         FPE_FLTSUB,     /* 5B - INV | DNML | OFL | UFL | STK */
484         FPE_FLTDIV,     /* 5C - DZ | OFL | UFL | STK */
485         FPE_FLTSUB,     /* 5D - INV | DZ | OFL | UFL | STK */
486         FPE_FLTDIV,     /* 5E - DNML | DZ | OFL | UFL | STK */
487         FPE_FLTSUB,     /* 5F - INV | DNML | DZ | OFL | UFL | STK */
488         FPE_FLTRES,     /* 60 - IMP | STK */
489         FPE_FLTSUB,     /* 61 - INV | IMP | STK */
490         FPE_FLTUND,     /* 62 - DNML | IMP | STK */
491         FPE_FLTSUB,     /* 63 - INV | DNML | IMP | STK */
492         FPE_FLTDIV,     /* 64 - DZ | IMP | STK */
493         FPE_FLTSUB,     /* 65 - INV | DZ | IMP | STK */
494         FPE_FLTDIV,     /* 66 - DNML | DZ | IMP | STK */
495         FPE_FLTSUB,     /* 67 - INV | DNML | DZ | IMP | STK */
496         FPE_FLTOVF,     /* 68 - OFL | IMP | STK */
497         FPE_FLTSUB,     /* 69 - INV | OFL | IMP | STK */
498         FPE_FLTUND,     /* 6A - DNML | OFL | IMP | STK */
499         FPE_FLTSUB,     /* 6B - INV | DNML | OFL | IMP | STK */
500         FPE_FLTDIV,     /* 6C - DZ | OFL | IMP | STK */
501         FPE_FLTSUB,     /* 6D - INV | DZ | OFL | IMP | STK */
502         FPE_FLTDIV,     /* 6E - DNML | DZ | OFL | IMP | STK */
503         FPE_FLTSUB,     /* 6F - INV | DNML | DZ | OFL | IMP | STK */
504         FPE_FLTUND,     /* 70 - UFL | IMP | STK */
505         FPE_FLTSUB,     /* 71 - INV | UFL | IMP | STK */
506         FPE_FLTUND,     /* 72 - DNML | UFL | IMP | STK */
507         FPE_FLTSUB,     /* 73 - INV | DNML | UFL | IMP | STK */
508         FPE_FLTDIV,     /* 74 - DZ | UFL | IMP | STK */
509         FPE_FLTSUB,     /* 75 - INV | DZ | UFL | IMP | STK */
510         FPE_FLTDIV,     /* 76 - DNML | DZ | UFL | IMP | STK */
511         FPE_FLTSUB,     /* 77 - INV | DNML | DZ | UFL | IMP | STK */
512         FPE_FLTOVF,     /* 78 - OFL | UFL | IMP | STK */
513         FPE_FLTSUB,     /* 79 - INV | OFL | UFL | IMP | STK */
514         FPE_FLTUND,     /* 7A - DNML | OFL | UFL | IMP | STK */
515         FPE_FLTSUB,     /* 7B - INV | DNML | OFL | UFL | IMP | STK */
516         FPE_FLTDIV,     /* 7C - DZ | OFL | UFL | IMP | STK */
517         FPE_FLTSUB,     /* 7D - INV | DZ | OFL | UFL | IMP | STK */
518         FPE_FLTDIV,     /* 7E - DNML | DZ | OFL | UFL | IMP | STK */
519         FPE_FLTSUB,     /* 7F - INV | DNML | DZ | OFL | UFL | IMP | STK */
520 };
521
522 /*
523  * Preserve the FP status word, clear FP exceptions, then generate a SIGFPE.
524  *
525  * Clearing exceptions is necessary mainly to avoid IRQ13 bugs.  We now
526  * depend on longjmp() restoring a usable state.  Restoring the state
527  * or examining it might fail if we didn't clear exceptions.
528  *
529  * The error code chosen will be one of the FPE_... macros. It will be
530  * sent as the second argument to old BSD-style signal handlers and as
531  * "siginfo_t->si_code" (second argument) to SA_SIGINFO signal handlers.
532  *
533  * XXX the FP state is not preserved across signal handlers.  So signal
534  * handlers cannot afford to do FP unless they preserve the state or
535  * longjmp() out.  Both preserving the state and longjmp()ing may be
536  * destroyed by IRQ13 bugs.  Clearing FP exceptions is not an acceptable
537  * solution for signals other than SIGFPE.
538  *
539  * The MP lock is not held on entry (see i386/i386/exception.s) and
540  * should not be held on exit.  Interrupts are enabled.  We must enter
541  * a critical section to stabilize the FP system and prevent an interrupt
542  * or preemption from changing the FP state out from under us.
543  */
544 void
545 npx_intr(void *dummy)
546 {
547         int code;
548         u_short control;
549         u_short status;
550         struct intrframe *frame;
551
552         crit_enter();
553
554         /*
555          * This exception can only occur with CR0_TS clear, otherwise we
556          * would get a DNA exception.  However, since interrupts were
557          * enabled a preemption could have sneaked in and used the FP system
558          * before we entered our critical section.  If that occured, the
559          * TS bit will be set and npxthread will be NULL.
560          */
561         if (npx_exists && (rcr0() & CR0_TS)) {
562                 KASSERT(mdcpu->gd_npxthread == NULL, ("gd_npxthread was %p with TS set!", mdcpu->gd_npxthread));
563                 npxdna();
564                 crit_exit();
565                 return;
566         }
567         if (mdcpu->gd_npxthread == NULL || !npx_exists) {
568                 get_mplock();
569                 kprintf("npxintr: npxthread = %p, curthread = %p, npx_exists = %d\n",
570                        mdcpu->gd_npxthread, curthread, npx_exists);
571                 panic("npxintr from nowhere");
572         }
573         if (mdcpu->gd_npxthread != curthread) {
574                 get_mplock();
575                 kprintf("npxintr: npxthread = %p, curthread = %p, npx_exists = %d\n",
576                        mdcpu->gd_npxthread, curthread, npx_exists);
577                 panic("npxintr from non-current process");
578         }
579
580         outb(0xf0, 0);
581         fnstsw(&status);
582         fnstcw(&control);
583         fnclex();
584
585         get_mplock();
586
587         /*
588          * Pass exception to process.
589          */
590         frame = (struct intrframe *)&dummy;     /* XXX */
591         if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) {
592                 /*
593                  * Interrupt is essentially a trap, so we can afford to call
594                  * the SIGFPE handler (if any) as soon as the interrupt
595                  * returns.
596                  *
597                  * XXX little or nothing is gained from this, and plenty is
598                  * lost - the interrupt frame has to contain the trap frame
599                  * (this is otherwise only necessary for the rescheduling trap
600                  * in doreti, and the frame for that could easily be set up
601                  * just before it is used).
602                  */
603                 curthread->td_lwp->lwp_md.md_regs = INTR_TO_TRAPFRAME(frame);
604                 /*
605                  * Encode the appropriate code for detailed information on
606                  * this exception.
607                  */
608                 code = 
609                     fpetable[(status & ~control & 0x3f) | (status & 0x40)];
610                 trapsignal(curthread->td_lwp, SIGFPE, code);
611         } else {
612                 /*
613                  * Nested interrupt.  These losers occur when:
614                  *      o an IRQ13 is bogusly generated at a bogus time, e.g.:
615                  *              o immediately after an fnsave or frstor of an
616                  *                error state.
617                  *              o a couple of 386 instructions after
618                  *                "fstpl _memvar" causes a stack overflow.
619                  *        These are especially nasty when combined with a
620                  *        trace trap.
621                  *      o an IRQ13 occurs at the same time as another higher-
622                  *        priority interrupt.
623                  *
624                  * Treat them like a true async interrupt.
625                  */
626                 lwpsignal(curproc, curthread->td_lwp, SIGFPE);
627         }
628         rel_mplock();
629         crit_exit();
630 }
631
632 /*
633  * Implement the device not available (DNA) exception.  gd_npxthread had 
634  * better be NULL.  Restore the current thread's FP state and set gd_npxthread
635  * to curthread.
636  *
637  * Interrupts are enabled and preemption can occur.  Enter a critical
638  * section to stabilize the FP state.
639  */
640 int
641 npxdna(void)
642 {
643         thread_t td = curthread;
644         int didinit = 0;
645
646         if (!npx_exists)
647                 return (0);
648         if (mdcpu->gd_npxthread != NULL) {
649                 kprintf("npxdna: npxthread = %p, curthread = %p\n",
650                        mdcpu->gd_npxthread, td);
651                 panic("npxdna");
652         }
653
654         /*
655          * Setup the initial saved state if the thread has never before
656          * used the FP unit.  This also occurs when a thread pushes a
657          * signal handler and uses FP in the handler.
658          */
659         if ((td->td_flags & (TDF_USINGFP | TDF_KERNELFP)) == 0) {
660                 td->td_flags |= TDF_USINGFP;
661                 npxinit(__INITIAL_NPXCW__);
662                 didinit = 1;
663         }
664
665         /*
666          * The setting of gd_npxthread and the call to fpurstor() must not
667          * be preempted by an interrupt thread or we will take an npxdna
668          * trap and potentially save our current fpstate (which is garbage)
669          * and then restore the garbage rather then the originally saved
670          * fpstate.
671          */
672         crit_enter();
673         stop_emulating();
674         /*
675          * Record new context early in case frstor causes an IRQ13.
676          */
677         mdcpu->gd_npxthread = td;
678         /*
679          * The following frstor may cause an IRQ13 when the state being
680          * restored has a pending error.  The error will appear to have been
681          * triggered by the current (npx) user instruction even when that
682          * instruction is a no-wait instruction that should not trigger an
683          * error (e.g., fnclex).  On at least one 486 system all of the
684          * no-wait instructions are broken the same as frstor, so our
685          * treatment does not amplify the breakage.  On at least one
686          * 386/Cyrix 387 system, fnclex works correctly while frstor and
687          * fnsave are broken, so our treatment breaks fnclex if it is the
688          * first FPU instruction after a context switch.
689          */
690         if ((td->td_savefpu->sv_xmm.sv_env.en_mxcsr & ~0xFFBF)
691 #ifndef CPU_DISABLE_SSE
692             && cpu_fxsr
693 #endif
694            ) {
695                 krateprintf(&badfprate,
696                             "FXRSTR: illegal FP MXCSR %08x didinit = %d\n",
697                             td->td_savefpu->sv_xmm.sv_env.en_mxcsr, didinit);
698                 td->td_savefpu->sv_xmm.sv_env.en_mxcsr &= 0xFFBF;
699                 lwpsignal(curproc, curthread->td_lwp, SIGFPE);
700         }
701         fpurstor(td->td_savefpu);
702         crit_exit();
703
704         return (1);
705 }
706
707 /*
708  * Wrapper for the fnsave instruction to handle h/w bugs.  If there is an error
709  * pending, then fnsave generates a bogus IRQ13 on some systems.  Force
710  * any IRQ13 to be handled immediately, and then ignore it.  This routine is
711  * often called at splhigh so it must not use many system services.  In
712  * particular, it's much easier to install a special handler than to
713  * guarantee that it's safe to use npxintr() and its supporting code.
714  *
715  * WARNING!  This call is made during a switch and the MP lock will be
716  * setup for the new target thread rather then the current thread, so we
717  * cannot do anything here that depends on the *_mplock() functions as
718  * we may trip over their assertions.
719  *
720  * WARNING!  When using fxsave we MUST fninit after saving the FP state.  The
721  * kernel will always assume that the FP state is 'safe' (will not cause
722  * exceptions) for mmx/xmm use if npxthread is NULL.  The kernel must still
723  * setup a custom save area before actually using the FP unit, but it will
724  * not bother calling fninit.  This greatly improves kernel performance when
725  * it wishes to use the FP unit.
726  */
727 void
728 npxsave(union savefpu *addr)
729 {
730         crit_enter();
731         stop_emulating();
732         fpusave(addr);
733         mdcpu->gd_npxthread = NULL;
734         fninit();
735         start_emulating();
736         crit_exit();
737 }
738
739 static void
740 fpusave(union savefpu *addr)
741 {
742 #ifndef CPU_DISABLE_SSE
743         if (cpu_fxsr)
744                 fxsave(addr);
745         else
746 #endif
747                 fnsave(addr);
748 }
749
750 /*
751  * Save the FP state to the mcontext structure.
752  *
753  * WARNING: If you want to try to npxsave() directly to mctx->mc_fpregs,
754  * then it MUST be 16-byte aligned.  Currently this is not guarenteed.
755  */
756 void
757 npxpush(mcontext_t *mctx)
758 {
759         thread_t td = curthread;
760
761         KKASSERT((td->td_flags & TDF_KERNELFP) == 0);
762
763         if (td->td_flags & TDF_USINGFP) {
764                 if (mdcpu->gd_npxthread == td) {
765                         /*
766                          * XXX Note: This is a bit inefficient if the signal
767                          * handler uses floating point, extra faults will
768                          * occur.
769                          */
770                         mctx->mc_ownedfp = _MC_FPOWNED_FPU;
771                         npxsave(td->td_savefpu);
772                 } else {
773                         mctx->mc_ownedfp = _MC_FPOWNED_PCB;
774                 }
775                 bcopy(td->td_savefpu, mctx->mc_fpregs, sizeof(mctx->mc_fpregs));
776                 td->td_flags &= ~TDF_USINGFP;
777                 mctx->mc_fpformat =
778 #ifndef CPU_DISABLE_SSE
779                         (cpu_fxsr) ? _MC_FPFMT_XMM :
780 #endif
781                         _MC_FPFMT_387;
782         } else {
783                 mctx->mc_ownedfp = _MC_FPOWNED_NONE;
784                 mctx->mc_fpformat = _MC_FPFMT_NODEV;
785         }
786 }
787
788 /*
789  * Restore the FP state from the mcontext structure.
790  */
791 void
792 npxpop(mcontext_t *mctx)
793 {
794         thread_t td = curthread;
795
796         KKASSERT((td->td_flags & TDF_KERNELFP) == 0);
797
798         switch(mctx->mc_ownedfp) {
799         case _MC_FPOWNED_NONE:
800                 /*
801                  * If the signal handler used the FP unit but the interrupted
802                  * code did not, release the FP unit.  Clear TDF_USINGFP will
803                  * force the FP unit to reinit so the interrupted code sees
804                  * a clean slate.
805                  */
806                 if (td->td_flags & TDF_USINGFP) {
807                         if (td == mdcpu->gd_npxthread)
808                                 npxsave(td->td_savefpu);
809                         td->td_flags &= ~TDF_USINGFP;
810                 }
811                 break;
812         case _MC_FPOWNED_FPU:
813         case _MC_FPOWNED_PCB:
814                 /*
815                  * Clear ownership of the FP unit and restore our saved state.
816                  *
817                  * NOTE: The signal handler may have set-up some FP state and
818                  * enabled the FP unit, so we have to restore no matter what.
819                  *
820                  * XXX: This is bit inefficient, if the code being returned
821                  * to is actively using the FP this results in multiple
822                  * kernel faults.
823                  *
824                  * WARNING: The saved state was exposed to userland and may
825                  * have to be sanitized to avoid a GP fault in the kernel.
826                  */
827                 if (td == mdcpu->gd_npxthread)
828                         npxsave(td->td_savefpu);
829                 bcopy(mctx->mc_fpregs, td->td_savefpu, sizeof(*td->td_savefpu));
830                 if ((td->td_savefpu->sv_xmm.sv_env.en_mxcsr & ~0xFFBF)
831 #ifndef CPU_DISABLE_SSE
832                     && cpu_fxsr
833 #endif
834                    ) {
835                         krateprintf(&badfprate,
836                                     "pid %d (%s) signal return from user: "
837                                     "illegal FP MXCSR %08x\n",
838                                     td->td_proc->p_pid,
839                                     td->td_proc->p_comm,
840                                     td->td_savefpu->sv_xmm.sv_env.en_mxcsr);
841                         td->td_savefpu->sv_xmm.sv_env.en_mxcsr &= 0xFFBF;
842                 }
843                 td->td_flags |= TDF_USINGFP;
844                 break;
845         }
846 }
847
848 #ifndef CPU_DISABLE_SSE
849 /*
850  * On AuthenticAMD processors, the fxrstor instruction does not restore
851  * the x87's stored last instruction pointer, last data pointer, and last
852  * opcode values, except in the rare case in which the exception summary
853  * (ES) bit in the x87 status word is set to 1.
854  *
855  * In order to avoid leaking this information across processes, we clean
856  * these values by performing a dummy load before executing fxrstor().
857  */
858 static  double  dummy_variable = 0.0;
859 static void
860 fpu_clean_state(void)
861 {
862         u_short status;
863
864         /*
865          * Clear the ES bit in the x87 status word if it is currently
866          * set, in order to avoid causing a fault in the upcoming load.
867          */
868         fnstsw(&status);
869         if (status & 0x80)
870                 fnclex();
871
872         /*
873          * Load the dummy variable into the x87 stack.  This mangles
874          * the x87 stack, but we don't care since we're about to call
875          * fxrstor() anyway.
876          */
877         __asm __volatile("ffree %%st(7); flds %0" : : "m" (dummy_variable));
878 }
879 #endif /* CPU_DISABLE_SSE */
880
881 static void
882 fpurstor(union savefpu *addr)
883 {
884 #ifndef CPU_DISABLE_SSE
885         if (cpu_fxsr) {
886                 fpu_clean_state();
887                 fxrstor(addr);
888         } else {
889                 frstor(addr);
890         }
891 #else
892         frstor(addr);
893 #endif
894 }
895
896 /*
897  * Because npx is a static device that always exists under nexus,
898  * and is not scanned by the nexus device, we need an identify
899  * function to install the device.
900  */
901 static device_method_t npx_methods[] = {
902         /* Device interface */
903         DEVMETHOD(device_identify,      bus_generic_identify),
904         DEVMETHOD(device_probe,         npx_probe),
905         DEVMETHOD(device_attach,        npx_attach),
906         DEVMETHOD(device_detach,        bus_generic_detach),
907         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
908         DEVMETHOD(device_suspend,       bus_generic_suspend),
909         DEVMETHOD(device_resume,        bus_generic_resume),
910         
911         DEVMETHOD_END
912 };
913
914 static driver_t npx_driver = {
915         "npx",
916         npx_methods,
917         1,                      /* no softc */
918 };
919
920 static devclass_t npx_devclass;
921
922 /*
923  * We prefer to attach to the root nexus so that the usual case (exception 16)
924  * doesn't describe the processor as being `on isa'.
925  */
926 DRIVER_MODULE(npx, nexus, npx_driver, npx_devclass, NULL, NULL);