From 4ee34dfb4e3b0441427cbd978deb0d1d32cf19bc Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 26 Apr 2009 16:47:48 -0700 Subject: X86: Centralize updates to the handy M5 reg. --- src/arch/x86/faults.cc | 10 ++----- src/arch/x86/miscregfile.cc | 71 +++++++++++++++++++++++++++------------------ src/arch/x86/miscregfile.hh | 2 ++ 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); } } -- cgit v1.2.3 From b6bfe8af26203247d9cab2a0ce369998946a8c91 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 26 Apr 2009 16:48:44 -0700 Subject: X86: Split out the internal memory space from the regular translate() and precompute mode. --- src/arch/x86/miscregfile.cc | 2 + src/arch/x86/miscregs.hh | 2 + src/arch/x86/tlb.cc | 745 ++++++++++++++++++++++---------------------- src/arch/x86/tlb.hh | 2 + 4 files changed, 380 insertions(+), 371 deletions(-) diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index b3ce7076e..f7c804fd0 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -118,6 +118,8 @@ void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0, } } m5reg.cpl = csAttr.dpl; + m5reg.paging = cr0.pg; + m5reg.prot = cr0.pe; regVal[MISCREG_M5_REG] = m5reg; } diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index af02e9422..7d46a87b9 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -518,6 +518,8 @@ namespace X86ISA Bitfield<0> mode; Bitfield<3, 1> submode; Bitfield<5, 4> cpl; + Bitfield<6> paging; + Bitfield<7> prot; EndBitUnion(HandyM5Reg) /** 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 @@ -185,392 +185,394 @@ 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); -- cgit v1.2.3 From 7146eb79f179510c980fd7681d1e45adf212c2b0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 26 Apr 2009 16:49:24 -0700 Subject: X86: Precompute the default and alternate address and operand size and the stack size. --- src/arch/x86/miscregfile.cc | 43 ++++++++++++++++++++++++- src/arch/x86/miscregfile.hh | 2 +- src/arch/x86/miscregs.hh | 5 +++ src/arch/x86/predecoder.cc | 78 ++++++++++----------------------------------- src/arch/x86/predecoder.hh | 5 ++- 5 files changed, 69 insertions(+), 64 deletions(-) diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index f7c804fd0..317cdadc5 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -97,7 +97,7 @@ using namespace std; class Checkpoint; void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0, - SegAttr csAttr, RFLAGS rflags) + SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags) { HandyM5Reg m5reg; if (efer.lma) { @@ -120,6 +120,37 @@ void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0, 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; } @@ -199,6 +230,7 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, updateHandyM5Reg(regVal[MISCREG_EFER], newCR0, regVal[MISCREG_CS_ATTR], + regVal[MISCREG_SS_ATTR], regVal[MISCREG_RFLAGS]); } break; @@ -239,9 +271,17 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, 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: @@ -346,6 +386,7 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, updateHandyM5Reg(regVal[MISCREG_EFER], regVal[MISCREG_CR0], regVal[MISCREG_CS_ATTR], + regVal[MISCREG_SS_ATTR], regVal[MISCREG_RFLAGS]); return; default: diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index 0488dbba7..babc65b44 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -108,7 +108,7 @@ namespace X86ISA protected: MiscReg regVal[NumMiscRegs]; void updateHandyM5Reg(Efer efer, CR0 cr0, - SegAttr csAttr, RFLAGS rflags); + SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags); public: void clear(); diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index 7d46a87b9..088dbeace 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -520,6 +520,11 @@ namespace X86ISA 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 #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 ¤t, int size) @@ -182,6 +184,7 @@ namespace X86ISA { emi.mode.mode = LongMode; emi.mode.submode = SixtyFourBitMode; + m5Reg = 0; } void reset() -- cgit v1.2.3 From dc35d2f125de43fb2b2865e9211cccca8546b8cd Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 4 May 2009 16:58:24 -0700 Subject: scons: re-work the *Source functions to take more information. Start by turning all of the *Source functions into classes so we can do more calculations and more easily collect the data we need. Add parameters to the new classes for indicating what sorts of flags the objects should be compiled with so we can allow certain files to be compiled without Werror for example. --- SConstruct | 2 +- src/SConscript | 361 ++++++++++++++++++++++++++++------------------------- src/sim/SConscript | 2 +- 3 files changed, 192 insertions(+), 173 deletions(-) diff --git a/SConstruct b/SConstruct index bfd93f26f..7a0bf2794 100644 --- a/SConstruct +++ b/SConstruct @@ -394,7 +394,7 @@ if main['GCC'] + main['SUNCC'] + main['ICC'] > 1: if main['GCC']: main.Append(CCFLAGS='-pipe') main.Append(CCFLAGS='-fno-strict-aliasing') - main.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef')) + main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef']) main.Append(CXXFLAGS='-Wno-deprecated') elif main['ICC']: pass #Fix me... add warning flags once we clean up icc warnings diff --git a/src/SConscript b/src/SConscript index 20d454f03..d36f5f244 100644 --- a/src/SConscript +++ b/src/SConscript @@ -29,6 +29,7 @@ # Authors: Nathan Binkert import array +import bisect import imp import marshal import os @@ -50,122 +51,144 @@ Export('env') build_env = dict([(opt, env[opt]) for opt in export_vars]) -def sort_list(_list): - """return a sorted copy of '_list'""" - if isinstance(_list, list): - _list = _list[:] - else: - _list = list(_list) - _list.sort() - return _list +######################################################################## +# Code for adding source files of various types +# +class SourceMeta(type): + def __init__(cls, name, bases, dict): + super(SourceMeta, cls).__init__(name, bases, dict) + cls.all = [] + + def get(cls, **kwargs): + for src in cls.all: + for attr,value in kwargs.iteritems(): + if getattr(src, attr) != value: + break + else: + yield src + +class SourceFile(object): + __metaclass__ = SourceMeta + def __init__(self, source): + tnode = source + if not isinstance(source, SCons.Node.FS.File): + tnode = File(source) -class PySourceFile(object): + self.tnode = tnode + self.snode = tnode.srcnode() + self.filename = str(tnode) + self.dirname = dirname(self.filename) + self.basename = basename(self.filename) + index = self.basename.rfind('.') + if index <= 0: + # dot files aren't extensions + self.extname = self.basename, None + else: + self.extname = self.basename[:index], self.basename[index+1:] + + for base in type(self).__mro__: + if issubclass(base, SourceFile): + bisect.insort_right(base.all, self) + + def __lt__(self, other): return self.filename < other.filename + def __le__(self, other): return self.filename <= other.filename + def __gt__(self, other): return self.filename > other.filename + def __ge__(self, other): return self.filename >= other.filename + def __eq__(self, other): return self.filename == other.filename + def __ne__(self, other): return self.filename != other.filename + +class Source(SourceFile): + '''Add a c/c++ source file to the build''' + def __init__(self, source, Werror=True, swig=False, bin_only=False, + skip_lib=False): + super(Source, self).__init__(source) + + self.Werror = Werror + self.swig = swig + self.bin_only = bin_only + self.skip_lib = bin_only or skip_lib + +class PySource(SourceFile): + '''Add a python source file to the named package''' invalid_sym_char = re.compile('[^A-z0-9_]') - def __init__(self, package, tnode): - snode = tnode.srcnode() - filename = str(tnode) - pyname = basename(filename) - assert pyname.endswith('.py') - name = pyname[:-3] + modules = {} + tnodes = {} + symnames = {} + + def __init__(self, package, source): + super(PySource, self).__init__(source) + + modname,ext = self.extname + assert ext == 'py' + if package: path = package.split('.') else: path = [] modpath = path[:] - if name != '__init__': - modpath += [name] + if modname != '__init__': + modpath += [ modname ] modpath = '.'.join(modpath) - arcpath = path + [ pyname ] - arcname = joinpath(*arcpath) - - debugname = snode.abspath + arcpath = path + [ self.basename ] + debugname = self.snode.abspath if not exists(debugname): - debugname = tnode.abspath + debugname = self.tnode.abspath - self.tnode = tnode - self.snode = snode - self.pyname = pyname self.package = package + self.modname = modname self.modpath = modpath - self.arcname = arcname + self.arcname = joinpath(*arcpath) self.debugname = debugname - self.compiled = File(filename + 'c') - self.assembly = File(filename + '.s') - self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath) - + self.compiled = File(self.filename + 'c') + self.assembly = File(self.filename + '.s') + self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath) -######################################################################## -# Code for adding source files of various types -# -cc_lib_sources = [] -def Source(source): - '''Add a source file to the libm5 build''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) + PySource.modules[modpath] = self + PySource.tnodes[self.tnode] = self + PySource.symnames[self.symname] = self - cc_lib_sources.append(source) +class SimObject(PySource): + '''Add a SimObject python file as a python source object and add + it to a list of sim object modules''' -cc_bin_sources = [] -def BinSource(source): - '''Add a source file to the m5 binary build''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) + fixed = False + modnames = [] - cc_bin_sources.append(source) + def __init__(self, source): + super(SimObject, self).__init__('m5.objects', source) + if self.fixed: + raise AttributeError, "Too late to call SimObject now." -py_sources = [] -def PySource(package, source): - '''Add a python source file to the named package''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) + bisect.insort_right(SimObject.modnames, self.modname) - source = PySourceFile(package, source) - py_sources.append(source) +class SwigSource(SourceFile): + '''Add a swig file to build''' -sim_objects_fixed = False -sim_object_modfiles = set() -def SimObject(source): - '''Add a SimObject python file as a python source object and add - it to a list of sim object modules''' + def __init__(self, package, source): + super(SwigSource, self).__init__(source) - if sim_objects_fixed: - raise AttributeError, "Too late to call SimObject now." + modname,ext = self.extname + assert ext == 'i' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) + self.module = modname + cc_file = joinpath(self.dirname, modname + '_wrap.cc') + py_file = joinpath(self.dirname, modname + '.py') - PySource('m5.objects', source) - modfile = basename(str(source)) - assert modfile.endswith('.py') - modname = modfile[:-3] - sim_object_modfiles.add(modname) - -swig_sources = [] -def SwigSource(package, source): - '''Add a swig file to build''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) - val = source,package - swig_sources.append(val) + self.cc_source = Source(cc_file, swig=True) + self.py_source = PySource(package, py_file) unit_tests = [] def UnitTest(target, sources): if not isinstance(sources, (list, tuple)): sources = [ sources ] - - srcs = [] - for source in sources: - if not isinstance(source, SCons.Node.FS.File): - source = File(source) - srcs.append(source) - - unit_tests.append((target, srcs)) + + sources = [ Source(src, skip_lib=True) for src in sources ] + unit_tests.append((target, sources)) # Children should have access Export('Source') -Export('BinSource') Export('PySource') Export('SimObject') Export('SwigSource') @@ -276,7 +299,8 @@ class DictImporter(object): if fullname.startswith('m5.internal'): return None - if fullname in self.modules and exists(self.modules[fullname]): + source = self.modules.get(fullname, None) + if source is not None and exists(source.snode.abspath): return self return None @@ -295,34 +319,28 @@ class DictImporter(object): mod.__dict__['buildEnv'] = build_env return mod - srcfile = self.modules[fullname] - if basename(srcfile) == '__init__.py': - mod.__path__ = fullname.split('.') - mod.__file__ = srcfile + source = self.modules[fullname] + if source.modname == '__init__': + mod.__path__ = source.modpath + mod.__file__ = source.snode.abspath - exec file(srcfile, 'r') in mod.__dict__ + exec file(source.snode.abspath, 'r') in mod.__dict__ return mod -py_modules = {} -for source in py_sources: - py_modules[source.modpath] = source.snode.abspath - # install the python importer so we can grab stuff from the source # tree itself. We can't have SimObjects added after this point or # else we won't know about them for the rest of the stuff. -sim_objects_fixed = True -importer = DictImporter(py_modules) +SimObject.fixed = True +importer = DictImporter(PySource.modules) sys.meta_path[0:0] = [ importer ] import m5 # import all sim objects so we can populate the all_objects list # make sure that we're working with a list, then let's sort it -sim_objects = list(sim_object_modfiles) -sim_objects.sort() -for simobj in sim_objects: - exec('from m5.objects import %s' % simobj) +for modname in SimObject.modnames: + exec('from m5.objects import %s' % modname) # we need to unload all of the currently imported modules so that they # will be re-imported the next time the sconscript is run @@ -333,7 +351,7 @@ sim_objects = m5.SimObject.allClasses all_enums = m5.params.allEnums all_params = {} -for name,obj in sim_objects.iteritems(): +for name,obj in sorted(sim_objects.iteritems()): for param in obj._params.local.values(): if not hasattr(param, 'swig_decl'): continue @@ -346,7 +364,7 @@ for name,obj in sim_objects.iteritems(): # calculate extra dependencies # module_depends = ["m5", "m5.SimObject", "m5.params"] -depends = [ File(py_modules[dep]) for dep in module_depends ] +depends = [ PySource.modules[dep].tnode for dep in module_depends ] ######################################################################## # @@ -392,7 +410,7 @@ def makeObjectsInitFile(target, source, env): # Generate an __init__.py file for the objects package env.Command('python/m5/objects/__init__.py', - [ Value(o) for o in sort_list(sim_object_modfiles) ], + map(Value, SimObject.modnames), makeObjectsInitFile) PySource('m5.objects', 'python/m5/objects/__init__.py') @@ -409,6 +427,7 @@ def createSimObjectParam(target, source, env): obj = sim_objects[name] print >>hh_file, obj.cxx_decl() + hh_file.close() def createSwigParam(target, source, env): assert len(target) == 1 and len(source) == 1 @@ -419,6 +438,7 @@ def createSwigParam(target, source, env): for line in param.swig_decl(): print >>i_file, line + i_file.close() def createEnumStrings(target, source, env): assert len(target) == 1 and len(source) == 1 @@ -438,11 +458,13 @@ def createEnumParam(target, source, env): obj = all_enums[name] print >>hh_file, obj.cxx_decl() + hh_file.close() # Generate all of the SimObject param struct header files params_hh_files = [] -for name,simobj in sim_objects.iteritems(): - extra_deps = [ File(py_modules[simobj.__module__]) ] +for name,simobj in sorted(sim_objects.iteritems()): + py_source = PySource.modules[simobj.__module__] + extra_deps = [ py_source.tnode ] hh_file = File('params/%s.hh' % name) params_hh_files.append(hh_file) @@ -463,8 +485,9 @@ for name,param in all_params.iteritems(): env.Depends(i_file, depends) # Generate all enum header files -for name,enum in all_enums.iteritems(): - extra_deps = [ File(py_modules[enum.__module__]) ] +for name,enum in sorted(all_enums.iteritems()): + py_source = PySource.modules[enum.__module__] + extra_deps = [ py_source.tnode ] cc_file = File('enums/%s.cc' % name) env.Command(cc_file, Value(name), createEnumStrings) @@ -576,32 +599,18 @@ def buildParams(target, source, env): print >>out, '%%include "params/%s.hh"' % obj params_file = File('params/params.i') -names = sort_list(sim_objects.keys()) -env.Command(params_file, [ Value(v) for v in names ], buildParams) +names = sorted(sim_objects.keys()) +env.Command(params_file, map(Value, names), buildParams) env.Depends(params_file, params_hh_files + params_i_files + depends) SwigSource('m5.objects', params_file) # Build all swig modules -swig_modules = [] -cc_swig_sources = [] -for source,package in swig_sources: - filename = str(source) - assert filename.endswith('.i') - - base = '.'.join(filename.split('.')[:-1]) - module = basename(base) - cc_file = base + '_wrap.cc' - py_file = base + '.py' - - env.Command([cc_file, py_file], source, +for swig in SwigSource.all: + env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' '-o ${TARGETS[0]} $SOURCES') - env.Depends(py_file, source) - env.Depends(cc_file, source) - - swig_modules.append(Value(module)) - cc_swig_sources.append(File(cc_file)) - PySource(package, py_file) + env.Depends(swig.py_source.tnode, swig.tnode) + env.Depends(swig.cc_source.tnode, swig.tnode) # Generate the main swig init file def makeSwigInit(target, source, env): @@ -616,7 +625,9 @@ def makeSwigInit(target, source, env): print >>f, '}' f.close() -env.Command('python/swig/init.cc', swig_modules, makeSwigInit) +env.Command('python/swig/init.cc', + map(Value, sorted(s.module for s in SwigSource.all)), + makeSwigInit) Source('python/swig/init.cc') # Generate traceflags.py @@ -813,7 +824,7 @@ extern const Flags *compoundFlags[]; f.close() -flags = [ Value(f) for f in trace_flags.values() ] +flags = map(Value, trace_flags.values()) env.Command('base/traceflags.py', flags, traceFlagsPy) PySource('m5', 'base/traceflags.py') @@ -827,10 +838,6 @@ Source('base/traceflags.cc') # byte code, compress it, and then generate an assembly file that # inserts the result into the data section with symbols indicating the # beginning, and end (and with the size at the end) -py_sources_tnodes = {} -for pysource in py_sources: - py_sources_tnodes[pysource.tnode] = pysource - def objectifyPyFile(target, source, env): '''Action function to compile a .py into a code object, marshal it, compress it, and stick it into an asm file so the code appears @@ -839,7 +846,7 @@ def objectifyPyFile(target, source, env): src = file(str(source[0]), 'r').read() dst = file(str(target[0]), 'w') - pysource = py_sources_tnodes[source[0]] + pysource = PySource.tnodes[source[0]] compiled = compile(src, pysource.debugname, 'exec') marshalled = marshal.dumps(compiled) compressed = zlib.compress(marshalled) @@ -864,7 +871,7 @@ def objectifyPyFile(target, source, env): print >>dst, "%s_end:" % sym print >>dst, ".long %d" % len(marshalled) -for source in py_sources: +for source in PySource.all: env.Command(source.assembly, source.tnode, objectifyPyFile) Source(source.assembly) @@ -873,14 +880,11 @@ for source in py_sources: # contains information about the importer that python uses to get at # the embedded files, and then there's a list of all of the rest that # the importer uses to load the rest on demand. -py_sources_symbols = {} -for pysource in py_sources: - py_sources_symbols[pysource.symname] = pysource def pythonInit(target, source, env): dst = file(str(target[0]), 'w') def dump_mod(sym, endchar=','): - pysource = py_sources_symbols[sym] + pysource = PySource.symnames[sym] print >>dst, ' { "%s",' % pysource.arcname print >>dst, ' "%s",' % pysource.modpath print >>dst, ' %s_beg, %s_end,' % (sym, sym) @@ -907,8 +911,10 @@ def pythonInit(target, source, env): print >>dst, " { 0, 0, 0, 0, 0, 0 }" print >>dst, "};" -symbols = [Value(s.symname) for s in py_sources] -env.Command('sim/init_python.cc', symbols, pythonInit) + +env.Command('sim/init_python.cc', + map(Value, (s.symname for s in PySource.all)), + pythonInit) Source('sim/init_python.cc') ######################################################################## @@ -920,26 +926,7 @@ Source('sim/init_python.cc') # List of constructed environments to pass back to SConstruct envList = [] -# This function adds the specified sources to the given build -# environment, and returns a list of all the corresponding SCons -# Object nodes (including an extra one for date.cc). We explicitly -# add the Object nodes so we can set up special dependencies for -# date.cc. -def make_objs(sources, env, static): - if static: - XObject = env.StaticObject - else: - XObject = env.SharedObject - - objs = [ XObject(s) for s in sources ] - - # make date.cc depend on all other objects so it always gets - # recompiled whenever anything else does - date_obj = XObject('base/date.cc') - - env.Depends(date_obj, objs) - objs.append(date_obj) - return objs +date_source = Source('base/date.cc', skip_lib=True) # Function to create a new build environment as clone of current # environment 'env' with modified object suffix and optional stripped @@ -956,15 +943,45 @@ def makeEnv(label, objsfx, strip = False, **kwargs): new_env.Append(**kwargs) swig_env = new_env.Clone() + swig_env.Append(CCFLAGS='-Werror') if env['GCC']: swig_env.Append(CCFLAGS='-Wno-uninitialized') swig_env.Append(CCFLAGS='-Wno-sign-compare') swig_env.Append(CCFLAGS='-Wno-parentheses') - static_objs = make_objs(cc_lib_sources, new_env, static=True) - shared_objs = make_objs(cc_lib_sources, new_env, static=False) - static_objs += [ swig_env.StaticObject(s) for s in cc_swig_sources ] - shared_objs += [ swig_env.SharedObject(s) for s in cc_swig_sources ] + werror_env = new_env.Clone() + werror_env.Append(CCFLAGS='-Werror') + + def make_obj(source, static, extra_deps = None): + '''This function adds the specified source to the correct + build environment, and returns the corresponding SCons Object + nodes''' + + if source.swig: + env = swig_env + elif source.Werror: + env = werror_env + else: + env = new_env + + if static: + obj = env.StaticObject(source.tnode) + else: + obj = env.SharedObject(source.tnode) + + if extra_deps: + env.Depends(obj, extra_deps) + + return obj + + static_objs = [ make_obj(s, True) for s in Source.get(skip_lib=False)] + shared_objs = [ make_obj(s, False) for s in Source.get(skip_lib=False)] + + static_date = make_obj(date_source, static=True, extra_deps=static_objs) + static_objs.append(static_date) + + shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) + shared_objs.append(static_date) # First make a library of everything but main() so other programs can # link against m5. @@ -972,21 +989,23 @@ def makeEnv(label, objsfx, strip = False, **kwargs): shared_lib = new_env.SharedLibrary(libname, shared_objs) for target, sources in unit_tests: - objs = [ new_env.StaticObject(s) for s in sources ] + objs = [ make_obj(s, static=True) for s in sources ] new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs) # Now link a stub with main() and the static library. - objects = [new_env.Object(s) for s in cc_bin_sources] + static_objs + bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ] + progname = exename + if strip: + progname += '.unstripped' + + targets = new_env.Program(progname, bin_objs + static_objs) + if strip: - unstripped_exe = exename + '.unstripped' - new_env.Program(unstripped_exe, objects) if sys.platform == 'sunos5': cmd = 'cp $SOURCE $TARGET; strip $TARGET' else: cmd = 'strip $SOURCE -o $TARGET' - targets = new_env.Command(exename, unstripped_exe, cmd) - else: - targets = new_env.Program(exename, objects) + targets = new_env.Command(exename, progname, cmd) new_env.M5Binary = targets[0] envList.append(new_env) diff --git a/src/sim/SConscript b/src/sim/SConscript index 750007947..c13ea9909 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -41,7 +41,7 @@ Source('debug.cc') Source('eventq.cc') Source('faults.cc') Source('init.cc') -BinSource('main.cc') +Source('main.cc', bin_only=True) Source('pseudo_inst.cc') Source('root.cc') Source('serialize.cc') -- cgit v1.2.3