Even though BIOS writer's guide recommends cpuid instruction of Cyrix

6x86MX CPU is enabled (BIOS should not disable it), some BIOS disables
it via CCR4.  In this case, cpu variable becomes CPU_486 and
identblue() is called.  Because Cyrix 6x86MX has MSR and doesn't have
MSR1002, wrmsr instruction generates general protection fault.

Tested by:	Simon Coggins <chaos@ultra.net.au>
This commit is contained in:
kato 1998-01-25 12:01:38 +00:00
parent 014c10f649
commit 4f6278680f
6 changed files with 116 additions and 36 deletions

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
* $Id: identcpu.c,v 1.37 1998/01/03 05:36:40 obrien Exp $
* $Id: identcpu.c,v 1.38 1998/01/03 05:43:37 obrien Exp $
*/
#include "opt_cpu.h"
@ -55,10 +55,14 @@
#include <i386/isa/intr_machdep.h>
#define IDENTBLUE_CYRIX486 0
#define IDENTBLUE_IBMCPU 1
#define IDENTBLUE_CYRIXM2 2
/* XXX - should be in header file */
void i486_bzero __P((void *buf, size_t len));
void printcpuinfo(void); /* XXX should be in different header file */
void printcpuinfo(void); /* XXX should be in different header file */
void finishidentcpu(void);
void earlysetcpuclass(void);
void panicifcpuunsupported(void);
@ -534,21 +538,38 @@ panicifcpuunsupported(void)
static volatile u_int trap_by_wrmsr;
/*
* Special exception 16 handler.
* Special exception 6 handler.
* The wrmsr instruction generates invalid opcodes fault on 486-class
* Cyrix CPU. Stacked eip register points the wrmsr instruction in the
* function identblue() when this handler is called. Stacked eip should
* be advanced.
*/
inthand_t bluetrap;
inthand_t bluetrap6;
asm
("
.text
.p2align 2,0x90
" __XSTRING(CNAME(bluetrap)) ":
" __XSTRING(CNAME(bluetrap6)) ":
ss
movl $0xa8c1d," __XSTRING(CNAME(trap_by_wrmsr)) " # Don't ask meaning of the number :-).
addl $2, (%esp) # I know wrmsr is a 2-bytes instruction.
movl $0xa8c1d," __XSTRING(CNAME(trap_by_wrmsr)) "
addl $2, (%esp) # I know wrmsr is a 2-bytes instruction.
iret
");
/*
* Special exception 13 handler.
* Accessing non-existent MSR generates general protection fault.
*/
inthand_t bluetrap13;
asm
("
.text
.p2align 2,0x90
" __XSTRING(CNAME(bluetrap13)) ":
ss
movl $0xa89c4," __XSTRING(CNAME(trap_by_wrmsr)) "
popl %eax # discard errorcode.
addl $2, (%esp) # I know wrmsr is a 2-bytes instruction.
iret
");
@ -565,19 +586,29 @@ identblue(void)
{
trap_by_wrmsr = 0;
/*
* Cyrix 486-class CPU does not support wrmsr instruction.
* The wrmsr instruction causes invalid opcode fault, and exception
* will be trapped by bluetrap() on Cyrix 486-class CPU. The bluetrap()
* set the magic number to trap_by_wrmsr.
* The wrmsr instruction generates invalid opcode fault, and exception
* will be trapped by bluetrap6() on Cyrix 486-class CPU. The
* bluetrap6() set the magic number to trap_by_wrmsr.
*/
setidt(6, bluetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
wrmsr(0x1002, 0x03000000LL); /* Fault on Cyrix 486-class CPU. */
setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
/*
* Certain BIOS disables cpuid instructnion of Cyrix 6x86MX CPU.
* In this case, wrmsr generates general protection fault, and
* exception will be trapped by bluetrap13().
*/
setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
wrmsr(0x1002, 0x03000000LL); /* Cyrix CPU generates fault. */
if (trap_by_wrmsr == 0xa8c1d)
return 0; /* Cyrix CPU sets the magic number. */
return 1; /* IBM Blue Lightnig CPU */
return IDENTBLUE_CYRIX486;
else if (trap_by_wrmsr == 0xa89c4)
return IDENTBLUE_CYRIXM2;
return IDENTBLUE_IBMCPU;
}
@ -632,6 +663,7 @@ identifycyrix(void)
void
finishidentcpu(void)
{
int isblue = 0;
if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
if (cpu == CPU_486) {
@ -640,7 +672,8 @@ finishidentcpu(void)
* - CPU does not support cpuid instruction.
* - Cyrix/IBM CPU is detected.
*/
if (identblue()) {
isblue = identblue();
if (isblue == IDENTBLUE_IBMCPU) {
strcpy(cpu_vendor, "IBM");
cpu = CPU_BLUE;
return;
@ -686,6 +719,11 @@ finishidentcpu(void)
default:
/* M2 and later CPUs are treated as M2. */
cpu = CPU_M2;
/*
* XXX
* Execute cpuid instrunction here and fix cpu_id and
* cpu_feature variables.
*/
break;
}
}

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.282 1998/01/22 17:29:26 dyson Exp $
* $Id: machdep.c,v 1.283 1998/01/24 02:00:47 dyson Exp $
*/
#include "apm.h"
@ -1225,6 +1225,7 @@ init386(first)
finishidentcpu(); /* Final stage of CPU initialization */
setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
/* Use BIOS values stored in RTC CMOS RAM, since probing

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
* $Id: identcpu.c,v 1.37 1998/01/03 05:36:40 obrien Exp $
* $Id: identcpu.c,v 1.38 1998/01/03 05:43:37 obrien Exp $
*/
#include "opt_cpu.h"
@ -55,10 +55,14 @@
#include <i386/isa/intr_machdep.h>
#define IDENTBLUE_CYRIX486 0
#define IDENTBLUE_IBMCPU 1
#define IDENTBLUE_CYRIXM2 2
/* XXX - should be in header file */
void i486_bzero __P((void *buf, size_t len));
void printcpuinfo(void); /* XXX should be in different header file */
void printcpuinfo(void); /* XXX should be in different header file */
void finishidentcpu(void);
void earlysetcpuclass(void);
void panicifcpuunsupported(void);
@ -534,21 +538,38 @@ panicifcpuunsupported(void)
static volatile u_int trap_by_wrmsr;
/*
* Special exception 16 handler.
* Special exception 6 handler.
* The wrmsr instruction generates invalid opcodes fault on 486-class
* Cyrix CPU. Stacked eip register points the wrmsr instruction in the
* function identblue() when this handler is called. Stacked eip should
* be advanced.
*/
inthand_t bluetrap;
inthand_t bluetrap6;
asm
("
.text
.p2align 2,0x90
" __XSTRING(CNAME(bluetrap)) ":
" __XSTRING(CNAME(bluetrap6)) ":
ss
movl $0xa8c1d," __XSTRING(CNAME(trap_by_wrmsr)) " # Don't ask meaning of the number :-).
addl $2, (%esp) # I know wrmsr is a 2-bytes instruction.
movl $0xa8c1d," __XSTRING(CNAME(trap_by_wrmsr)) "
addl $2, (%esp) # I know wrmsr is a 2-bytes instruction.
iret
");
/*
* Special exception 13 handler.
* Accessing non-existent MSR generates general protection fault.
*/
inthand_t bluetrap13;
asm
("
.text
.p2align 2,0x90
" __XSTRING(CNAME(bluetrap13)) ":
ss
movl $0xa89c4," __XSTRING(CNAME(trap_by_wrmsr)) "
popl %eax # discard errorcode.
addl $2, (%esp) # I know wrmsr is a 2-bytes instruction.
iret
");
@ -565,19 +586,29 @@ identblue(void)
{
trap_by_wrmsr = 0;
/*
* Cyrix 486-class CPU does not support wrmsr instruction.
* The wrmsr instruction causes invalid opcode fault, and exception
* will be trapped by bluetrap() on Cyrix 486-class CPU. The bluetrap()
* set the magic number to trap_by_wrmsr.
* The wrmsr instruction generates invalid opcode fault, and exception
* will be trapped by bluetrap6() on Cyrix 486-class CPU. The
* bluetrap6() set the magic number to trap_by_wrmsr.
*/
setidt(6, bluetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
wrmsr(0x1002, 0x03000000LL); /* Fault on Cyrix 486-class CPU. */
setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
/*
* Certain BIOS disables cpuid instructnion of Cyrix 6x86MX CPU.
* In this case, wrmsr generates general protection fault, and
* exception will be trapped by bluetrap13().
*/
setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
wrmsr(0x1002, 0x03000000LL); /* Cyrix CPU generates fault. */
if (trap_by_wrmsr == 0xa8c1d)
return 0; /* Cyrix CPU sets the magic number. */
return 1; /* IBM Blue Lightnig CPU */
return IDENTBLUE_CYRIX486;
else if (trap_by_wrmsr == 0xa89c4)
return IDENTBLUE_CYRIXM2;
return IDENTBLUE_IBMCPU;
}
@ -632,6 +663,7 @@ identifycyrix(void)
void
finishidentcpu(void)
{
int isblue = 0;
if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
if (cpu == CPU_486) {
@ -640,7 +672,8 @@ finishidentcpu(void)
* - CPU does not support cpuid instruction.
* - Cyrix/IBM CPU is detected.
*/
if (identblue()) {
isblue = identblue();
if (isblue == IDENTBLUE_IBMCPU) {
strcpy(cpu_vendor, "IBM");
cpu = CPU_BLUE;
return;
@ -686,6 +719,11 @@ finishidentcpu(void)
default:
/* M2 and later CPUs are treated as M2. */
cpu = CPU_M2;
/*
* XXX
* Execute cpuid instrunction here and fix cpu_id and
* cpu_feature variables.
*/
break;
}
}

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.282 1998/01/22 17:29:26 dyson Exp $
* $Id: machdep.c,v 1.283 1998/01/24 02:00:47 dyson Exp $
*/
#include "apm.h"
@ -1225,6 +1225,7 @@ init386(first)
finishidentcpu(); /* Final stage of CPU initialization */
setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
/* Use BIOS values stored in RTC CMOS RAM, since probing

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.70 1998/01/24 03:15:37 kato Exp $
* $Id: machdep.c,v 1.71 1998/01/24 06:53:32 kato Exp $
*/
#include "apm.h"
@ -1249,6 +1249,7 @@ init386(first)
finishidentcpu(); /* Final stage of CPU initialization */
setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
#ifdef PC98

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.70 1998/01/24 03:15:37 kato Exp $
* $Id: machdep.c,v 1.71 1998/01/24 06:53:32 kato Exp $
*/
#include "apm.h"
@ -1249,6 +1249,7 @@ init386(first)
finishidentcpu(); /* Final stage of CPU initialization */
setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
#ifdef PC98