X86: Centralize updates to the handy M5 reg.

This commit is contained in:
Gabe Black 2009-04-26 16:47:48 -07:00
parent 06b3e3c303
commit 4ee34dfb4e
4 changed files with 65 additions and 54 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -107,6 +107,8 @@ namespace X86ISA
{
protected:
MiscReg regVal[NumMiscRegs];
void updateHandyM5Reg(Efer efer, CR0 cr0,
SegAttr csAttr, RFLAGS rflags);
public:
void clear();

View file

@ -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);
}
}