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