X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Farch%2Farm%2Fisa.cc;h=b8a0fe2823572e7d674e515c2de110c47cdb3237;hb=df05ffab1289b26aab2a0eb71ee55dcb7f42e5e9;hp=20cddcff16c5b808a20bfd3fdab466fc51e92e57;hpb=0f2bbe15ddfeb3894726c19e09ed23f7027df1cb;p=gem5.git diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 20cddcff1..b8a0fe282 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -39,7 +39,16 @@ */ #include "arch/arm/isa.hh" +#include "config/use_checker.hh" +#include "debug/Arm.hh" +#include "debug/MiscRegs.hh" #include "sim/faults.hh" +#include "sim/stat_control.hh" +#include "sim/system.hh" + +#if USE_CHECKER +#include "cpu/checker/cpu.hh" +#endif namespace ArmISA { @@ -48,7 +57,7 @@ void ISA::clear() { SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST]; - + uint32_t midr = miscRegs[MISCREG_MIDR]; memset(miscRegs, 0, sizeof(miscRegs)); CPSR cpsr = 0; cpsr.mode = MODE_USER; @@ -67,21 +76,12 @@ ISA::clear() miscRegs[MISCREG_SCTLR] = sctlr; miscRegs[MISCREG_SCTLR_RST] = sctlr_rst; + // Preserve MIDR accross reset + miscRegs[MISCREG_MIDR] = midr; + /* Start with an event in the mailbox */ miscRegs[MISCREG_SEV_MAILBOX] = 1; - /* - * Implemented = '5' from "M5", - * Variant = 0, - */ - miscRegs[MISCREG_MIDR] = - (0x35 << 24) | // Implementor is '5' from "M5" - (0 << 20) | // Variant - (0xf << 16) | // Architecture from CPUID scheme - (0xf00 << 4) | // Primary part number - (0 << 0) | // Revision - 0; - // Separate Instruction and Data TLBs. miscRegs[MISCREG_TLBTR] = 1; @@ -142,6 +142,16 @@ ISA::clear() miscRegs[MISCREG_CPACR] = 0; miscRegs[MISCREG_FPSID] = 0x410430A0; + + // See section B4.1.84 of ARM ARM + // All values are latest for ARMv7-A profile + miscRegs[MISCREG_ID_ISAR0] = 0x02101111; + miscRegs[MISCREG_ID_ISAR1] = 0x02112111; + miscRegs[MISCREG_ID_ISAR2] = 0x21232141; + miscRegs[MISCREG_ID_ISAR3] = 0x01112131; + miscRegs[MISCREG_ID_ISAR4] = 0x10010142; + miscRegs[MISCREG_ID_ISAR5] = 0x00000000; + //XXX We need to initialize the rest of the state. } @@ -173,15 +183,29 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc) cpsr.t = pc.thumb() ? 1 : 0; return cpsr; } - if (misc_reg >= MISCREG_CP15_UNIMP_START && - misc_reg < MISCREG_CP15_END) { + if (misc_reg >= MISCREG_CP15_UNIMP_START) panic("Unimplemented CP15 register %s read.\n", miscRegName[misc_reg]); - } + switch (misc_reg) { + case MISCREG_MPIDR: + + return 0x80000000 | // multiprocessor extensions available + tc->cpuId(); + break; + case MISCREG_ID_MMFR0: + return 0x03; // VMSAv7 support + case MISCREG_ID_MMFR2: + return 0x01230000; // no HW access | WFI stalling | ISB and DSB + // | all TLB maintenance | no Harvard + case MISCREG_ID_MMFR3: + return 0xF0102211; // SuperSec | Coherent TLB | Bcast Maint | + // BP Maint | Cache Maint Set/way | Cache Maint MVA case MISCREG_CLIDR: warn_once("The clidr register always reports 0 caches.\n"); - break; + warn_once("clidr LoUIS field of 0b001 to match current " + "ARM implementations.\n"); + return 0x00200000; case MISCREG_CCSIDR: warn_once("The ccsidr register isn't implemented and " "always reads as 0.\n"); @@ -190,8 +214,8 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc) warn("Returning thumbEE disabled for now since we don't support CP14" "config registers and jumping to ThumbEE vectors\n"); return 0x0031; // !ThumbEE | !Jazelle | Thumb | ARM - case MISCREG_ID_MMFR0: - return 0x03; //VMSAz7 + case MISCREG_ID_PFR1: + return 0x00001; // !Timer | !Virti | !M Profile | !TrustZone | ARMv4 case MISCREG_CTR: return 0x86468006; // V7, 64 byte cache line, load/exclusive is exact case MISCREG_ACTLR: @@ -200,10 +224,30 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc) case MISCREG_PMCR: case MISCREG_PMCCNTR: case MISCREG_PMSELR: - warn("Not doing anyhting for read to miscreg %s\n", + warn("Not doing anything for read to miscreg %s\n", miscRegName[misc_reg]); break; - + case MISCREG_CPSR_Q: + panic("shouldn't be reading this register seperately\n"); + case MISCREG_FPSCR_QC: + return readMiscRegNoEffect(MISCREG_FPSCR) & ~FpscrQcMask; + case MISCREG_FPSCR_EXC: + return readMiscRegNoEffect(MISCREG_FPSCR) & ~FpscrExcMask; + case MISCREG_L2CTLR: + { + // mostly unimplemented, just set NumCPUs field from sim and return + L2CTLR l2ctlr = 0; + // b00:1CPU to b11:4CPUs + l2ctlr.numCPUs = tc->getSystemPtr()->numContexts() - 1; + return l2ctlr; + } + case MISCREG_DBGDIDR: + /* For now just implement the version number. + * Return 0 as we don't support debug architecture yet. + */ + return 0; + case MISCREG_DBGDSCR_INT: + return 0; } return readMiscRegNoEffect(misc_reg); } @@ -227,49 +271,58 @@ ISA::setMiscRegNoEffect(int misc_reg, const MiscReg &val) void ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) { + MiscReg newVal = val; + int x; + System *sys; + ThreadContext *oc; + if (misc_reg == MISCREG_CPSR) { updateRegMap(val); + + + CPSR old_cpsr = miscRegs[MISCREG_CPSR]; + int old_mode = old_cpsr.mode; CPSR cpsr = val; + if (old_mode != cpsr.mode) { + tc->getITBPtr()->invalidateMiscReg(); + tc->getDTBPtr()->invalidateMiscReg(); + } + DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n", miscRegs[misc_reg], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode); PCState pc = tc->pcState(); pc.nextThumb(cpsr.t); pc.nextJazelle(cpsr.j); +#if USE_CHECKER + tc->pcStateNoRecord(pc); +#else tc->pcState(pc); +#endif //USE_CHECKER } else if (misc_reg >= MISCREG_CP15_UNIMP_START && misc_reg < MISCREG_CP15_END) { panic("Unimplemented CP15 register %s wrote with %#x.\n", miscRegName[misc_reg], val); } else { switch (misc_reg) { - case MISCREG_ITSTATE: - { - ITSTATE itstate = newVal; - CPSR cpsr = miscRegs[MISCREG_CPSR]; - cpsr.it1 = itstate.bottom2; - cpsr.it2 = itstate.top6; - miscRegs[MISCREG_CPSR] = cpsr; - DPRINTF(MiscRegs, - "Updating ITSTATE -> %#x in CPSR -> %#x.\n", - (uint8_t)itstate, (uint32_t)cpsr); - } - break; case MISCREG_CPACR: { - CPACR newCpacr = 0; - CPACR valCpacr = val; - newCpacr.cp10 = valCpacr.cp10; - newCpacr.cp11 = valCpacr.cp11; - //XXX d32dis isn't implemented. The manual says whether or not - //it works is implementation defined. - newCpacr.asedis = valCpacr.asedis; - newVal = newCpacr; + + const uint32_t ones = (uint32_t)(-1); + CPACR cpacrMask = 0; + // Only cp10, cp11, and ase are implemented, nothing else should + // be writable + cpacrMask.cp10 = ones; + cpacrMask.cp11 = ones; + cpacrMask.asedis = ones; + newVal &= cpacrMask; + DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n", + miscRegName[misc_reg], newVal); } break; case MISCREG_CSSELR: warn_once("The csselr register isn't implemented.\n"); - break; + return; case MISCREG_FPSCR: { const uint32_t ones = (uint32_t)(-1); @@ -295,8 +348,29 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) (miscRegs[MISCREG_FPSCR] & ~(uint32_t)fpscrMask); } break; + case MISCREG_CPSR_Q: + { + assert(!(newVal & ~CpsrMaskQ)); + newVal = miscRegs[MISCREG_CPSR] | newVal; + misc_reg = MISCREG_CPSR; + } + break; + case MISCREG_FPSCR_QC: + { + newVal = miscRegs[MISCREG_FPSCR] | (newVal & FpscrQcMask); + misc_reg = MISCREG_FPSCR; + } + break; + case MISCREG_FPSCR_EXC: + { + newVal = miscRegs[MISCREG_FPSCR] | (newVal & FpscrExcMask); + misc_reg = MISCREG_FPSCR; + } + break; case MISCREG_FPEXC: { + // vfpv3 architecture, section B.6.1 of DDI04068 + // bit 29 - valid only if fpexc[31] is 0 const uint32_t fpexcMask = 0x60000000; newVal = (newVal & fpexcMask) | (miscRegs[MISCREG_FPEXC] & ~fpexcMask); @@ -309,6 +383,33 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) SCTLR new_sctlr = newVal; new_sctlr.nmfi = (bool)sctlr.nmfi; miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr; + tc->getITBPtr()->invalidateMiscReg(); + tc->getDTBPtr()->invalidateMiscReg(); + + // Check if all CPUs are booted with caches enabled + // so we can stop enforcing coherency of some kernel + // structures manually. + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + SCTLR other_sctlr = oc->readMiscRegNoEffect(MISCREG_SCTLR); + if (!other_sctlr.c && oc->status() != ThreadContext::Halted) + return; + } + + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + oc->getDTBPtr()->allCpusCaching(); + oc->getITBPtr()->allCpusCaching(); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getDTBPtr()->allCpusCaching(); + checker->getITBPtr()->allCpusCaching(); + } +#endif + } return; } case MISCREG_TLBTR: @@ -319,9 +420,21 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) return; case MISCREG_TLBIALLIS: case MISCREG_TLBIALL: - warn_once("Need to flush all TLBs in MP\n"); - tc->getITBPtr()->flushAll(); - tc->getDTBPtr()->flushAll(); + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushAll(); + oc->getDTBPtr()->flushAll(); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushAll(); + checker->getDTBPtr()->flushAll(); + } +#endif + } return; case MISCREG_ITLBIALL: tc->getITBPtr()->flushAll(); @@ -331,23 +444,61 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) return; case MISCREG_TLBIMVAIS: case MISCREG_TLBIMVA: - warn_once("Need to flush all TLBs in MP\n"); - tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), - bits(newVal, 7,0)); - tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), - bits(newVal, 7,0)); + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + oc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + checker->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + } +#endif + } return; case MISCREG_TLBIASIDIS: case MISCREG_TLBIASID: - warn_once("Need to flush all TLBs in MP\n"); - tc->getITBPtr()->flushAsid(bits(newVal, 7,0)); - tc->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushAsid(bits(newVal, 7,0)); + oc->getDTBPtr()->flushAsid(bits(newVal, 7,0)); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushAsid(bits(newVal, 7,0)); + checker->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + } +#endif + } return; case MISCREG_TLBIMVAAIS: case MISCREG_TLBIMVAA: - warn_once("Need to flush all TLBs in MP\n"); - tc->getITBPtr()->flushMva(mbits(newVal, 31,12)); - tc->getDTBPtr()->flushMva(mbits(newVal, 31,12)); + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + assert(oc->getITBPtr() && oc->getDTBPtr()); + oc->getITBPtr()->flushMva(mbits(newVal, 31,12)); + oc->getDTBPtr()->flushMva(mbits(newVal, 31,12)); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushMva(mbits(newVal, 31,12)); + checker->getDTBPtr()->flushMva(mbits(newVal, 31,12)); + } +#endif + } return; case MISCREG_ITLBIMVA: tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), @@ -367,6 +518,18 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) warn("Not doing anything for write of miscreg ACTLR\n"); break; case MISCREG_PMCR: + { + // Performance counters not implemented. Instead, interpret + // a reset command to this register to reset the simulator + // statistics. + // PMCR_E | PMCR_P | PMCR_C + const int ResetAndEnableCounters = 0x7; + if (newVal == ResetAndEnableCounters) { + inform("Resetting all simobject stats\n"); + Stats::schedStatEvent(false, true); + break; + } + } case MISCREG_PMCCNTR: case MISCREG_PMSELR: warn("Not doing anything for write to miscreg %s\n", @@ -405,7 +568,9 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) default: panic("Security Extensions not implemented!"); } - req->setVirt(0, val, 1, flags, tc->pcState().pc()); + warn("Translating via MISCREG in atomic mode! Fix Me!\n"); + req->setVirt(0, val, 1, flags, tc->pcState().pc(), + Request::funcMasterId); fault = tc->getDTBPtr()->translateAtomic(req, tc, mode); if (fault == NoFault) { miscRegs[MISCREG_PAR] = @@ -426,6 +591,23 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) } return; } + case MISCREG_CONTEXTIDR: + case MISCREG_PRRR: + case MISCREG_NMRR: + case MISCREG_DACR: + tc->getITBPtr()->invalidateMiscReg(); + tc->getDTBPtr()->invalidateMiscReg(); + break; + case MISCREG_CPSR_MODE: + // This miscreg is used by copy*Regs to set the CPSR mode + // without updating other CPSR variables. It's used to + // make sure the register map is in such a state that we can + // see all of the registers for the copy. + updateRegMap(val); + return; + case MISCREG_L2CTLR: + warn("miscreg L2CTLR (%s) written with %#x. ignored...\n", + miscRegName[misc_reg], uint32_t(val)); } } setMiscRegNoEffect(misc_reg, newVal);