-in case of --enable-ignore-bad-msr enabled read ignored MSRs as zeRo

- enabled #DE and #TSD and #MCE bits in CR4 register, previosly setting
    of one of these bits generated #GP(0) (Stanislav, Volker Ruppert)
This commit is contained in:
Stanislav Shwartsman 2005-02-03 18:25:10 +00:00
parent 5ec5e89575
commit d27e81bdac
2 changed files with 98 additions and 82 deletions

View File

@ -26,10 +26,13 @@ Changes to next release:
instructions (Stanislav Shwartsman)
- fixed CF flag handling for SHL instruction in x86-64 mode
(Stanislav Shwartsman)
- added missed GP(0) exception when loading incorrect flags combination
- added missed #GP(0) exception when loading incorrect flags combination
to CR0 (Stanislav Shwartsman)
- implemented CR8 register (aliased to APIC.TPR[7:4]) in x86-64 mode
- implemented NXE bit (No-Execute page protection) support for x86-64
- in case of --enable-ignore-bad-msr enabled read ignored MSRs as zero
- enabled #DE and #TSD and #MCE bits in CR4 register, previosly setting
of one of these bits generated #GP(0) (Stanislav, Volker Ruppert)
- FPU
- totally rewritten all FPU code based on softfloat library
@ -202,6 +205,7 @@ Changes to next release:
- patches applied
- patch.rombios.markevich (Start/Stop Wait Timer) (Kory Markevich)
- patch.apic-zwane (APIC fixes) (Zwane Mwaikambo)
- patch.v8086-exception.lightcone (LightCone)
- these S.F. bugs were closed
#549793 flaw in interrupt gate handling(exception.cc)

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.91 2005-01-23 21:13:49 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.92 2005-02-03 18:25:10 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -68,7 +68,7 @@ void BX_CPU_C::HLT(bxInstruction_c *i)
if (CPL!=0) {
exception(BX_GP_EXCEPTION, 0, 0);
return;
}
}
if (! BX_CPU_THIS_PTR get_IF ()) {
BX_INFO(("WARNING: HLT instruction with IF=0!"));
@ -104,7 +104,7 @@ BX_CPU_C::CLTS(bxInstruction_c *i)
BX_INFO(("CLTS: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
return;
}
}
BX_CPU_THIS_PTR cr0.ts = 0;
BX_CPU_THIS_PTR cr0.val32 &= ~0x08;
@ -125,8 +125,8 @@ void BX_CPU_C::INVD(bxInstruction_c *i)
if (CPL!=0) {
BX_INFO(("INVD: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
}
BX_INSTR_CACHE_CNTRL(BX_CPU_ID, BX_INSTR_INVD);
#else
UndefinedOpcode(i);
@ -144,8 +144,8 @@ void BX_CPU_C::WBINVD(bxInstruction_c *i)
if (CPL!=0) {
BX_INFO(("WBINVD: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
}
BX_INSTR_CACHE_CNTRL(BX_CPU_ID, BX_INSTR_WBINVD);
#else
UndefinedOpcode(i);
@ -212,7 +212,7 @@ void BX_CPU_C::MOV_DdRd(bxInstruction_c *i)
// Debug extensions on
BX_INFO(("MOV_DdRd: access to DR4 causes #UD"));
UndefinedOpcode(i);
}
}
#endif
#if BX_CPU_LEVEL <= 4
// On 386/486 bit12 is settable
@ -238,35 +238,36 @@ void BX_CPU_C::MOV_DdRd(bxInstruction_c *i)
// Debug extensions (CR4.DE) on
BX_INFO(("MOV_DdRd: access to DR5 causes #UD"));
UndefinedOpcode(i);
}
}
#endif
// Some sanity checks...
if ( val_32 & 0x00002000 ) {
BX_PANIC(("MOV_DdRd: GD bit not supported yet"));
// Note: processor clears GD upon entering debug exception
// handler, to allow access to the debug registers
}
}
if ( (((val_32>>16) & 3)==2) ||
(((val_32>>20) & 3)==2) ||
(((val_32>>24) & 3)==2) ||
(((val_32>>28) & 3)==2) ) {
// IO breakpoints (10b) are not yet supported.
BX_PANIC(("MOV_DdRd: write of %08x contains IO breakpoint", val_32));
}
}
if ( (((val_32>>18) & 3)==2) ||
(((val_32>>22) & 3)==2) ||
(((val_32>>26) & 3)==2) ||
(((val_32>>30) & 3)==2) ) {
// LEN0..3 contains undefined length specifier (10b)
BX_PANIC(("MOV_DdRd: write of %08x contains undefined LENx", val_32));
}
}
if ( ((((val_32>>16) & 3)==0) && (((val_32>>18) & 3)!=0)) ||
((((val_32>>20) & 3)==0) && (((val_32>>22) & 3)!=0)) ||
((((val_32>>24) & 3)==0) && (((val_32>>26) & 3)!=0)) ||
((((val_32>>28) & 3)==0) && (((val_32>>30) & 3)!=0)) ) {
((((val_32>>28) & 3)==0) && (((val_32>>30) & 3)!=0)) )
{
// Instruction breakpoint with LENx not 00b (1-byte length)
BX_PANIC(("MOV_DdRd: write of %08x, R/W=00b LEN!=00b", val_32));
}
}
#if BX_CPU_LEVEL <= 4
// 386/486: you can play with all the bits except b10 is always 1
BX_CPU_THIS_PTR dr7 = val_32 | 0x00000400;
@ -298,7 +299,7 @@ void BX_CPU_C::MOV_RdDd(bxInstruction_c *i)
if (v8086_mode()) {
BX_INFO(("MOV_RdDd: v8086 mode causes #GP(0)"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
@ -338,7 +339,7 @@ void BX_CPU_C::MOV_RdDd(bxInstruction_c *i)
// Debug extensions on
BX_INFO(("MOV_RdDd: access to DR4 causes #UD"));
UndefinedOpcode(i);
}
}
#endif
val_32 = BX_CPU_THIS_PTR dr6;
break;
@ -352,7 +353,7 @@ void BX_CPU_C::MOV_RdDd(bxInstruction_c *i)
// Debug extensions on
BX_INFO(("MOV_RdDd: access to DR5 causes #UD"));
UndefinedOpcode(i);
}
}
#endif
val_32 = BX_CPU_THIS_PTR dr7;
break;
@ -373,7 +374,7 @@ void BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
if (v8086_mode()) {
BX_INFO(("MOV_DqRq: v8086 mode causes #GP(0)"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
/* NOTES:
* 64bit operands always used
@ -447,7 +448,7 @@ void BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
BX_PANIC(("MOV_DqRq: GD bit not supported yet"));
// Note: processor clears GD upon entering debug exception
// handler, to allow access to the debug registers
}
}
if ( (((val_64>>16) & 3)==2) ||
(((val_64>>20) & 3)==2) ||
(((val_64>>24) & 3)==2) ||
@ -494,7 +495,7 @@ void BX_CPU_C::MOV_RqDq(bxInstruction_c *i)
if (v8086_mode()) {
BX_INFO(("MOV_RqDq: v8086 mode causes #GP(0)"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
@ -552,7 +553,7 @@ void BX_CPU_C::MOV_RqDq(bxInstruction_c *i)
default:
BX_PANIC(("MOV_RqDq: control register index out of range"));
val_64 = 0;
}
}
BX_WRITE_64BIT_REG(i->rm(), val_64);
}
#endif // #if BX_SUPPORT_X86_64
@ -571,15 +572,15 @@ void BX_CPU_C::LMSW_Ew(bxInstruction_c *i)
if (CPL != 0) {
BX_INFO(("LMSW: CPL != 0, CPL=%u", (unsigned) CPL));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
}
if (i->modC0()) {
msw = BX_READ_16BIT_REG(i->rm());
}
}
else {
read_virtual_word(i->seg(), RMAddr(i), &msw);
}
}
// LMSW does not affect PG,CD,NW,AM,WP,NE,ET bits, and cannot clear PE
@ -613,14 +614,14 @@ void BX_CPU_C::SMSW_Ew(bxInstruction_c *i)
if (i->modC0()) {
if (i->os32L()) {
BX_WRITE_32BIT_REGZ(i->rm(), msw); // zeros out high 16bits
}
}
else {
BX_WRITE_16BIT_REG(i->rm(), msw);
}
}
}
else {
write_virtual_word(i->seg(), RMAddr(i), &msw);
}
}
#endif
}
@ -699,7 +700,7 @@ void BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
default:
BX_PANIC(("MOV_CdRd: control register index out of range"));
break;
}
}
#endif
}
@ -711,7 +712,7 @@ void BX_CPU_C::MOV_RdCd(bxInstruction_c *i)
#else
Bit32u val_32;
if (v8086_mode()){
if (v8086_mode()) {
BX_INFO(("MOV_RdCd: v8086 mode causes #GP(0)"));
exception(BX_GP_EXCEPTION, 0, 0);
}
@ -855,7 +856,7 @@ void BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
default:
BX_PANIC(("MOV_CqRq: control register index out of range"));
break;
}
}
}
void BX_CPU_C::MOV_RqCq(bxInstruction_c *i)
@ -1006,21 +1007,22 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
BX_CPU_THIS_PTR tr.cache.u.tss286.base = (base_23_16 << 16) | base_15_0;
BX_CPU_THIS_PTR tr.cache.u.tss286.limit = limit;
if ( (BX_CPU_THIS_PTR tr.selector.value & 0xfffc) == 0 ) {
if ((BX_CPU_THIS_PTR tr.selector.value & 0xfffc) == 0) {
BX_CPU_THIS_PTR tr.cache.valid = 0;
}
if ( BX_CPU_THIS_PTR tr.cache.valid == 0 ) {
}
if ( BX_CPU_THIS_PTR tr.cache.u.tss286.limit < 43 ) {
}
if (BX_CPU_THIS_PTR tr.cache.valid == 0) {
}
if (BX_CPU_THIS_PTR tr.cache.u.tss286.limit < 43) {
BX_CPU_THIS_PTR tr.cache.valid = 0;
}
if ( BX_CPU_THIS_PTR tr.cache.type != 1 ) {
}
if (BX_CPU_THIS_PTR tr.cache.type != 1) {
BX_CPU_THIS_PTR tr.cache.valid = 0;
}
if ( BX_CPU_THIS_PTR tr.cache.segment ) {
}
if (BX_CPU_THIS_PTR tr.cache.segment) {
BX_CPU_THIS_PTR tr.cache.valid = 0;
}
if (BX_CPU_THIS_PTR tr.cache.valid==0) {
}
if (BX_CPU_THIS_PTR tr.cache.valid==0)
{
BX_CPU_THIS_PTR tr.cache.u.tss286.base = 0;
BX_CPU_THIS_PTR tr.cache.u.tss286.limit = 0;
BX_CPU_THIS_PTR tr.cache.p = 0;
@ -1028,7 +1030,7 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
BX_CPU_THIS_PTR tr.selector.index = 0;
BX_CPU_THIS_PTR tr.selector.ti = 0;
BX_CPU_THIS_PTR tr.selector.rpl = 0;
}
}
/* FLAGS */
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x818, 2, &flags);
@ -1044,7 +1046,8 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
BX_CPU_THIS_PTR ldtr.selector.rpl = (ldtr & 0x03); ldtr >>= 2;
BX_CPU_THIS_PTR ldtr.selector.ti = (ldtr & 0x01); ldtr >>= 1;
BX_CPU_THIS_PTR ldtr.selector.index = ldtr;
if ( (BX_CPU_THIS_PTR ldtr.selector.value & 0xfffc) == 0 ) {
if ((BX_CPU_THIS_PTR ldtr.selector.value & 0xfffc) == 0)
{
BX_CPU_THIS_PTR ldtr.cache.valid = 0;
BX_CPU_THIS_PTR ldtr.cache.p = 0;
BX_CPU_THIS_PTR ldtr.cache.segment = 0;
@ -1054,7 +1057,7 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
BX_CPU_THIS_PTR ldtr.selector.value = 0;
BX_CPU_THIS_PTR ldtr.selector.index = 0;
BX_CPU_THIS_PTR ldtr.selector.ti = 0;
}
}
else {
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x854, 2, &base_15_0);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x856, 1, &base_23_16);
@ -1070,18 +1073,18 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
if (access == 0) {
BX_PANIC(("loadall: LDTR case access byte=0."));
}
if ( BX_CPU_THIS_PTR ldtr.cache.valid==0 ) {
}
if (BX_CPU_THIS_PTR ldtr.cache.valid==0) {
BX_PANIC(("loadall: ldtr.valid=0"));
}
}
if (BX_CPU_THIS_PTR ldtr.cache.segment) { /* not a system segment */
BX_INFO((" AR byte = %02x", (unsigned) access));
BX_PANIC(("loadall: LDTR descriptor cache loaded with non system segment"));
}
if ( BX_CPU_THIS_PTR ldtr.cache.type != 2 ) {
BX_PANIC(("loadall: LDTR.type(%u) != 2", (unsigned) (access & 0x0f)));
}
}
if (BX_CPU_THIS_PTR ldtr.cache.type != 2) {
BX_PANIC(("loadall: LDTR.type(%u) != 2", (unsigned) (access & 0x0f)));
}
}
/* DS */
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x81e, 2, &ds_raw);
@ -1106,11 +1109,12 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
if ( (BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value & 0xfffc) == 0 ) {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = 0;
}
}
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid==0 ||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.segment==0) {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.segment==0)
{
BX_PANIC(("loadall: DS invalid"));
}
}
/* SS */
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x820, 2, &ss_raw);
@ -1132,15 +1136,15 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = (access & 0x03); access >>= 2;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = (access & 0x01);
if ( (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value & 0xfffc) == 0 ) {
if ((BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value & 0xfffc) == 0) {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 0;
}
}
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid==0 ||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment==0) {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment==0)
{
BX_PANIC(("loadall: SS invalid"));
}
}
/* CS */
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x822, 2, &cs_raw);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = cs_raw;
@ -1165,13 +1169,15 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = (access & 0x03); access >>= 2;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = (access & 0x01);
if ( (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value & 0xfffc) == 0 ) {
if ((BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value & 0xfffc) == 0)
{
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 0;
}
}
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid==0 ||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment==0) {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment==0)
{
BX_PANIC(("loadall: CS invalid"));
}
}
/* ES */
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x824, 2, &es_raw);
@ -1208,13 +1214,15 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
(unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.rpl));
#endif
if ( (BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value & 0xfffc) == 0 ) {
if ((BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value & 0xfffc) == 0)
{
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0;
}
}
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid==0 ||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.segment==0) {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.segment==0)
{
BX_PANIC(("loadall: ES invalid"));
}
}
/* DI */
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, 0x826, 2, &di);
@ -1333,13 +1341,13 @@ void BX_CPU_C::SetCR0(Bit32u val_32)
BX_CPU_THIS_PTR protectedMode = 1;
BX_CPU_THIS_PTR v8086Mode = 0;
BX_CPU_THIS_PTR realMode = 0;
}
}
else if (prev_pe==1 && BX_CPU_THIS_PTR cr0.pe==0) {
enter_real_mode();
BX_CPU_THIS_PTR protectedMode = 0;
BX_CPU_THIS_PTR v8086Mode = 0;
BX_CPU_THIS_PTR realMode = 1;
}
}
#if BX_SUPPORT_X86_64
if (prev_pg==0 && BX_CPU_THIS_PTR cr0.pg) {
@ -1347,26 +1355,26 @@ void BX_CPU_C::SetCR0(Bit32u val_32)
if (!BX_CPU_THIS_PTR cr4.get_PAE()) {
BX_PANIC(("SetCR0: attempt to enter x86-64 LONG mode without enabling CR4.PAE !!!"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
BX_CPU_THIS_PTR msr.lma = 1;
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT;
#if BX_EXTERNAL_DEBUGGER
//trap_debugger(0);
#endif
}
}
}
else if (prev_pg==1 && BX_CPU_THIS_PTR cr0.pg==0) {
if (BX_CPU_THIS_PTR msr.lma) {
if (BX_CPU_THIS_PTR dword.rip_upper != 0) {
BX_PANIC(("SetCR0: attempt to leave x86-64 LONG mode with RIP upper != 0 !!!"));
}
}
BX_CPU_THIS_PTR msr.lma = 0;
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32;
#if BX_EXTERNAL_DEBUGGER
//trap_debugger(0);
#endif
}
}
}
#endif // #if BX_SUPPORT_X86_64
// Give the paging unit a chance to look for changes in bits
@ -1377,6 +1385,9 @@ void BX_CPU_C::SetCR0(Bit32u val_32)
#if BX_CPU_LEVEL >= 4
void BX_CPU_C::SetCR4(Bit32u val_32)
{
Bit32u oldCR4 = BX_CPU_THIS_PTR cr4.getRegister();
Bit32u allowMask = 0;
// CR4 bit definitions from AMD Hammer manual:
// [63-11] Reserved, Must be Zero
// [10] OSXMMEXCPT: Operating System Unmasked Exception Support R/W
@ -1391,8 +1402,7 @@ void BX_CPU_C::SetCR4(Bit32u val_32)
// [1] PVI: Protected-Mode Virtual Interrupts R/W
// [0] VME: Virtual-8086 Mode Extensions R/W
Bit32u oldCR4 = BX_CPU_THIS_PTR cr4.getRegister();
Bit32u allowMask = 0;
allowMask |= (1<<3); /* DE */
#if BX_CPU_LEVEL >= 5
allowMask |= (1<<2); /* TSD */
@ -1531,12 +1541,12 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
if (v8086_mode()) {
BX_INFO(("RDMSR: Invalid in virtual 8086 mode"));
goto do_exception;
}
}
if (CPL!= 0) {
BX_INFO(("RDMSR: CPL!= 0"));
BX_INFO(("RDMSR: CPL != 0"));
goto do_exception;
}
}
/* We have the requested MSR register in ECX */
switch(ECX) {
@ -1641,6 +1651,8 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
default:
BX_ERROR(("RDMSR: Unknown register %#x", ECX));
#if BX_IGNORE_BAD_MSR
RAX = 0;
RDX = 0;
return;
#endif
}
@ -1662,12 +1674,12 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
if (v8086_mode()) {
BX_INFO(("WRMSR: Invalid in virtual 8086 mode"));
goto do_exception;
}
}
if (CPL!= 0) {
BX_INFO(("WDMSR: CPL!= 0"));
BX_INFO(("WDMSR: CPL != 0"));
goto do_exception;
}
}
/* ECX has the MSR to write to */
switch(ECX) {
@ -1734,7 +1746,7 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
if ( (BX_CPU_THIS_PTR msr.lme != (EAX >> 8) & 1)
&& (BX_CPU_THIS_PTR cr0.pg == 1)) {
exception(BX_GP_EXCEPTION, 0, 0);
}
}
BX_CPU_THIS_PTR msr.sce = (EAX >> 0) & 1;
BX_CPU_THIS_PTR msr.lme = (EAX >> 8) & 1;
return;