summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/faults.cc10
-rw-r--r--src/arch/x86/miscregfile.cc71
-rw-r--r--src/arch/x86/miscregfile.hh2
-rw-r--r--src/arch/x86/process.cc36
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);
}
}