summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/faults.cc10
-rw-r--r--src/arch/x86/miscregfile.cc114
-rw-r--r--src/arch/x86/miscregfile.hh2
-rw-r--r--src/arch/x86/miscregs.hh7
-rw-r--r--src/arch/x86/predecoder.cc78
-rw-r--r--src/arch/x86/predecoder.hh5
-rw-r--r--src/arch/x86/process.cc36
-rw-r--r--src/arch/x86/tlb.cc745
-rw-r--r--src/arch/x86/tlb.hh2
9 files changed, 512 insertions, 487 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..317cdadc5 100644
--- a/src/arch/x86/miscregfile.cc
+++ b/src/arch/x86/miscregfile.cc
@@ -96,6 +96,64 @@ using namespace std;
class Checkpoint;
+void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0,
+ SegAttr csAttr, SegAttr ssAttr, 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;
+ m5reg.paging = cr0.pg;
+ m5reg.prot = cr0.pe;
+
+ // Compute the default and alternate operand size.
+ if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) {
+ m5reg.defOp = 2;
+ m5reg.altOp = 1;
+ } else {
+ m5reg.defOp = 1;
+ m5reg.altOp = 2;
+ }
+
+ // Compute the default and alternate address size.
+ if (m5reg.submode == SixtyFourBitMode) {
+ m5reg.defAddr = 3;
+ m5reg.altAddr = 2;
+ } else if (csAttr.defaultSize) {
+ m5reg.defAddr = 2;
+ m5reg.altAddr = 1;
+ } else {
+ m5reg.defAddr = 1;
+ m5reg.altAddr = 2;
+ }
+
+ // Compute the stack size
+ if (m5reg.submode == SixtyFourBitMode) {
+ m5reg.stack = 3;
+ } else if (ssAttr.defaultSize) {
+ m5reg.stack = 2;
+ } else {
+ m5reg.stack = 1;
+ }
+
+ regVal[MISCREG_M5_REG] = m5reg;
+}
+
void MiscRegFile::clear()
{
// Blank everything. 0 might not be an appropriate value for some things,
@@ -151,39 +209,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 +227,11 @@ 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_SS_ATTR],
+ regVal[MISCREG_RFLAGS]);
}
break;
case MISCREG_CR2:
@@ -214,28 +255,33 @@ 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_SS_ATTR],
+ regVal[MISCREG_RFLAGS]);
}
break;
+ case MISCREG_SS_ATTR:
+ updateHandyM5Reg(regVal[MISCREG_EFER],
+ regVal[MISCREG_CR0],
+ regVal[MISCREG_CS_ATTR],
+ val,
+ regVal[MISCREG_RFLAGS]);
+ break;
// These segments always actually use their bases, or in other words
// their effective bases must stay equal to their actual bases.
case MISCREG_FS_BASE:
@@ -333,6 +379,16 @@ 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_SS_ATTR],
+ regVal[MISCREG_RFLAGS]);
+ return;
default:
break;
}
diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh
index 6d3ae4e92..babc65b44 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, SegAttr ssAttr, RFLAGS rflags);
public:
void clear();
diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh
index af02e9422..088dbeace 100644
--- a/src/arch/x86/miscregs.hh
+++ b/src/arch/x86/miscregs.hh
@@ -518,6 +518,13 @@ namespace X86ISA
Bitfield<0> mode;
Bitfield<3, 1> submode;
Bitfield<5, 4> cpl;
+ Bitfield<6> paging;
+ Bitfield<7> prot;
+ Bitfield<9, 8> defOp;
+ Bitfield<11, 10> altOp;
+ Bitfield<13, 12> defAddr;
+ Bitfield<15, 14> altAddr;
+ Bitfield<17, 16> stack;
EndBitUnion(HandyM5Reg)
/**
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
index 620ab89ea..5bac8e711 100644
--- a/src/arch/x86/predecoder.cc
+++ b/src/arch/x86/predecoder.cc
@@ -80,9 +80,9 @@ namespace X86ISA
emi.modRM = 0;
emi.sib = 0;
- HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
- emi.mode.mode = m5reg.mode;
- emi.mode.submode = m5reg.submode;
+ m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+ emi.mode.mode = m5Reg.mode;
+ emi.mode.submode = m5Reg.submode;
}
void Predecoder::process()
@@ -216,34 +216,15 @@ namespace X86ISA
DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
emi.opcode.op = nextByte;
- SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
-
//Figure out the effective operand size. This can be overriden to
//a fixed value at the decoder level.
int logOpSize;
- if (emi.mode.submode == SixtyFourBitMode)
- {
- if(emi.rex.w)
- logOpSize = 3; // 64 bit operand size
- else if(emi.legacy.op)
- logOpSize = 1; // 16 bit operand size
- else
- logOpSize = 2; // 32 bit operand size
- }
- else if(csAttr.defaultSize)
- {
- if(emi.legacy.op)
- logOpSize = 1; // 16 bit operand size
- else
- logOpSize = 2; // 32 bit operand size
- }
- else // 16 bit default operand size
- {
- if(emi.legacy.op)
- logOpSize = 2; // 32 bit operand size
- else
- logOpSize = 1; // 16 bit operand size
- }
+ if (emi.rex.w)
+ logOpSize = 3; // 64 bit operand size
+ else if (emi.legacy.op)
+ logOpSize = m5Reg.altOp;
+ else
+ logOpSize = m5Reg.defOp;
//Set the actual op size
emi.opSize = 1 << logOpSize;
@@ -251,41 +232,18 @@ namespace X86ISA
//Figure out the effective address size. This can be overriden to
//a fixed value at the decoder level.
int logAddrSize;
- if(emi.mode.submode == SixtyFourBitMode)
- {
- if(emi.legacy.addr)
- logAddrSize = 2; // 32 bit address size
- else
- logAddrSize = 3; // 64 bit address size
- }
- else if(csAttr.defaultSize)
- {
- if(emi.legacy.addr)
- logAddrSize = 1; // 16 bit address size
- else
- logAddrSize = 2; // 32 bit address size
- }
- else // 16 bit default operand size
- {
- if(emi.legacy.addr)
- logAddrSize = 2; // 32 bit address size
- else
- logAddrSize = 1; // 16 bit address size
- }
-
- SegAttr ssAttr = tc->readMiscRegNoEffect(MISCREG_SS_ATTR);
- //Figure out the effective stack width. This can be overriden to
- //a fixed value at the decoder level.
- if(emi.mode.submode == SixtyFourBitMode)
- emi.stackSize = 8; // 64 bit stack width
- else if(ssAttr.defaultSize)
- emi.stackSize = 4; // 32 bit stack width
+ if(emi.legacy.addr)
+ logAddrSize = m5Reg.altAddr;
else
- emi.stackSize = 2; // 16 bit stack width
+ logAddrSize = m5Reg.defAddr;
//Set the actual address size
emi.addrSize = 1 << logAddrSize;
+ //Figure out the effective stack width. This can be overriden to
+ //a fixed value at the decoder level.
+ emi.stackSize = 1 << m5Reg.stack;
+
//Figure out how big of an immediate we'll retreive based
//on the opcode.
int immType = ImmediateType[emi.opcode.num - 1][nextByte];
@@ -318,9 +276,7 @@ namespace X86ISA
ModRM modRM;
modRM = nextByte;
DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
- SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
- if (emi.mode.submode != SixtyFourBitMode &&
- !csAttr.defaultSize) {
+ if (m5Reg.defOp == 1) {
//figure out 16 bit displacement size
if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
displacementSize = 2;
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index a16ce6fb8..4893f1de9 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -61,6 +61,7 @@
#include <cassert>
#include "arch/x86/types.hh"
+#include "arch/x86/miscregs.hh"
#include "base/bitfield.hh"
#include "base/misc.hh"
#include "base/trace.hh"
@@ -91,10 +92,11 @@ namespace X86ISA
int offset;
//The extended machine instruction being generated
ExtMachInst emi;
+ HandyM5Reg m5Reg;
inline uint8_t getNextByte()
{
- return (fetchChunk >> (offset * 8)) & 0xff;
+ return ((uint8_t *)&fetchChunk)[offset];
}
void getImmediate(int &collected, uint64_t &current, int size)
@@ -182,6 +184,7 @@ namespace X86ISA
{
emi.mode.mode = LongMode;
emi.mode.submode = SixtyFourBitMode;
+ m5Reg = 0;
}
void reset()
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);
}
}
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index f8b5c3392..1478c3e66 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -186,391 +186,393 @@ TLB::demapPage(Addr va, uint64_t asn)
}
Fault
+TLB::translateInt(RequestPtr req, ThreadContext *tc)
+{
+ DPRINTF(TLB, "Addresses references internal memory.\n");
+ Addr vaddr = req->getVaddr();
+ Addr prefix = (vaddr >> 3) & IntAddrPrefixMask;
+ if (prefix == IntAddrPrefixCPUID) {
+ panic("CPUID memory space not yet implemented!\n");
+ } else if (prefix == IntAddrPrefixMSR) {
+ vaddr = vaddr >> 3;
+ req->setMmapedIpr(true);
+ Addr regNum = 0;
+ switch (vaddr & ~IntAddrPrefixMask) {
+ case 0x10:
+ regNum = MISCREG_TSC;
+ break;
+ case 0x1B:
+ regNum = MISCREG_APIC_BASE;
+ break;
+ case 0xFE:
+ regNum = MISCREG_MTRRCAP;
+ break;
+ case 0x174:
+ regNum = MISCREG_SYSENTER_CS;
+ break;
+ case 0x175:
+ regNum = MISCREG_SYSENTER_ESP;
+ break;
+ case 0x176:
+ regNum = MISCREG_SYSENTER_EIP;
+ break;
+ case 0x179:
+ regNum = MISCREG_MCG_CAP;
+ break;
+ case 0x17A:
+ regNum = MISCREG_MCG_STATUS;
+ break;
+ case 0x17B:
+ regNum = MISCREG_MCG_CTL;
+ break;
+ case 0x1D9:
+ regNum = MISCREG_DEBUG_CTL_MSR;
+ break;
+ case 0x1DB:
+ regNum = MISCREG_LAST_BRANCH_FROM_IP;
+ break;
+ case 0x1DC:
+ regNum = MISCREG_LAST_BRANCH_TO_IP;
+ break;
+ case 0x1DD:
+ regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
+ break;
+ case 0x1DE:
+ regNum = MISCREG_LAST_EXCEPTION_TO_IP;
+ break;
+ case 0x200:
+ regNum = MISCREG_MTRR_PHYS_BASE_0;
+ break;
+ case 0x201:
+ regNum = MISCREG_MTRR_PHYS_MASK_0;
+ break;
+ case 0x202:
+ regNum = MISCREG_MTRR_PHYS_BASE_1;
+ break;
+ case 0x203:
+ regNum = MISCREG_MTRR_PHYS_MASK_1;
+ break;
+ case 0x204:
+ regNum = MISCREG_MTRR_PHYS_BASE_2;
+ break;
+ case 0x205:
+ regNum = MISCREG_MTRR_PHYS_MASK_2;
+ break;
+ case 0x206:
+ regNum = MISCREG_MTRR_PHYS_BASE_3;
+ break;
+ case 0x207:
+ regNum = MISCREG_MTRR_PHYS_MASK_3;
+ break;
+ case 0x208:
+ regNum = MISCREG_MTRR_PHYS_BASE_4;
+ break;
+ case 0x209:
+ regNum = MISCREG_MTRR_PHYS_MASK_4;
+ break;
+ case 0x20A:
+ regNum = MISCREG_MTRR_PHYS_BASE_5;
+ break;
+ case 0x20B:
+ regNum = MISCREG_MTRR_PHYS_MASK_5;
+ break;
+ case 0x20C:
+ regNum = MISCREG_MTRR_PHYS_BASE_6;
+ break;
+ case 0x20D:
+ regNum = MISCREG_MTRR_PHYS_MASK_6;
+ break;
+ case 0x20E:
+ regNum = MISCREG_MTRR_PHYS_BASE_7;
+ break;
+ case 0x20F:
+ regNum = MISCREG_MTRR_PHYS_MASK_7;
+ break;
+ case 0x250:
+ regNum = MISCREG_MTRR_FIX_64K_00000;
+ break;
+ case 0x258:
+ regNum = MISCREG_MTRR_FIX_16K_80000;
+ break;
+ case 0x259:
+ regNum = MISCREG_MTRR_FIX_16K_A0000;
+ break;
+ case 0x268:
+ regNum = MISCREG_MTRR_FIX_4K_C0000;
+ break;
+ case 0x269:
+ regNum = MISCREG_MTRR_FIX_4K_C8000;
+ break;
+ case 0x26A:
+ regNum = MISCREG_MTRR_FIX_4K_D0000;
+ break;
+ case 0x26B:
+ regNum = MISCREG_MTRR_FIX_4K_D8000;
+ break;
+ case 0x26C:
+ regNum = MISCREG_MTRR_FIX_4K_E0000;
+ break;
+ case 0x26D:
+ regNum = MISCREG_MTRR_FIX_4K_E8000;
+ break;
+ case 0x26E:
+ regNum = MISCREG_MTRR_FIX_4K_F0000;
+ break;
+ case 0x26F:
+ regNum = MISCREG_MTRR_FIX_4K_F8000;
+ break;
+ case 0x277:
+ regNum = MISCREG_PAT;
+ break;
+ case 0x2FF:
+ regNum = MISCREG_DEF_TYPE;
+ break;
+ case 0x400:
+ regNum = MISCREG_MC0_CTL;
+ break;
+ case 0x404:
+ regNum = MISCREG_MC1_CTL;
+ break;
+ case 0x408:
+ regNum = MISCREG_MC2_CTL;
+ break;
+ case 0x40C:
+ regNum = MISCREG_MC3_CTL;
+ break;
+ case 0x410:
+ regNum = MISCREG_MC4_CTL;
+ break;
+ case 0x414:
+ regNum = MISCREG_MC5_CTL;
+ break;
+ case 0x418:
+ regNum = MISCREG_MC6_CTL;
+ break;
+ case 0x41C:
+ regNum = MISCREG_MC7_CTL;
+ break;
+ case 0x401:
+ regNum = MISCREG_MC0_STATUS;
+ break;
+ case 0x405:
+ regNum = MISCREG_MC1_STATUS;
+ break;
+ case 0x409:
+ regNum = MISCREG_MC2_STATUS;
+ break;
+ case 0x40D:
+ regNum = MISCREG_MC3_STATUS;
+ break;
+ case 0x411:
+ regNum = MISCREG_MC4_STATUS;
+ break;
+ case 0x415:
+ regNum = MISCREG_MC5_STATUS;
+ break;
+ case 0x419:
+ regNum = MISCREG_MC6_STATUS;
+ break;
+ case 0x41D:
+ regNum = MISCREG_MC7_STATUS;
+ break;
+ case 0x402:
+ regNum = MISCREG_MC0_ADDR;
+ break;
+ case 0x406:
+ regNum = MISCREG_MC1_ADDR;
+ break;
+ case 0x40A:
+ regNum = MISCREG_MC2_ADDR;
+ break;
+ case 0x40E:
+ regNum = MISCREG_MC3_ADDR;
+ break;
+ case 0x412:
+ regNum = MISCREG_MC4_ADDR;
+ break;
+ case 0x416:
+ regNum = MISCREG_MC5_ADDR;
+ break;
+ case 0x41A:
+ regNum = MISCREG_MC6_ADDR;
+ break;
+ case 0x41E:
+ regNum = MISCREG_MC7_ADDR;
+ break;
+ case 0x403:
+ regNum = MISCREG_MC0_MISC;
+ break;
+ case 0x407:
+ regNum = MISCREG_MC1_MISC;
+ break;
+ case 0x40B:
+ regNum = MISCREG_MC2_MISC;
+ break;
+ case 0x40F:
+ regNum = MISCREG_MC3_MISC;
+ break;
+ case 0x413:
+ regNum = MISCREG_MC4_MISC;
+ break;
+ case 0x417:
+ regNum = MISCREG_MC5_MISC;
+ break;
+ case 0x41B:
+ regNum = MISCREG_MC6_MISC;
+ break;
+ case 0x41F:
+ regNum = MISCREG_MC7_MISC;
+ break;
+ case 0xC0000080:
+ regNum = MISCREG_EFER;
+ break;
+ case 0xC0000081:
+ regNum = MISCREG_STAR;
+ break;
+ case 0xC0000082:
+ regNum = MISCREG_LSTAR;
+ break;
+ case 0xC0000083:
+ regNum = MISCREG_CSTAR;
+ break;
+ case 0xC0000084:
+ regNum = MISCREG_SF_MASK;
+ break;
+ case 0xC0000100:
+ regNum = MISCREG_FS_BASE;
+ break;
+ case 0xC0000101:
+ regNum = MISCREG_GS_BASE;
+ break;
+ case 0xC0000102:
+ regNum = MISCREG_KERNEL_GS_BASE;
+ break;
+ case 0xC0000103:
+ regNum = MISCREG_TSC_AUX;
+ break;
+ case 0xC0010000:
+ regNum = MISCREG_PERF_EVT_SEL0;
+ break;
+ case 0xC0010001:
+ regNum = MISCREG_PERF_EVT_SEL1;
+ break;
+ case 0xC0010002:
+ regNum = MISCREG_PERF_EVT_SEL2;
+ break;
+ case 0xC0010003:
+ regNum = MISCREG_PERF_EVT_SEL3;
+ break;
+ case 0xC0010004:
+ regNum = MISCREG_PERF_EVT_CTR0;
+ break;
+ case 0xC0010005:
+ regNum = MISCREG_PERF_EVT_CTR1;
+ break;
+ case 0xC0010006:
+ regNum = MISCREG_PERF_EVT_CTR2;
+ break;
+ case 0xC0010007:
+ regNum = MISCREG_PERF_EVT_CTR3;
+ break;
+ case 0xC0010010:
+ regNum = MISCREG_SYSCFG;
+ break;
+ case 0xC0010016:
+ regNum = MISCREG_IORR_BASE0;
+ break;
+ case 0xC0010017:
+ regNum = MISCREG_IORR_BASE1;
+ break;
+ case 0xC0010018:
+ regNum = MISCREG_IORR_MASK0;
+ break;
+ case 0xC0010019:
+ regNum = MISCREG_IORR_MASK1;
+ break;
+ case 0xC001001A:
+ regNum = MISCREG_TOP_MEM;
+ break;
+ case 0xC001001D:
+ regNum = MISCREG_TOP_MEM2;
+ break;
+ case 0xC0010114:
+ regNum = MISCREG_VM_CR;
+ break;
+ case 0xC0010115:
+ regNum = MISCREG_IGNNE;
+ break;
+ case 0xC0010116:
+ regNum = MISCREG_SMM_CTL;
+ break;
+ case 0xC0010117:
+ regNum = MISCREG_VM_HSAVE_PA;
+ break;
+ default:
+ return new GeneralProtection(0);
+ }
+ //The index is multiplied by the size of a MiscReg so that
+ //any memory dependence calculations will not see these as
+ //overlapping.
+ req->setPaddr(regNum * sizeof(MiscReg));
+ return NoFault;
+ } else if (prefix == IntAddrPrefixIO) {
+ // TODO If CPL > IOPL or in virtual mode, check the I/O permission
+ // bitmap in the TSS.
+
+ Addr IOPort = vaddr & ~IntAddrPrefixMask;
+ // Make sure the address fits in the expected 16 bit IO address
+ // space.
+ assert(!(IOPort & ~0xFFFF));
+ if (IOPort == 0xCF8 && req->getSize() == 4) {
+ req->setMmapedIpr(true);
+ req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg));
+ } else if ((IOPort & ~mask(2)) == 0xCFC) {
+ Addr configAddress =
+ tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
+ if (bits(configAddress, 31, 31)) {
+ req->setPaddr(PhysAddrPrefixPciConfig |
+ mbits(configAddress, 30, 2) |
+ (IOPort & mask(2)));
+ }
+ } else {
+ req->setPaddr(PhysAddrPrefixIO | IOPort);
+ }
+ return NoFault;
+ } else {
+ panic("Access to unrecognized internal address space %#x.\n",
+ prefix);
+ }
+}
+
+Fault
TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
Mode mode, bool &delayedResponse, bool timing)
{
- delayedResponse = false;
- Addr vaddr = req->getVaddr();
- DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
uint32_t flags = req->getFlags();
- bool storeCheck = flags & (StoreCheck << FlagShift);
-
int seg = flags & SegmentFlagMask;
+ bool storeCheck = flags & (StoreCheck << FlagShift);
- // If this is true, we're dealing with a request to read an internal
- // value.
+ // If this is true, we're dealing with a request to a non-memory address
+ // space.
if (seg == SEGMENT_REG_MS) {
- DPRINTF(TLB, "Addresses references internal memory.\n");
- Addr prefix = (vaddr >> 3) & IntAddrPrefixMask;
- if (prefix == IntAddrPrefixCPUID) {
- panic("CPUID memory space not yet implemented!\n");
- } else if (prefix == IntAddrPrefixMSR) {
- vaddr = vaddr >> 3;
- req->setMmapedIpr(true);
- Addr regNum = 0;
- switch (vaddr & ~IntAddrPrefixMask) {
- case 0x10:
- regNum = MISCREG_TSC;
- break;
- case 0x1B:
- regNum = MISCREG_APIC_BASE;
- break;
- case 0xFE:
- regNum = MISCREG_MTRRCAP;
- break;
- case 0x174:
- regNum = MISCREG_SYSENTER_CS;
- break;
- case 0x175:
- regNum = MISCREG_SYSENTER_ESP;
- break;
- case 0x176:
- regNum = MISCREG_SYSENTER_EIP;
- break;
- case 0x179:
- regNum = MISCREG_MCG_CAP;
- break;
- case 0x17A:
- regNum = MISCREG_MCG_STATUS;
- break;
- case 0x17B:
- regNum = MISCREG_MCG_CTL;
- break;
- case 0x1D9:
- regNum = MISCREG_DEBUG_CTL_MSR;
- break;
- case 0x1DB:
- regNum = MISCREG_LAST_BRANCH_FROM_IP;
- break;
- case 0x1DC:
- regNum = MISCREG_LAST_BRANCH_TO_IP;
- break;
- case 0x1DD:
- regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
- break;
- case 0x1DE:
- regNum = MISCREG_LAST_EXCEPTION_TO_IP;
- break;
- case 0x200:
- regNum = MISCREG_MTRR_PHYS_BASE_0;
- break;
- case 0x201:
- regNum = MISCREG_MTRR_PHYS_MASK_0;
- break;
- case 0x202:
- regNum = MISCREG_MTRR_PHYS_BASE_1;
- break;
- case 0x203:
- regNum = MISCREG_MTRR_PHYS_MASK_1;
- break;
- case 0x204:
- regNum = MISCREG_MTRR_PHYS_BASE_2;
- break;
- case 0x205:
- regNum = MISCREG_MTRR_PHYS_MASK_2;
- break;
- case 0x206:
- regNum = MISCREG_MTRR_PHYS_BASE_3;
- break;
- case 0x207:
- regNum = MISCREG_MTRR_PHYS_MASK_3;
- break;
- case 0x208:
- regNum = MISCREG_MTRR_PHYS_BASE_4;
- break;
- case 0x209:
- regNum = MISCREG_MTRR_PHYS_MASK_4;
- break;
- case 0x20A:
- regNum = MISCREG_MTRR_PHYS_BASE_5;
- break;
- case 0x20B:
- regNum = MISCREG_MTRR_PHYS_MASK_5;
- break;
- case 0x20C:
- regNum = MISCREG_MTRR_PHYS_BASE_6;
- break;
- case 0x20D:
- regNum = MISCREG_MTRR_PHYS_MASK_6;
- break;
- case 0x20E:
- regNum = MISCREG_MTRR_PHYS_BASE_7;
- break;
- case 0x20F:
- regNum = MISCREG_MTRR_PHYS_MASK_7;
- break;
- case 0x250:
- regNum = MISCREG_MTRR_FIX_64K_00000;
- break;
- case 0x258:
- regNum = MISCREG_MTRR_FIX_16K_80000;
- break;
- case 0x259:
- regNum = MISCREG_MTRR_FIX_16K_A0000;
- break;
- case 0x268:
- regNum = MISCREG_MTRR_FIX_4K_C0000;
- break;
- case 0x269:
- regNum = MISCREG_MTRR_FIX_4K_C8000;
- break;
- case 0x26A:
- regNum = MISCREG_MTRR_FIX_4K_D0000;
- break;
- case 0x26B:
- regNum = MISCREG_MTRR_FIX_4K_D8000;
- break;
- case 0x26C:
- regNum = MISCREG_MTRR_FIX_4K_E0000;
- break;
- case 0x26D:
- regNum = MISCREG_MTRR_FIX_4K_E8000;
- break;
- case 0x26E:
- regNum = MISCREG_MTRR_FIX_4K_F0000;
- break;
- case 0x26F:
- regNum = MISCREG_MTRR_FIX_4K_F8000;
- break;
- case 0x277:
- regNum = MISCREG_PAT;
- break;
- case 0x2FF:
- regNum = MISCREG_DEF_TYPE;
- break;
- case 0x400:
- regNum = MISCREG_MC0_CTL;
- break;
- case 0x404:
- regNum = MISCREG_MC1_CTL;
- break;
- case 0x408:
- regNum = MISCREG_MC2_CTL;
- break;
- case 0x40C:
- regNum = MISCREG_MC3_CTL;
- break;
- case 0x410:
- regNum = MISCREG_MC4_CTL;
- break;
- case 0x414:
- regNum = MISCREG_MC5_CTL;
- break;
- case 0x418:
- regNum = MISCREG_MC6_CTL;
- break;
- case 0x41C:
- regNum = MISCREG_MC7_CTL;
- break;
- case 0x401:
- regNum = MISCREG_MC0_STATUS;
- break;
- case 0x405:
- regNum = MISCREG_MC1_STATUS;
- break;
- case 0x409:
- regNum = MISCREG_MC2_STATUS;
- break;
- case 0x40D:
- regNum = MISCREG_MC3_STATUS;
- break;
- case 0x411:
- regNum = MISCREG_MC4_STATUS;
- break;
- case 0x415:
- regNum = MISCREG_MC5_STATUS;
- break;
- case 0x419:
- regNum = MISCREG_MC6_STATUS;
- break;
- case 0x41D:
- regNum = MISCREG_MC7_STATUS;
- break;
- case 0x402:
- regNum = MISCREG_MC0_ADDR;
- break;
- case 0x406:
- regNum = MISCREG_MC1_ADDR;
- break;
- case 0x40A:
- regNum = MISCREG_MC2_ADDR;
- break;
- case 0x40E:
- regNum = MISCREG_MC3_ADDR;
- break;
- case 0x412:
- regNum = MISCREG_MC4_ADDR;
- break;
- case 0x416:
- regNum = MISCREG_MC5_ADDR;
- break;
- case 0x41A:
- regNum = MISCREG_MC6_ADDR;
- break;
- case 0x41E:
- regNum = MISCREG_MC7_ADDR;
- break;
- case 0x403:
- regNum = MISCREG_MC0_MISC;
- break;
- case 0x407:
- regNum = MISCREG_MC1_MISC;
- break;
- case 0x40B:
- regNum = MISCREG_MC2_MISC;
- break;
- case 0x40F:
- regNum = MISCREG_MC3_MISC;
- break;
- case 0x413:
- regNum = MISCREG_MC4_MISC;
- break;
- case 0x417:
- regNum = MISCREG_MC5_MISC;
- break;
- case 0x41B:
- regNum = MISCREG_MC6_MISC;
- break;
- case 0x41F:
- regNum = MISCREG_MC7_MISC;
- break;
- case 0xC0000080:
- regNum = MISCREG_EFER;
- break;
- case 0xC0000081:
- regNum = MISCREG_STAR;
- break;
- case 0xC0000082:
- regNum = MISCREG_LSTAR;
- break;
- case 0xC0000083:
- regNum = MISCREG_CSTAR;
- break;
- case 0xC0000084:
- regNum = MISCREG_SF_MASK;
- break;
- case 0xC0000100:
- regNum = MISCREG_FS_BASE;
- break;
- case 0xC0000101:
- regNum = MISCREG_GS_BASE;
- break;
- case 0xC0000102:
- regNum = MISCREG_KERNEL_GS_BASE;
- break;
- case 0xC0000103:
- regNum = MISCREG_TSC_AUX;
- break;
- case 0xC0010000:
- regNum = MISCREG_PERF_EVT_SEL0;
- break;
- case 0xC0010001:
- regNum = MISCREG_PERF_EVT_SEL1;
- break;
- case 0xC0010002:
- regNum = MISCREG_PERF_EVT_SEL2;
- break;
- case 0xC0010003:
- regNum = MISCREG_PERF_EVT_SEL3;
- break;
- case 0xC0010004:
- regNum = MISCREG_PERF_EVT_CTR0;
- break;
- case 0xC0010005:
- regNum = MISCREG_PERF_EVT_CTR1;
- break;
- case 0xC0010006:
- regNum = MISCREG_PERF_EVT_CTR2;
- break;
- case 0xC0010007:
- regNum = MISCREG_PERF_EVT_CTR3;
- break;
- case 0xC0010010:
- regNum = MISCREG_SYSCFG;
- break;
- case 0xC0010016:
- regNum = MISCREG_IORR_BASE0;
- break;
- case 0xC0010017:
- regNum = MISCREG_IORR_BASE1;
- break;
- case 0xC0010018:
- regNum = MISCREG_IORR_MASK0;
- break;
- case 0xC0010019:
- regNum = MISCREG_IORR_MASK1;
- break;
- case 0xC001001A:
- regNum = MISCREG_TOP_MEM;
- break;
- case 0xC001001D:
- regNum = MISCREG_TOP_MEM2;
- break;
- case 0xC0010114:
- regNum = MISCREG_VM_CR;
- break;
- case 0xC0010115:
- regNum = MISCREG_IGNNE;
- break;
- case 0xC0010116:
- regNum = MISCREG_SMM_CTL;
- break;
- case 0xC0010117:
- regNum = MISCREG_VM_HSAVE_PA;
- break;
- default:
- return new GeneralProtection(0);
- }
- //The index is multiplied by the size of a MiscReg so that
- //any memory dependence calculations will not see these as
- //overlapping.
- req->setPaddr(regNum * sizeof(MiscReg));
- return NoFault;
- } else if (prefix == IntAddrPrefixIO) {
- // TODO If CPL > IOPL or in virtual mode, check the I/O permission
- // bitmap in the TSS.
-
- Addr IOPort = vaddr & ~IntAddrPrefixMask;
- // Make sure the address fits in the expected 16 bit IO address
- // space.
- assert(!(IOPort & ~0xFFFF));
- if (IOPort == 0xCF8 && req->getSize() == 4) {
- req->setMmapedIpr(true);
- req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg));
- } else if ((IOPort & ~mask(2)) == 0xCFC) {
- Addr configAddress =
- tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
- if (bits(configAddress, 31, 31)) {
- req->setPaddr(PhysAddrPrefixPciConfig |
- mbits(configAddress, 30, 2) |
- (IOPort & mask(2)));
- }
- } else {
- req->setPaddr(PhysAddrPrefixIO | IOPort);
- }
- return NoFault;
- } else {
- panic("Access to unrecognized internal address space %#x.\n",
- prefix);
- }
+ return translateInt(req, tc);
}
- // Get cr0. This will tell us how to do translation. We'll assume it was
- // verified to be correct and consistent when set.
- CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
+ delayedResponse = false;
+ Addr vaddr = req->getVaddr();
+ DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
+
+ HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
// If protected mode has been enabled...
- if (cr0.pe) {
+ if (m5Reg.prot) {
DPRINTF(TLB, "In protected mode.\n");
- Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
- SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
// If we're not in 64-bit mode, do protection/limit checks
- if (!efer.lma || !csAttr.longMode) {
+ if (m5Reg.mode != LongMode) {
DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
// Check for a NULL segment selector.
if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR ||
- seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS ||
- seg == SEGMENT_REG_MS)
+ seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS)
&& !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
return new GeneralProtection(0);
bool expandDown = false;
@@ -589,6 +591,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
// address size is 64 bits, overridable to 32.
int size = 32;
bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift));
+ SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
if ((csAttr.defaultSize && sizeOverride) ||
(!csAttr.defaultSize && !sizeOverride))
size = 16;
@@ -605,7 +608,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
}
}
// If paging is enabled, do the translation.
- if (cr0.pg) {
+ if (m5Reg.paging) {
DPRINTF(TLB, "Paging enabled.\n");
// The vaddr already has the segment base applied.
TlbEntry *entry = lookup(vaddr);
@@ -643,7 +646,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
#endif
}
// Do paging protection checks.
- bool inUser = (csAttr.dpl == 3 &&
+ bool inUser = (m5Reg.cpl == 3 &&
!(flags & (CPL0FlagBit << FlagShift)));
if ((inUser && !entry->user) ||
(mode == Write && !entry->writable)) {
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
index f55c26435..dca95eaaf 100644
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -124,6 +124,8 @@ namespace X86ISA
EntryList freeList;
EntryList entryList;
+ Fault translateInt(RequestPtr req, ThreadContext *tc);
+
Fault translate(RequestPtr req, ThreadContext *tc,
Translation *translation, Mode mode,
bool &delayedResponse, bool timing);