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>
