Deleted Added
full compact
npx.c (74430) npx.c (74903)
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:

--- 18 unchanged lines hidden (view full) ---

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
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:

--- 18 unchanged lines hidden (view full) ---

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: head/sys/i386/isa/npx.c 74430 2001-03-19 00:28:04Z des $
35 * $FreeBSD: head/sys/i386/isa/npx.c 74903 2001-03-28 03:06:10Z jhb $
36 */
37
38#include "opt_debug_npx.h"
39#include "opt_math_emulate.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/bus.h>

--- 171 unchanged lines hidden (view full) ---

215
216 if (resource_int_value("npx", 0, "irq", &npx_irq) != 0)
217 npx_irq = 13;
218 return npx_probe1(dev);
219
220#else /* SMP */
221
222 int result;
36 */
37
38#include "opt_debug_npx.h"
39#include "opt_math_emulate.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/bus.h>

--- 171 unchanged lines hidden (view full) ---

215
216 if (resource_int_value("npx", 0, "irq", &npx_irq) != 0)
217 npx_irq = 13;
218 return npx_probe1(dev);
219
220#else /* SMP */
221
222 int result;
223 u_long save_eflags;
223 critical_t savecrit;
224 u_char save_icu1_mask;
225 u_char save_icu2_mask;
226 struct gate_descriptor save_idt_npxintr;
227 struct gate_descriptor save_idt_npxtrap;
228 /*
229 * This routine is now just a wrapper for npxprobe1(), to install
230 * special npx interrupt and trap handlers, to enable npx interrupts
231 * and to disable other interrupts. Someday isa_configure() will
232 * install suitable handlers and run with interrupts enabled so we
233 * won't need to do so much here.
234 */
235 if (resource_int_value("npx", 0, "irq", &npx_irq) != 0)
236 npx_irq = 13;
237 npx_intrno = NRSVIDT + npx_irq;
224 u_char save_icu1_mask;
225 u_char save_icu2_mask;
226 struct gate_descriptor save_idt_npxintr;
227 struct gate_descriptor save_idt_npxtrap;
228 /*
229 * This routine is now just a wrapper for npxprobe1(), to install
230 * special npx interrupt and trap handlers, to enable npx interrupts
231 * and to disable other interrupts. Someday isa_configure() will
232 * install suitable handlers and run with interrupts enabled so we
233 * won't need to do so much here.
234 */
235 if (resource_int_value("npx", 0, "irq", &npx_irq) != 0)
236 npx_irq = 13;
237 npx_intrno = NRSVIDT + npx_irq;
238 save_eflags = read_eflags();
239 disable_intr();
238 savecrit = critical_enter();
240 save_icu1_mask = inb(IO_ICU1 + 1);
241 save_icu2_mask = inb(IO_ICU2 + 1);
242 save_idt_npxintr = idt[npx_intrno];
243 save_idt_npxtrap = idt[16];
244 outb(IO_ICU1 + 1, ~IRQ_SLAVE);
245 outb(IO_ICU2 + 1, ~(1 << (npx_irq - 8)));
246 setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
247 setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
248 npx_idt_probeintr = idt[npx_intrno];
249
250 /*
251 * XXX This looks highly bogus, but it appears that npc_probe1
252 * needs interrupts enabled. Does this make any difference
253 * here?
254 */
239 save_icu1_mask = inb(IO_ICU1 + 1);
240 save_icu2_mask = inb(IO_ICU2 + 1);
241 save_idt_npxintr = idt[npx_intrno];
242 save_idt_npxtrap = idt[16];
243 outb(IO_ICU1 + 1, ~IRQ_SLAVE);
244 outb(IO_ICU2 + 1, ~(1 << (npx_irq - 8)));
245 setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
246 setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
247 npx_idt_probeintr = idt[npx_intrno];
248
249 /*
250 * XXX This looks highly bogus, but it appears that npc_probe1
251 * needs interrupts enabled. Does this make any difference
252 * here?
253 */
255 enable_intr();
254 critical_exit(savecrit);
256 result = npx_probe1(dev);
255 result = npx_probe1(dev);
257 disable_intr();
256 savecrit = critical_enter();
258 outb(IO_ICU1 + 1, save_icu1_mask);
259 outb(IO_ICU2 + 1, save_icu2_mask);
260 idt[npx_intrno] = save_idt_npxintr;
261 idt[16] = save_idt_npxtrap;
257 outb(IO_ICU1 + 1, save_icu1_mask);
258 outb(IO_ICU2 + 1, save_icu2_mask);
259 idt[npx_intrno] = save_idt_npxintr;
260 idt[16] = save_idt_npxtrap;
262 write_eflags(save_eflags);
261 critical_exit(savecrit);
263 return (result);
264
265#endif /* SMP */
266}
267
268static int
269npx_probe1(dev)
270 device_t dev;

--- 522 unchanged lines hidden (view full) ---

793 *
794 * It would be better to switch FP context here (if curproc != npxproc)
795 * and not necessarily for every context switch, but it is too hard to
796 * access foreign pcb's.
797 */
798int
799npxdna()
800{
262 return (result);
263
264#endif /* SMP */
265}
266
267static int
268npx_probe1(dev)
269 device_t dev;

--- 522 unchanged lines hidden (view full) ---

792 *
793 * It would be better to switch FP context here (if curproc != npxproc)
794 * and not necessarily for every context switch, but it is too hard to
795 * access foreign pcb's.
796 */
797int
798npxdna()
799{
801 int s;
800 critical_t s;
802
803 if (!npx_exists)
804 return (0);
805 if (PCPU_GET(npxproc) != NULL) {
806 printf("npxdna: npxproc = %p, curproc = %p\n",
807 PCPU_GET(npxproc), curproc);
808 panic("npxdna");
809 }
801
802 if (!npx_exists)
803 return (0);
804 if (PCPU_GET(npxproc) != NULL) {
805 printf("npxdna: npxproc = %p, curproc = %p\n",
806 PCPU_GET(npxproc), curproc);
807 panic("npxdna");
808 }
810 s = save_intr();
811 disable_intr();
809 s = critical_enter();
812 stop_emulating();
813 /*
814 * Record new context early in case frstor causes an IRQ13.
815 */
816 PCPU_SET(npxproc, CURPROC);
817 PCPU_GET(curpcb)->pcb_savefpu.sv_ex_sw = 0;
818 /*
819 * The following frstor may cause an IRQ13 when the state being
820 * restored has a pending error. The error will appear to have been
821 * triggered by the current (npx) user instruction even when that
822 * instruction is a no-wait instruction that should not trigger an
823 * error (e.g., fnclex). On at least one 486 system all of the
824 * no-wait instructions are broken the same as frstor, so our
825 * treatment does not amplify the breakage. On at least one
826 * 386/Cyrix 387 system, fnclex works correctly while frstor and
827 * fnsave are broken, so our treatment breaks fnclex if it is the
828 * first FPU instruction after a context switch.
829 */
830 frstor(&PCPU_GET(curpcb)->pcb_savefpu);
810 stop_emulating();
811 /*
812 * Record new context early in case frstor causes an IRQ13.
813 */
814 PCPU_SET(npxproc, CURPROC);
815 PCPU_GET(curpcb)->pcb_savefpu.sv_ex_sw = 0;
816 /*
817 * The following frstor may cause an IRQ13 when the state being
818 * restored has a pending error. The error will appear to have been
819 * triggered by the current (npx) user instruction even when that
820 * instruction is a no-wait instruction that should not trigger an
821 * error (e.g., fnclex). On at least one 486 system all of the
822 * no-wait instructions are broken the same as frstor, so our
823 * treatment does not amplify the breakage. On at least one
824 * 386/Cyrix 387 system, fnclex works correctly while frstor and
825 * fnsave are broken, so our treatment breaks fnclex if it is the
826 * first FPU instruction after a context switch.
827 */
828 frstor(&PCPU_GET(curpcb)->pcb_savefpu);
831 restore_intr(s);
829 critical_exit(s);
832
833 return (1);
834}
835
836/*
837 * Wrapper for fnsave instruction to handle h/w bugs. If there is an error
838 * pending, then fnsave generates a bogus IRQ13 on some systems. Force
839 * any IRQ13 to be handled immediately, and then ignore it. This routine is

--- 10 unchanged lines hidden (view full) ---

850 stop_emulating();
851 fnsave(addr);
852 /* fnop(); */
853 start_emulating();
854 PCPU_SET(npxproc, NULL);
855
856#else /* SMP */
857
830
831 return (1);
832}
833
834/*
835 * Wrapper for fnsave instruction to handle h/w bugs. If there is an error
836 * pending, then fnsave generates a bogus IRQ13 on some systems. Force
837 * any IRQ13 to be handled immediately, and then ignore it. This routine is

--- 10 unchanged lines hidden (view full) ---

848 stop_emulating();
849 fnsave(addr);
850 /* fnop(); */
851 start_emulating();
852 PCPU_SET(npxproc, NULL);
853
854#else /* SMP */
855
858 int intrstate;
856 critical_t savecrit;
859 u_char icu1_mask;
860 u_char icu2_mask;
861 u_char old_icu1_mask;
862 u_char old_icu2_mask;
863 struct gate_descriptor save_idt_npxintr;
864
857 u_char icu1_mask;
858 u_char icu2_mask;
859 u_char old_icu1_mask;
860 u_char old_icu2_mask;
861 struct gate_descriptor save_idt_npxintr;
862
865 intrstate = save_intr();
866 disable_intr();
863 savecrit = critical_enter();
867 old_icu1_mask = inb(IO_ICU1 + 1);
868 old_icu2_mask = inb(IO_ICU2 + 1);
869 save_idt_npxintr = idt[npx_intrno];
870 outb(IO_ICU1 + 1, old_icu1_mask & ~(IRQ_SLAVE | npx0_imask));
871 outb(IO_ICU2 + 1, old_icu2_mask & ~(npx0_imask >> 8));
872 idt[npx_intrno] = npx_idt_probeintr;
864 old_icu1_mask = inb(IO_ICU1 + 1);
865 old_icu2_mask = inb(IO_ICU2 + 1);
866 save_idt_npxintr = idt[npx_intrno];
867 outb(IO_ICU1 + 1, old_icu1_mask & ~(IRQ_SLAVE | npx0_imask));
868 outb(IO_ICU2 + 1, old_icu2_mask & ~(npx0_imask >> 8));
869 idt[npx_intrno] = npx_idt_probeintr;
873 write_eflags(intrstate);
870 critical_exit(savecrit);
874 stop_emulating();
875 fnsave(addr);
876 fnop();
877 start_emulating();
871 stop_emulating();
872 fnsave(addr);
873 fnop();
874 start_emulating();
875 savecrit = critical_enter();
878 PCPU_SET(npxproc, NULL);
876 PCPU_SET(npxproc, NULL);
879 disable_intr();
880 icu1_mask = inb(IO_ICU1 + 1); /* masks may have changed */
881 icu2_mask = inb(IO_ICU2 + 1);
882 outb(IO_ICU1 + 1,
883 (icu1_mask & ~npx0_imask) | (old_icu1_mask & npx0_imask));
884 outb(IO_ICU2 + 1,
885 (icu2_mask & ~(npx0_imask >> 8))
886 | (old_icu2_mask & (npx0_imask >> 8)));
887 idt[npx_intrno] = save_idt_npxintr;
877 icu1_mask = inb(IO_ICU1 + 1); /* masks may have changed */
878 icu2_mask = inb(IO_ICU2 + 1);
879 outb(IO_ICU1 + 1,
880 (icu1_mask & ~npx0_imask) | (old_icu1_mask & npx0_imask));
881 outb(IO_ICU2 + 1,
882 (icu2_mask & ~(npx0_imask >> 8))
883 | (old_icu2_mask & (npx0_imask >> 8)));
884 idt[npx_intrno] = save_idt_npxintr;
888 restore_intr(intrstate); /* back to previous state */
885 critical_exit(savecrit); /* back to previous state */
889
890#endif /* SMP */
891}
892
893#ifdef I586_CPU
894static long
895timezero(funcname, func)
896 const char *funcname;

--- 99 unchanged lines hidden ---
886
887#endif /* SMP */
888}
889
890#ifdef I586_CPU
891static long
892timezero(funcname, func)
893 const char *funcname;

--- 99 unchanged lines hidden ---