diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/x86/faults.cc | 10 | ||||
-rw-r--r-- | src/arch/x86/miscregfile.cc | 71 | ||||
-rw-r--r-- | src/arch/x86/miscregfile.hh | 2 | ||||
-rw-r--r-- | src/arch/x86/process.cc | 36 |
4 files changed, 65 insertions, 54 deletions
diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index bef7e4414..10b539248 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -271,12 +271,8 @@ namespace X86ISA tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL); tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL); - // We're now in real mode, effectively at CPL 0 - HandyM5Reg m5Reg = 0; - m5Reg.mode = LegacyMode; - m5Reg.submode = RealMode; - m5Reg.cpl = 0; - tc->setMiscReg(MISCREG_M5_REG, m5Reg); + // Update the handy M5 Reg. + tc->setMiscReg(MISCREG_M5_REG, 0); MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt; tc->setMicroPC(romMicroPC(entry)); tc->setNextMicroPC(romMicroPC(entry) + 1); @@ -289,7 +285,7 @@ namespace X86ISA HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG); if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) { panic("Startup IPI recived outside of real mode. " - "Don't know what to do."); + "Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode); } tc->setMiscReg(MISCREG_CS, vector << 8); diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 0316603e5..b3ce7076e 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -96,6 +96,31 @@ using namespace std; class Checkpoint; +void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0, + SegAttr csAttr, RFLAGS rflags) +{ + HandyM5Reg m5reg; + if (efer.lma) { + m5reg.mode = LongMode; + if (csAttr.longMode) + m5reg.submode = SixtyFourBitMode; + else + m5reg.submode = CompatabilityMode; + } else { + m5reg.mode = LegacyMode; + if (cr0.pe) { + if (rflags.vm) + m5reg.submode = Virtual8086Mode; + else + m5reg.submode = ProtectedMode; + } else { + m5reg.submode = RealMode; + } + } + m5reg.cpl = csAttr.dpl; + regVal[MISCREG_M5_REG] = m5reg; +} + void MiscRegFile::clear() { // Blank everything. 0 might not be an appropriate value for some things, @@ -151,39 +176,17 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, CR0 toggled = regVal[miscReg] ^ val; CR0 newCR0 = val; Efer efer = regVal[MISCREG_EFER]; - HandyM5Reg m5reg = regVal[MISCREG_M5_REG]; if (toggled.pg && efer.lme) { if (newCR0.pg) { //Turning on long mode efer.lma = 1; - m5reg.mode = LongMode; regVal[MISCREG_EFER] = efer; } else { //Turning off long mode efer.lma = 0; - m5reg.mode = LegacyMode; regVal[MISCREG_EFER] = efer; } } - // Figure out what submode we're in. - if (m5reg.mode == LongMode) { - SegAttr csAttr = regVal[MISCREG_CS_ATTR]; - if (csAttr.longMode) - m5reg.submode = SixtyFourBitMode; - else - m5reg.submode = CompatabilityMode; - } else { - if (newCR0.pe) { - RFLAGS rflags = regVal[MISCREG_RFLAGS]; - if (rflags.vm) - m5reg.submode = Virtual8086Mode; - else - m5reg.submode = ProtectedMode; - } else { - m5reg.submode = RealMode; - } - } - regVal[MISCREG_M5_REG] = m5reg; if (toggled.pg) { tc->getITBPtr()->invalidateAll(); tc->getDTBPtr()->invalidateAll(); @@ -191,6 +194,10 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, //This must always be 1. newCR0.et = 1; newVal = newCR0; + updateHandyM5Reg(regVal[MISCREG_EFER], + newCR0, + regVal[MISCREG_CS_ATTR], + regVal[MISCREG_RFLAGS]); } break; case MISCREG_CR2: @@ -214,26 +221,23 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, { SegAttr toggled = regVal[miscReg] ^ val; SegAttr newCSAttr = val; - HandyM5Reg m5reg = regVal[MISCREG_M5_REG]; if (toggled.longMode) { if (newCSAttr.longMode) { - if (m5reg.mode == LongMode) - m5reg.submode = SixtyFourBitMode; regVal[MISCREG_ES_EFF_BASE] = 0; regVal[MISCREG_CS_EFF_BASE] = 0; regVal[MISCREG_SS_EFF_BASE] = 0; regVal[MISCREG_DS_EFF_BASE] = 0; } else { - if (m5reg.mode == LongMode) - m5reg.submode = CompatabilityMode; regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE]; regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE]; regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE]; regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE]; } } - m5reg.cpl = newCSAttr.dpl; - regVal[MISCREG_M5_REG] = m5reg; + updateHandyM5Reg(regVal[MISCREG_EFER], + regVal[MISCREG_CR0], + newCSAttr, + regVal[MISCREG_RFLAGS]); } break; // These segments always actually use their bases, or in other words @@ -333,6 +337,15 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, dr7.len3 = newDR7.len3; } break; + case MISCREG_M5_REG: + // Writing anything to the m5reg with side effects makes it update + // based on the current values of the relevant registers. The actual + // value written is discarded. + updateHandyM5Reg(regVal[MISCREG_EFER], + regVal[MISCREG_CR0], + regVal[MISCREG_CS_ATTR], + regVal[MISCREG_RFLAGS]); + return; default: break; } diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index 6d3ae4e92..0488dbba7 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -107,6 +107,8 @@ namespace X86ISA { protected: MiscReg regVal[NumMiscRegs]; + void updateHandyM5Reg(Efer efer, CR0 cr0, + SegAttr csAttr, RFLAGS rflags); public: void clear(); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 43dd4a591..f7b5468b4 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -232,6 +232,15 @@ X86_64LiveProcess::startup() tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr); + Efer efer = 0; + efer.sce = 1; // Enable system call extensions. + efer.lme = 1; // Enable long mode. + efer.lma = 1; // Activate long mode. + efer.nxe = 1; // Enable nx support. + efer.svme = 0; // Disable svm support for now. It isn't implemented. + efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. + tc->setMiscReg(MISCREG_EFER, efer); + //Set up the registers that describe the operating mode. CR0 cr0 = 0; cr0.pg = 1; // Turn on paging. @@ -248,15 +257,6 @@ X86_64LiveProcess::startup() // setting it to one. cr0.pe = 1; // We're definitely in protected mode. tc->setMiscReg(MISCREG_CR0, cr0); - - Efer efer = 0; - efer.sce = 1; // Enable system call extensions. - efer.lme = 1; // Enable long mode. - efer.lma = 1; // Activate long mode. - efer.nxe = 1; // Enable nx support. - efer.svme = 0; // Disable svm support for now. It isn't implemented. - efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. - tc->setMiscReg(MISCREG_EFER, efer); } } @@ -340,6 +340,15 @@ I386LiveProcess::startup() // Set the LDT selector to 0 to deactivate it. tc->setMiscRegNoEffect(MISCREG_TSL, 0); + Efer efer = 0; + efer.sce = 1; // Enable system call extensions. + efer.lme = 1; // Enable long mode. + efer.lma = 0; // Deactivate long mode. + efer.nxe = 1; // Enable nx support. + efer.svme = 0; // Disable svm support for now. It isn't implemented. + efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. + tc->setMiscReg(MISCREG_EFER, efer); + //Set up the registers that describe the operating mode. CR0 cr0 = 0; cr0.pg = 1; // Turn on paging. @@ -356,15 +365,6 @@ I386LiveProcess::startup() // setting it to one. cr0.pe = 1; // We're definitely in protected mode. tc->setMiscReg(MISCREG_CR0, cr0); - - Efer efer = 0; - efer.sce = 1; // Enable system call extensions. - efer.lme = 1; // Enable long mode. - efer.lma = 0; // Deactivate long mode. - efer.nxe = 1; // Enable nx support. - efer.svme = 0; // Disable svm support for now. It isn't implemented. - efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. - tc->setMiscReg(MISCREG_EFER, efer); } } |