Skip site navigation (1)Skip section navigation (2)
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>