Date: Wed, 11 Sep 1996 20:39:15 +0900 From: KATO Takenori <kato@eclogite.eps.nagoya-u.ac.jp> To: current@freebsd.org Subject: patch for Cyrix/Ti 486SLC/DLC CPU bug Message-ID: <199609111139.UAA00456@marble.eps.nagoya-u.ac.jp>
next in thread | raw e-mail | index | archive | help
Hi, Cyrix/Ti 486 users, Some version of Cyrix 486SLC/DLC and TI 486DLC have paging related bug, and they cause strange segmentation fault and/or page fault trap. I got some information for that bug and fix, and I made the patch for FreeBSD-current. The patch contains: 1) FPU exception is handled by interrupt gate (machdep.c). 2) The function trap gets fault page address as soon as possible (trap.c). 3) The functions pmap_update_{1,2}pg don't use LMSW instruction but call pmap_update in cpufunc.h (pmap.c). 1 and 2 are effective for strange signal 11, and 3 is for page fault. These change are #ifdef'ed because it might have disadvantage for system performance. Please add "options CYRIX_486_BUG" line in your kernel configuration file to enable bug fix. Above change has been already included in sys/pc98/i386 stuffs of FreeBSD-current, and it has been tested Cyrix/Ti 486 users on PC-9801 architecture. Is this effective for you? Comment please! ---------- BEGIN ---------- diff -arcN sys.old/i386/i386/machdep.c sys/i386/i386/machdep.c *** sys.old/i386/i386/machdep.c Wed Sep 11 18:42:45 1996 --- sys/i386/i386/machdep.c Wed Sep 11 18:44:02 1996 *************** *** 1040,1046 **** --- 1040,1050 ---- setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + #ifdef CYRIX_486_BUG setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + #else + setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + #endif setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); diff -arcN sys.old/i386/i386/pmap.c sys/i386/i386/pmap.c *** sys.old/i386/i386/pmap.c Wed Sep 11 18:42:45 1996 --- sys/i386/i386/pmap.c Wed Sep 11 18:44:31 1996 *************** *** 148,153 **** --- 148,157 ---- extern vm_offset_t clean_sva, clean_eva; extern int cpu_class; + #if defined(I386_CPU) || defined(CYRIX_486_BUG) + extern int cpu; + #endif + #define PV_FREELIST_MIN ((PAGE_SIZE / sizeof (struct pv_entry)) / 2) /* *************** *** 407,414 **** */ static PMAP_INLINE void pmap_update_1pg( vm_offset_t va) { ! #if defined(I386_CPU) ! if (cpu_class == CPUCLASS_386) pmap_update(); else #endif --- 411,419 ---- */ static PMAP_INLINE void pmap_update_1pg( vm_offset_t va) { ! #if defined(I386_CPU) || defined(CYRIX_486_BUG) ! /* CYRIX Bug? */ ! if (cpu_class == CPUCLASS_386 || cpu == CPU_486DLC) pmap_update(); else #endif *************** *** 417,424 **** static PMAP_INLINE void pmap_update_2pg( vm_offset_t va1, vm_offset_t va2) { ! #if defined(I386_CPU) ! if (cpu_class == CPUCLASS_386) { pmap_update(); } else #endif --- 422,430 ---- static PMAP_INLINE void pmap_update_2pg( vm_offset_t va1, vm_offset_t va2) { ! #if defined(I386_CPU) || defined(CYRIX_486_BUG) ! /* CYRIX Bug? */ ! if (cpu_class == CPUCLASS_386 || cpu == CPU_486DLC) { pmap_update(); } else #endif diff -arcN sys.old/i386/i386/trap.c sys/i386/i386/trap.c *** sys.old/i386/i386/trap.c Wed Sep 11 18:42:45 1996 --- sys/i386/i386/trap.c Wed Sep 11 18:45:20 1996 *************** *** 77,88 **** #include <machine/trap.h> #include <machine/../isa/isa_device.h> #ifdef POWERFAIL_NMI #include <sys/syslog.h> #include <machine/clock.h> #endif - #include "isa.h" #include "npx.h" int (*pmath_emulate) __P((struct trapframe *)); --- 77,89 ---- #include <machine/trap.h> #include <machine/../isa/isa_device.h> + #include "isa.h" + #ifdef POWERFAIL_NMI #include <sys/syslog.h> #include <machine/clock.h> #endif #include "npx.h" int (*pmath_emulate) __P((struct trapframe *)); *************** *** 91,97 **** --- 92,102 ---- extern int trapwrite __P((unsigned addr)); extern void syscall __P((struct trapframe frame)); + #ifdef CYRIX_486_BUG + static int trap_pfault __P((struct trapframe *, int, vm_offset_t)); + #else static int trap_pfault __P((struct trapframe *, int)); + #endif static void trap_fatal __P((struct trapframe *)); void dblfault_handler __P((void)); *************** *** 188,197 **** --- 193,218 ---- #ifdef DEBUG u_long eva; #endif + #ifdef CYRIX_486_BUG + vm_offset_t va; + #endif type = frame.tf_trapno; code = frame.tf_err; + #ifdef CYRIX_486_BUG + /* XXX: + * CYRIX 486 CPU FIX. + * If you use cyrix cpu, you often encouter strange signal 11's? + * I think this is due to cyrix cpu bugs. + * In any way, the following trick is effective for the problem. + * As soon as possible, we must get the fault page address. + */ + va = (vm_offset_t)(rcr2()); + if( type == T_PAGEFLT && ( frame.tf_eflags & PSL_I ) ) + asm("sti"); + #endif /* CYRIX_486_BUG */ + if (ISPL(frame.tf_cs) == SEL_UPL) { /* user trap */ *************** *** 236,242 **** --- 257,267 ---- break; case T_PAGEFLT: /* page fault */ + #ifdef CYRIX_486_BUG + i = trap_pfault(&frame, TRUE, va); + #else i = trap_pfault(&frame, TRUE); + #endif if (i == -1) return; if (i == 0) *************** *** 308,314 **** --- 333,343 ---- switch (type) { case T_PAGEFLT: /* page fault */ + #ifdef CYRIX_486_BUG + (void) trap_pfault(&frame, FALSE, va); + #else (void) trap_pfault(&frame, FALSE); + #endif return; case T_DNA: *************** *** 467,475 **** --- 496,511 ---- * debugging code. */ static int + #ifdef CYRIX_486_BUG + trap_pfault(frame, usermode,faultva) + struct trapframe *frame; + int usermode; + vm_offset_t faultva; + #else trap_pfault(frame, usermode) struct trapframe *frame; int usermode; + #endif { vm_offset_t va; struct vmspace *vm = NULL; *************** *** 484,490 **** --- 520,530 ---- else ftype = VM_PROT_READ; + #ifdef CYRIX_486_BUG + eva = faultva; + #else eva = rcr2(); + #endif va = trunc_page((vm_offset_t)eva); if (va < VM_MIN_KERNEL_ADDRESS) { *************** *** 566,574 **** --- 606,621 ---- #endif int + #ifdef CYRIX_486_BUG + trap_pfault(frame, usermode,faultva) + struct trapframe *frame; + int usermode; + vm_offset_t faultva; + #else trap_pfault(frame, usermode) struct trapframe *frame; int usermode; + #endif { vm_offset_t va; struct vmspace *vm = NULL; *************** *** 578,584 **** --- 625,635 ---- int eva; struct proc *p = curproc; + #ifdef CYRIX_486_BUG + eva = faultva; + #else eva = rcr2(); + #endif va = trunc_page((vm_offset_t)eva); if (va >= KERNBASE) { ---------- END ---------- ---- KATO Takenori <kato@eclogite.eps.nagoya-u.ac.jp> Dept. Earth Planet. Sci., Nagoya Univ., Nagoya, 464-01, Japan
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199609111139.UAA00456>