57#include "debug/Arm.hh"
58#include "debug/LLSC.hh"
59#include "debug/MatRegs.hh"
60#include "debug/VecPredRegs.hh"
61#include "debug/VecRegs.hh"
65#include "params/ArmISA.hh"
160 if (
release->has(ArmExtension::TME)) {
162 tc->setHtmCheckpointPtr(std::move(cpt));
170 pmu->setThreadContext(
tc);
178 gicv3_ifc->setISA(
this);
179 gicv3_ifc->setThreadContext(
tc);
239 bool sec_el2 = scr.eel2 &&
release->has(ArmExtension::FEAT_SEL2);
405 int lower = map.first, upper = map.second;
411 DPRINTF(MiscRegs,
"Reading MiscReg %s with set res0 bits: %#x\n",
415 DPRINTF(MiscRegs,
"Reading MiscReg %s with clear res1 bits: %#x\n",
431 cpsr.t =
pc.thumb() ? 1 : 0;
439 warn(
"Unimplemented system register %s read.\n",
442 panic(
"Unimplemented system register %s read.\n",
451 const uint32_t ones = (uint32_t)(-1);
455 cpacrMask.cp10 = ones;
456 cpacrMask.cp11 = ones;
457 cpacrMask.asedis = ones;
460 if (
release->has(ArmExtension::SECURITY)) {
466 if (!nsacr.cp10) cpacrMask.cp10 = 0;
467 if (!nsacr.cp11) cpacrMask.cp11 = 0;
472 DPRINTF(MiscRegs,
"Reading misc reg %s: %#x\n",
491 warn_once(
"The clidr register always reports 0 caches.\n");
492 warn_once(
"clidr LoUIS field of 0b001 to match current "
493 "ARM implementations.\n");
496 warn_once(
"The ccsidr register isn't implemented and "
497 "always reads as 0.\n");
500 warn(
"Not doing anything for miscreg ACTLR\n");
507 return pmu->readMiscReg(idx);
510 panic(
"shouldn't be reading this register seperately\n");
517 const uint32_t ones = (uint32_t)(-1);
519 fpscrMask.ioc = ones;
520 fpscrMask.dzc = ones;
521 fpscrMask.ofc = ones;
522 fpscrMask.ufc = ones;
523 fpscrMask.ixc = ones;
524 fpscrMask.idc = ones;
534 const uint32_t ones = (uint32_t)(-1);
536 fpscrMask.len = ones;
537 fpscrMask.fz16 = ones;
538 fpscrMask.stride = ones;
539 fpscrMask.rMode = ones;
542 fpscrMask.ahp = ones;
592 l2ctlr.numCPUs =
tc->getSystemPtr()->threads.size() - 1;
599 tc->getCpuPtr()->getInterruptController(
tc->threadId()));
608 bool secure_lookup =
release->has(ArmExtension::SECURITY) &&
610 if (!secure_lookup) {
680 int lower = map.first, upper = map.second;
686 DPRINTF(MiscRegs,
"Writing MiscReg %s (%d %d:%d) : %#x\n",
690 DPRINTF(MiscRegs,
"Writing MiscReg %s (%d %d) : %#x\n",
708 int old_mode = old_cpsr.mode;
710 if (cpsr.pan != old_cpsr.pan || cpsr.il != old_cpsr.il) {
714 DPRINTF(Arm,
"Updating CPSR from %#x to %#x f:%d i:%d a:%d d:%d "
715 "mode:%#x\n",
miscRegs[idx], cpsr, cpsr.f, cpsr.i, cpsr.a,
718 pc.nextThumb(cpsr.t);
719 pc.illegalExec(cpsr.il == 1);
722 tc->getDecoderPtr()->as<
Decoder>().setSveLen(
724 tc->getDecoderPtr()->as<
Decoder>().setSmeLen(
731 tc->pcStateNoRecord(
pc);
738 if (old_mode != cpsr.mode) {
758 warn(
"Unimplemented system register %s write with %#x.\n",
761 panic(
"Unimplemented system register %s write with %#x.\n",
771 const uint32_t ones = (uint32_t)(-1);
775 cpacrMask.cp10 = ones;
776 cpacrMask.cp11 = ones;
777 cpacrMask.asedis = ones;
780 if (
release->has(ArmExtension::SECURITY)) {
786 if (!nsacr.cp10) cpacrMask.cp10 = 0;
787 if (!nsacr.cp11) cpacrMask.cp11 = 0;
793 newVal |= old_val & ~cpacrMask;
794 DPRINTF(MiscRegs,
"Writing misc reg %s: %#x\n",
800 const uint32_t ones = (uint32_t)(-1);
802 cpacrMask.tta = ones;
803 cpacrMask.fpen = ones;
804 if (
release->has(ArmExtension::FEAT_SVE)) {
805 cpacrMask.zen = ones;
807 if (
release->has(ArmExtension::FEAT_SME)) {
808 cpacrMask.smen = ones;
811 DPRINTF(MiscRegs,
"Writing misc reg %s: %#x\n",
818 const uint32_t ones = (uint32_t)(-1);
820 cptrMask.tcpac = ones;
823 if (
release->has(ArmExtension::FEAT_SVE)) {
825 cptrMask.zen = hcr.e2h ? ones : 0;
827 if (
release->has(ArmExtension::FEAT_SME)) {
829 cptrMask.smen = hcr.e2h ? ones : 0;
831 cptrMask.fpen = hcr.e2h ? ones : 0;
834 cptrMask.res1_13_el2 = ones;
835 cptrMask.res1_7_0_el2 = ones;
836 if (!
release->has(ArmExtension::FEAT_SVE)) {
837 cptrMask.res1_8_el2 = ones;
839 if (!
release->has(ArmExtension::FEAT_SME)) {
840 cptrMask.res1_12_el2 = ones;
842 cptrMask.res1_9_el2 = ones;
844 DPRINTF(MiscRegs,
"Writing misc reg %s: %#x\n",
850 const uint32_t ones = (uint32_t)(-1);
852 cptrMask.tcpac = ones;
855 if (
release->has(ArmExtension::FEAT_SVE)) {
858 if (
release->has(ArmExtension::FEAT_SME)) {
862 DPRINTF(MiscRegs,
"Writing misc reg %s: %#x\n",
867 warn_once(
"The csselr register isn't implemented.\n");
871 warn(
"Calling DC ZVA! Not Implemeted! Expect WEIRD results\n");
875 tc->getDecoderPtr()->as<
Decoder>().setContext(newVal);
879 const uint32_t ones = (uint32_t)(-1);
881 fpscrMask.ioc = ones;
882 fpscrMask.dzc = ones;
883 fpscrMask.ofc = ones;
884 fpscrMask.ufc = ones;
885 fpscrMask.ixc = ones;
886 fpscrMask.idc = ones;
892 newVal = (newVal & (uint32_t)fpscrMask) |
894 ~(uint32_t)fpscrMask);
900 const uint32_t ones = (uint32_t)(-1);
902 fpscrMask.len = ones;
903 fpscrMask.fz16 = ones;
904 fpscrMask.stride = ones;
905 fpscrMask.rMode = ones;
908 fpscrMask.ahp = ones;
909 newVal = (newVal & (uint32_t)fpscrMask) |
911 ~(uint32_t)fpscrMask);
940 const uint32_t fpexcMask = 0x60000000;
941 newVal = (newVal & fpexcMask) |
961 const uint32_t temp = (
val == 0xC5ACCE55)? 0x1 : 0x0;
963 r.oslk =
bits(temp,0);
992 r.udccdis =
v.udccdis;
1026 DPRINTF(MiscRegs,
"Writing SCTLR: %#x\n", newVal);
1030 if (
release->has(ArmExtension::SECURITY) &&
1038 SCTLR new_sctlr = newVal;
1039 new_sctlr.nmfi = ((bool)sctlr.nmfi) &&
1040 !
release->has(ArmExtension::VIRTUALIZATION);
1082 warn(
"Not doing anything for write of miscreg ACTLR\n");
1089 pmu->setMiscReg(idx, newVal);
1097 newVal &= ~((uint32_t) hstrMask);
1104 secure_lookup =
release->has(ArmExtension::SECURITY) &&
1106 if (!secure_lookup) {
1110 newVal = (newVal &
~mask) | (oldValue &
mask);
1135 if (!
release->has(ArmExtension::SECURITY))
1136 panic(
"Security Extensions required for ATS12NSOPR");
1140 if (!
release->has(ArmExtension::SECURITY))
1141 panic(
"Security Extensions required for ATS12NSOPW");
1145 if (!
release->has(ArmExtension::SECURITY))
1146 panic(
"Security Extensions required for ATS12NSOUR");
1151 if (!
release->has(ArmExtension::SECURITY))
1152 panic(
"Security Extensions required for ATS12NSOUW");
1165 const uint32_t ones = (uint32_t)(-1);
1166 TTBCR ttbcrMask = 0;
1167 TTBCR ttbcrNew = newVal;
1171 if (
release->has(ArmExtension::SECURITY)) {
1172 ttbcrMask.pd0 = ones;
1173 ttbcrMask.pd1 = ones;
1175 ttbcrMask.epd0 = ones;
1176 ttbcrMask.irgn0 = ones;
1177 ttbcrMask.orgn0 = ones;
1178 ttbcrMask.sh0 = ones;
1179 ttbcrMask.ps = ones;
1180 ttbcrMask.a1 = ones;
1181 ttbcrMask.epd1 = ones;
1182 ttbcrMask.irgn1 = ones;
1183 ttbcrMask.orgn1 = ones;
1184 ttbcrMask.sh1 = ones;
1185 if (
release->has(ArmExtension::LPAE))
1186 ttbcrMask.eae = ones;
1188 if (
release->has(ArmExtension::LPAE) && ttbcrNew.eae) {
1189 newVal = newVal & ttbcrMask;
1191 newVal = (newVal & ttbcrMask) | (ttbcr & (~ttbcrMask));
1201 if (
release->has(ArmExtension::LPAE)) {
1205 uint64_t ttbrMask =
mask(63,56) |
mask(47,40);
1206 newVal = (newVal & (~ttbrMask));
1263 cpsr.daif = (uint8_t) ((CPSR) newVal).daif;
1280 cpsr.sp = (uint8_t) ((CPSR) newVal).sp;
1288 cpsr.el = (uint8_t) ((CPSR) newVal).el;
1299 cpsr.pan = (uint8_t) ((CPSR) newVal).pan;
1310 cpsr.uao = (uint8_t) ((CPSR) newVal).uao;
1316 warn(
"miscreg L2CTLR (%s) written with %#x. ignored...\n",
1337 tc->getDecoderPtr()->as<
Decoder>().setSveLen(
1347 tc->getDecoderPtr()->as<
Decoder>().setSmeLen(
1375 return *
timer.get();
1379 if (!generic_timer) {
1380 panic(
"Trying to get a generic timer from a system that hasn't "
1381 "been configured to use a generic timer.\n");
1387 return *
timer.get();
1397 panic_if(!gicv3_ifc,
"The system does not have a GICv3 irq controller\n");
1418 if (!
release->has(ArmExtension::SECURITY)) {
1462 "A ThreadContext is needed to determine the SVE vector length "
1463 "in full-system mode");
1480 static_cast<unsigned>(
1486 }
else if (
release->has(ArmExtension::SECURITY)) {
1489 static_cast<unsigned>(
1495 return (
len + 1) * 128;
1506 "A ThreadContext is needed to determine the SME vector length "
1507 "in full-system mode");
1524 static_cast<unsigned>(
1530 }
else if (
release->has(ArmExtension::SECURITY)) {
1533 static_cast<unsigned>(
1541 static const unsigned LUT[16] = {0, 1, 1, 3, 3, 3, 3, 7,
1542 7, 7, 7, 7, 7, 7, 7, 15};
1545 return (
len + 1) * 128;
1553 DPRINTF(Checkpoint,
"Serializing Arm Misc Registers\n");
1560 DPRINTF(Checkpoint,
"Unserializing Arm Misc Registers\n");
1566 warn(
"Checkpoint value for register %s does not match "
1567 "current configuration (checkpointed: %#x, current: %#x)",
1588 warn_once(
"Doing AT (address translation) in functional mode! Fix Me!\n");
1590 auto req = std::make_shared<Request>(
1592 tc->pcState().instAddr(),
tc->contextId());
1595 req,
tc,
mode, tran_type);
1599 Addr paddr = req->getPaddr();
1603 uint8_t max_paddr_bit = 0;
1604 if (
release->has(ArmExtension::LPAE) &&
1613 par = (paddr &
mask(max_paddr_bit, 12)) |
1617 "MISCREG: Translated addr 0x%08x: PAR: 0x%08x\n",
1626 par.lpae = fsr.lpae;
1627 par.ptw = (arm_fault->
iss() >> 7) & 0x1;
1628 par.s = arm_fault->
isStage2() ? 1 : 0;
1632 par.fst = fsr.status;
1635 par.fs4_0 = fsr.fsLow | (fsr.fsHigh << 5);
1639 "MISCREG: Translated addr 0x%08x fault fsr %#x: PAR: 0x%08x\n",
1649 Addr cacheBlockMask)
1654 DPRINTF(LLSC,
"%s: handling snoop for address: %#x locked: %d\n",
1662 Addr snoop_addr = pkt->
getAddr() & cacheBlockMask;
1664 DPRINTF(LLSC,
"%s: handling snoop for address: %#x locked addr: %#x\n",
1666 if (locked_addr == snoop_addr) {
1667 DPRINTF(LLSC,
"%s: address match, clearing lock and signaling sev\n",
1693 DPRINTF(LLSC,
"%s: Placing address %#x in monitor\n",
1694 tc->getCpuPtr()->name(), req->getPaddr());
1702 DPRINTF(LLSC,
"%s: Placing address %#x in monitor\n",
1709 DPRINTF(LLSC,
"%s: handling snoop lock hit address: %#x\n",
1718 DPRINTF(LLSC,
"%s: handling snoop lock hit address: %#x\n",
1728 Addr cacheBlockMask)
1733 DPRINTF(LLSC,
"Handling locked write for address %#x in monitor.\n",
1739 if (!lock_flag || (req->getPaddr() & cacheBlockMask) != lock_addr) {
1742 req->setExtraData(0);
1744 DPRINTF(LLSC,
"clearing lock flag in handle locked write\n",
1750 int stCondFailures = xc->readStCondFailures();
1752 xc->setStCondFailures(stCondFailures);
1753 if (stCondFailures % 100000 == 0) {
1754 warn(
"context %d: %d consecutive "
1755 "store conditional failures\n",
1773 Addr cacheBlockMask)
1785 DPRINTF(LLSC,
"Clearing lock and signaling sev\n");
1799 DPRINTF(LLSC,
"Clearing lock and signaling sev\n");
ISA-specific types for hardware transactional memory.
virtual FSR getFsr(ThreadContext *tc) const
virtual uint32_t iss() const =0
virtual void update(ThreadContext *tc)
virtual bool isStage2() const
Base class for devices that use the MiscReg interfaces.
virtual void setMiscReg(int misc_reg, RegVal val)=0
Write to a system register belonging to this device.
virtual RegVal readMiscReg(int misc_reg)=0
Read a system register belonging to this device.
bool inSecureState() const
Return true if the PE is in Secure state.
void setMiscRegReset(RegIndex, RegVal val)
unsigned getCurSveVecLenInBits() const
ExceptionLevel currEL() const
Returns the current Exception Level (EL) of the ISA object.
void takeOverFrom(ThreadContext *new_tc, ThreadContext *old_tc) override
void serialize(CheckpointOut &cp) const override
Serialize an object.
void copyRegsFrom(ThreadContext *src) override
const enums::DecoderFlavor _decoderFlavor
DummyISADevice dummyDevice
Dummy device for to handle non-existing ISA devices.
RegVal readMiscRegReset(RegIndex) const
void setupThreadContext()
void setMiscRegNoEffect(RegIndex idx, RegVal val) override
void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask) override
int flattenMiscIndex(int reg) const
std::pair< int, int > getMiscIndices(int misc_reg) const
RegVal miscRegs[NUM_MISCREGS]
unsigned smeVL
SME vector length in quadwords.
std::unique_ptr< BaseISADevice > timer
bool handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask) override
void globalClearExclusive() override
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void updateRegMap(CPSR cpsr)
void startup() override
startup() is the final initialization call before simulation.
int redirectRegVHE(int misc_reg)
Returns the enconcing equivalent when VHE is implemented and HCR_EL2.E2H is enabled and executing at ...
BaseISADevice & getGICv3CPUInterface()
BaseISADevice & getGenericTimer()
RegVal readMiscRegNoEffect(RegIndex idx) const override
bool impdefAsNop
If true, accesses to IMPLEMENTATION DEFINED registers are treated as NOP hence not causing UNDEFINED ...
void setMiscReg(RegIndex, RegVal val) override
unsigned sveVL
SVE vector length in quadwords.
const MiscRegLUTEntryInitializer InitReg(uint32_t reg)
void handleLockedRead(const RequestPtr &req) override
enums::DecoderFlavor decoderFlavor() const
void addressTranslation(MMU::ArmTranslationType tran_type, BaseMMU::Mode mode, Request::Flags flags, RegVal val)
void initializeMiscRegMetadata()
const ArmRelease * release
This could be either a FS or a SE release.
RegVal readMiscReg(RegIndex idx) override
void handleLockedSnoopHit() override
std::unique_ptr< BaseISADevice > gicv3CpuInterface
unsigned getCurSmeVecLenInBits() const
TranslationGenPtr translateFunctional(Addr start, Addr size, ThreadContext *tc, Mode mode, Request::Flags flags) override
Returns a translation generator for a region of virtual addresses, instead of directly translating a ...
chain reset(uint64_t res_val) const
void serialize(CheckpointOut &cp) const override
Serialize an object.
BaseISA(const SimObjectParams &p, const std::string &name)
The ExecContext is an abstract base class the provides the interface used by the ISA to manipulate th...
virtual ThreadContext * tcBase() const =0
Returns a pointer to the ThreadContext.
virtual RegVal readMiscReg(int misc_reg)=0
Reads a miscellaneous register, handling any architectural side effects due to reading that register.
virtual void setMiscReg(int misc_reg, RegVal val)=0
Sets a miscellaneous register, handling any architectural side effects due to writing that register.
Gicv3CPUInterface * getCPUInterface(int cpu_id) const
virtual std::string name() const
bool isInvalidate() const
@ funcRequestorId
This requestor id is used for functional requests that don't come from a particular device.
gem5::Flags< FlagsType > Flags
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal getReg(const RegId ®) const
virtual BaseCPU * getCpuPtr()=0
virtual const PCStateBase & pcState() const =0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
virtual ContextID contextId() const =0
This module implements the global system counter and the local per-CPU architected timers as specifie...
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
virtual void startup()
startup() is the final initialization call before simulation.
RegAccessor::type readRegisterNoEffect(ThreadContext *tc, ExceptionLevel el)
bool ELIs32(ThreadContext *tc, ExceptionLevel el)
constexpr RegClass flatIntRegClass
static const uint32_t FpscrQcMask
bool ELIsInHost(ThreadContext *tc, ExceptionLevel el)
Returns true if the current exception level el is executing a Host OS or an application of a Host OS ...
bool isSecure(ThreadContext *tc)
static const uint32_t FpscrExcMask
void sendEvent(ThreadContext *tc)
Send an event (SEV) to a specific PE if there isn't already a pending event.
constexpr RegClass matRegClass
constexpr RegClass vecElemClass
static const uint32_t CpsrMaskQ
bool EL2Enabled(ThreadContext *tc)
void preUnflattenMiscReg()
gem5::MatStore< MaxSmeVecLenInBytes, MaxSmeVecLenInBytes > MatRegContainer
constexpr RegClass vecPredRegClass
constexpr RegClass ccRegClass
@ MISCREG_ID_AA64PFR0_EL1
@ MISCREG_ICC_IGRPEN1_EL3
@ MISCREG_ID_AA64DFR0_EL1
@ MISCREG_ID_AA64DFR1_EL1
@ MISCREG_ID_AA64ISAR1_EL1
@ MISCREG_ID_AA64MMFR1_EL1
@ MISCREG_CNTHPS_CVAL_EL2
@ MISCREG_CNTHPS_TVAL_EL2
@ MISCREG_ID_AA64MMFR0_EL1
@ MISCREG_CNTHVS_TVAL_EL2
@ MISCREG_CNTHVS_CVAL_EL2
@ MISCREG_ID_AA64MMFR2_EL1
@ MISCREG_ID_AA64AFR1_EL1
@ MISCREG_ID_AA64AFR0_EL1
@ MISCREG_ID_AA64ISAR0_EL1
@ MISCREG_CONTEXTIDR_EL12
@ MISCREG_PMXEVTYPER_PMCCFILTR
@ MISCREG_ID_AA64PFR1_EL1
gem5::VecRegContainer< NumVecElemPerVecReg *sizeof(VecElem)> VecRegContainer
int unflattenMiscReg(int reg)
static bool lockedWriteHandler(ThreadContext *tc, XC *xc, const RequestPtr &req, Addr cacheBlockMask)
static ExceptionLevel opModeToEL(OperatingMode mode)
constexpr RegClass miscRegClass
const char *const miscRegName[]
RegVal readMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
This helper function is either returing the value of MPIDR_EL1 (by calling getMPIDR),...
static void lockedSnoopHandler(ThreadContext *tc, XC *xc, PacketPtr pkt, Addr cacheBlockMask)
std::vector< struct MiscRegLUTEntry > lookUpMiscReg(NUM_MISCREGS)
constexpr RegClass vecRegClass
constexpr RegClass floatRegClass
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< FaultBase > Fault
std::shared_ptr< Request > RequestPtr
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
constexpr decltype(nullptr) NoFault
@ FloatRegClass
Floating-point register.
constexpr char FloatRegClassName[]
#define UNSERIALIZE_MAPPING(member, names, size)
#define SERIALIZE_MAPPING(member, names, size)