diff --git a/components/MMU/MMUUtil.cpp b/components/MMU/MMUUtil.cpp index 24b3e2db..b5bc8eb2 100644 --- a/components/MMU/MMUUtil.cpp +++ b/components/MMU/MMUUtil.cpp @@ -38,22 +38,17 @@ TTEDescriptor::isBlockEntry() } void -fm_print_mmu_regs(mmu_regs_t* r) +fm_print_mmu_regs(mmu_regs_t* mmu_regs) { - DBG_(VVerb, - (<< "SCTLR_EL1: " << std::hex << r->SCTLR[EL1] << std::dec << std::endl - << "SCTLR_EL2: " << std::hex << r->SCTLR[EL2] << std::dec << std::endl - << "SCTLR_EL3: " << std::hex << r->SCTLR[EL3] << std::dec << std::endl - << "TCR_EL1: " << std::hex << r->TCR[EL1] << std::dec << std::endl - << "TCR_EL2: " << std::hex << r->TCR[EL2] << std::dec << std::endl - << "TCR_EL3: " << std::hex << r->TCR[EL3] << std::dec << std::endl - << "TTBR0_EL1: " << std::hex << r->TTBR0[EL1] << std::dec << std::endl - << "TTBR1_EL1: " << std::hex << r->TTBR1[EL1] << std::dec << std::endl - << "TTBR0_EL2: " << std::hex << r->TTBR0[EL2] << std::dec << std::endl - << "TTBR1_EL2: " << std::hex << r->TTBR1[EL2] << std::dec << std::endl - << "TTBR0_EL3: " << std::hex << r->TTBR0[EL3] << std::dec << std::endl - << "ID_AA64MMFR0_EL1: " << std::hex << r->ID_AA64MMFR0_EL1 << std::dec)); - ; + DBG_(VVerb, (<< "Initializing mmu registers from QEMU..." << std::endl + << std::hex + << "\t" << "TCR_EL1: " << mmu_regs.TCR[EL1] << std::endl + << "\t" << "SCTLR_El1: " << mmu_regs.SCTLR[EL1] << std::endl + << "\t" << "TTBR0_EL1: " << mmu_regs.TTBR0[EL1] << std::endl + << "\t" << "TTBR1_EL1: " << mmu_regs.TTBR1[EL1] << std::endl + << "\t" << "ID_AA64MMFR0_EL1: " << mmu_regs.ID_AA64MMFR0_EL1 + << std::dec + << std::endl)); } void mmu_t::setupBitConfigs() @@ -112,39 +107,31 @@ mmu_t::init_mmu_regs(std::size_t core_index) /** * Everything here is detailed in the chapter D7 * of the 2024 ARM Reference manual. (ARM DDI 0487K.a) + * + * Bryan Perdrizat + * EL2 and EL3 are not setted up because QFlex is not (yet) + * supporting well EL2 (hypervisor) mode well. */ //? sctlr_el0 does not exist mmu_regs.SCTLR[EL1] = cpu.read_register(Qemu::API::SCTLR, EL1); - mmu_regs.SCTLR[EL2] = cpu.read_register(Qemu::API::SCTLR, EL2); - mmu_regs.SCTLR[EL3] = cpu.read_register(Qemu::API::SCTLR, EL3); //? tcr_el0 does not exist mmu_regs.TCR[EL1] = cpu.read_register(Qemu::API::TCR, EL1); - mmu_regs.TCR[EL2] = cpu.read_register(Qemu::API::TCR, EL2); - mmu_regs.TCR[EL3] = cpu.read_register(Qemu::API::TCR, EL3); //? Section G8.2.167 - TTBR0, Translation Table Base Register 0 //? Section G8.2.168 - TTBR1, Translation Table Base Register 1 mmu_regs.TTBR0[EL1] = cpu.read_register(Qemu::API::TTBR0, EL1); mmu_regs.TTBR1[EL1] = cpu.read_register(Qemu::API::TTBR1, EL1); - mmu_regs.TTBR0[EL2] = cpu.read_register(Qemu::API::TTBR0, EL2); - mmu_regs.TTBR1[EL2] = cpu.read_register(Qemu::API::TTBR1, EL2); - mmu_regs.TTBR0[EL3] = cpu.read_register(Qemu::API::TTBR0, EL3); //? Section D23.2.74 - AArch64 Memory Model Feature Register 0 mmu_regs.ID_AA64MMFR0_EL1 = cpu.read_register(Qemu::API::ID_AA64MMFR0, EL1); - DBG_(VVerb, (<< "Initializing mmu registers from QEMU...." << mmu_regs.TCR[EL1])); + fm_print_mmu_regs(mmu_regs); + return (mmu_regs.TCR[EL1] != 0); } -bool -mmu_t::IsExcLevelEnabled(uint8_t EL) const -{ - DBG_Assert(EL > 0 && EL <= 3, (<< "ERROR, ARM MMU: Transl. Request Not Supported at Invalid EL = " << EL)); - return extractSingleBitAsBool(mmu_regs.SCTLR[EL], aarch64_bit_configs.M_Bit); -} void mmu_t::setupAddressSpaceSizesAndGranules(void) { diff --git a/components/MMU/pageWalk.cpp b/components/MMU/pageWalk.cpp index 72b0e174..09203188 100644 --- a/components/MMU/pageWalk.cpp +++ b/components/MMU/pageWalk.cpp @@ -256,6 +256,14 @@ PageWalk::InitialTranslationSetup(TranslationTransport& aTranslation) uint8_t EL = statefulPointer->ELRegime; + + /** + * Bryan Perdrizat + * EL2 and EL3 are not setted up because QFlex is not (yet) + * supporting well EL2 (hypervisor) mode well. + */ + DBG_Assert(EL <= 1); + // Handle a case where for Linux, the page table of EL0 is in EL1's register. if (EL == 0) { DBG_Assert(statefulPointer->isBR0); diff --git a/components/uArch/CoreModel/construct.cpp b/components/uArch/CoreModel/construct.cpp index 84422529..7c3209af 100644 --- a/components/uArch/CoreModel/construct.cpp +++ b/components/uArch/CoreModel/construct.cpp @@ -441,24 +441,28 @@ void CoreImpl::setSP_el(uint8_t anId, uint64_t aVal) { DBG_Assert(0 <= anId && anId < 4, (<< "Out of bound access with index = " << anId)); + DBG_Assert(anId < 2, (<< "Unhandled simulation of hypervisor mode")); theSP_el[anId] = aVal; } uint64_t CoreImpl::getSP_el(uint8_t anId) { DBG_Assert(0 <= anId && anId < 4, (<< "Out of bound access with index = " << anId)); + DBG_Assert(anId < 2, (<< "Unhandled simulation of hypervisor mode")); return theSP_el[anId]; } void CoreImpl::setSPSR_el(uint8_t anId, uint64_t aVal) { DBG_Assert(0 <= anId && anId < 4, (<< "Out of bound access with index = " << anId)); + DBG_Assert(anId < 2, (<< "Unhandled simulation of hypervisor mode")); theSPSR_EL[anId] = aVal; } uint64_t CoreImpl::getSPSR_el(uint8_t anId) { DBG_Assert(0 <= anId && anId < 4, (<< "Out of bound access with index = " << anId)); + DBG_Assert(anId < 2, (<< "Unhandled simulation of hypervisor mode")); return theSPSR_EL[anId]; } uint32_t @@ -514,6 +518,7 @@ CoreImpl::setSCTLR_EL(uint8_t anId, uint64_t aSCTLR_EL) uint64_t CoreImpl::getSCTLR_EL(uint8_t anId) { + DBG_Assert(anId < 2, (<< "Unhandled simulation of hypervisor mode")); return theSCTLR_EL[anId]; } void @@ -524,7 +529,7 @@ CoreImpl::setHCREL2(uint64_t aHCREL2) uint64_t CoreImpl::getHCREL2() { - return theHCR_EL2; + DBG_Assert(false, (<< "Unhandled simulation of hypervisor mode")); } void CoreImpl::setException(Flexus::Qemu::API::exception_t anEXP) diff --git a/components/uArch/systemRegister.cpp b/components/uArch/systemRegister.cpp index 062c5433..63e0848b 100644 --- a/components/uArch/systemRegister.cpp +++ b/components/uArch/systemRegister.cpp @@ -135,41 +135,6 @@ class TPIDR_EL0_ : public SysRegInfo } }; -class TPIDR_EL2_ : public SysRegInfo -{ - public: - std::string name = "TPIDR_EL2"; - static const eRegExecutionState state = kARM_STATE_AA64; - static const uint8_t opc0 = 3; - static const uint8_t opc1 = 4; - static const uint8_t opc2 = 2; - static const uint8_t crn = 13; - static const uint8_t crm = 0; - static const eAccessRight access = kPL0_RW; - static const eRegInfo type = kARM_NO_RAW; - uint64_t resetvalue = -1; - - virtual eAccessResult accessfn(uArch* aCore) override - { - if (aCore->currentEL() <= 2) { return kACCESS_TRAP_EL2; } - return kACCESS_OK; // access OK since we assume the access right is EL0_RW - } // FIXME /*aa64_daif_access*/ - virtual void writefn(uArch* aCore, uint64_t aVal) override {} - virtual uint64_t readfn(uArch* aCore) override { return aCore->getTPIDR(2); } - TPIDR_EL2_() - : SysRegInfo("TPIDR_EL2_", - TPIDR_EL2_::state, - TPIDR_EL2_::type, - TPIDR_EL2_::opc0, - TPIDR_EL2_::opc1, - TPIDR_EL2_::opc2, - TPIDR_EL2_::crn, - TPIDR_EL2_::crm, - TPIDR_EL2_::access) - { - } -}; - class FPCR_ : public SysRegInfo { public: @@ -348,30 +313,6 @@ class CURRENT_EL_ : public SysRegInfo } }; -class ELR_EL2_ : public SysRegInfo -{ - public: - static const eRegExecutionState state = kARM_STATE_AA64; - static const uint8_t opc0 = 3; - static const uint8_t opc1 = 4; - static const uint8_t opc2 = 1; - static const uint8_t crn = 4; - static const uint8_t crm = 0; - static const eAccessRight access = kPL1_RW; - static const eRegInfo type = kARM_ALIAS; - ELR_EL2_() - : SysRegInfo("ELR_EL2", - ELR_EL2_::state, - ELR_EL2_::type, - ELR_EL2_::opc0, - ELR_EL2_::opc1, - ELR_EL2_::opc2, - ELR_EL2_::crn, - ELR_EL2_::crm, - ELR_EL2_::access) - { - } -}; class ELR_EL1_ : public SysRegInfo { public: @@ -386,71 +327,21 @@ class ELR_EL1_ : public SysRegInfo virtual uint64_t readfn(uArch* aCore) override { - // if PSTATE.EL == EL0 then - // UNDEFINED; - // elsif PSTATE.EL == EL1 then - // if EL2Enabled() && HCR_EL2. == '011' then - // AArch64.SystemAccessTrap(EL2, 0x18); - // elsif EL2Enabled() && HCR_EL2. == '111' then - // return NVMem[0x230]; - // else - // return ELR_EL1; - // elsif PSTATE.EL == EL2 then - // if HCR_EL2.E2H == '1' then - // return ELR_EL2; - // else - // return ELR_EL1; - // elsif PSTATE.EL == EL3 then - // return ELR_EL1; auto currentel = aCore->_PSTATE().EL(); - auto HCR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(0, 3, 4, 0, 1, 1, false); - auto HCR_EL2_E2H = extract64(HCR_EL2, 34, 1); - - if (currentel == 1 || currentel == 3) return aCore->getELR_el(1); - if (currentel == 2) { - if (HCR_EL2_E2H == 1) - return aCore->getELR_el(2); - else - return aCore->getELR_el(1); - } - - return aCore->getELR_el(1); + DBG_Assert(currentel == 1, (<< "EL must be EL1")); + return aCore->getELR_el(currentel); } virtual void writefn(uArch* aCore, uint64_t aVal) override { auto currentel = aCore->_PSTATE().EL(); - auto HCR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(0, 3, 4, 0, 1, 1, false); - auto HCR_EL2_E2H = extract64(HCR_EL2, 34, 1); - - if (currentel == 1 || currentel == 3) aCore->setELR_el(1, aVal); - if (currentel == 2) { - if (HCR_EL2_E2H == 1) - aCore->setELR_el(2, aVal); - else - aCore->setELR_el(1, aVal); - } + DBG_Assert(currentel == 1, (<< "EL must be EL1")); + + aCore->setELR_el(currentel, aVal); } virtual void sync(uArch* aCore, size_t theNode) override { - auto currentel = aCore->_PSTATE().EL(); - auto HCR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(0, 3, 4, 0, 1, 1, true); - auto HCR_EL2_E2H = extract64(HCR_EL2, 34, 1); auto valELR_EL1 = Flexus::Qemu::API::qemu_api.read_sys_register(theNode, opc0, opc1, opc2, crn, crm, true); - auto valELR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(theNode, - ELR_EL2_::opc0, - ELR_EL2_::opc1, - ELR_EL2_::opc2, - ELR_EL2_::crn, - ELR_EL2_::crm, - true); - - if (currentel == 1 || currentel == 3) writefn(aCore, valELR_EL1); - if (currentel == 2) { - if (HCR_EL2_E2H == 1) - writefn(aCore, valELR_EL2); - else - writefn(aCore, valELR_EL1); - } + aCore->setELR_el(1, valELR_EL1); } ELR_EL1_() : SysRegInfo("ELR_EL1", @@ -465,32 +356,7 @@ class ELR_EL1_ : public SysRegInfo { } }; -class SPSR_EL2_ : public SysRegInfo -{ - public: - static const eRegExecutionState state = kARM_STATE_AA64; - static const uint8_t opc0 = 3; - static const uint8_t opc1 = 4; - static const uint8_t opc2 = 0; - static const uint8_t crn = 4; - static const uint8_t crm = 0; - static const eAccessRight access = kPL1_RW; - static const eRegInfo type = kARM_ALIAS; - uint64_t resetvalue = -1; - SPSR_EL2_() - : SysRegInfo("SPSR_EL2", - SPSR_EL2_::state, - SPSR_EL2_::type, - SPSR_EL2_::opc0, - SPSR_EL2_::opc1, - SPSR_EL2_::opc2, - SPSR_EL2_::crn, - SPSR_EL2_::crm, - SPSR_EL2_::access) - { - } -}; class SPSR_EL1_ : public SysRegInfo { public: @@ -506,82 +372,24 @@ class SPSR_EL1_ : public SysRegInfo virtual uint64_t readfn(uArch* aCore) override { - // if PSTATE.EL == EL0 then - // UNDEFINED; - // elsif PSTATE.EL == EL1 then - // if EffectiveHCR_EL2_NVx() == '011' then - // AArch64.SystemAccessTrap(EL2, 0x18); - // elsif EffectiveHCR_EL2_NVx() IN {'111'} then - // X[t, 64] = NVMem[0x160]; - // else - // X[t, 64] = SPSR_EL1; - // elsif PSTATE.EL == EL2 then - // if ELIsInHost(EL2) then - // X[t, 64] = SPSR_EL2; - // else - // X[t, 64] = SPSR_EL1; - // elsif PSTATE.EL == EL3 then - // X[t, 64] = SPSR_EL1; - // - // boolean ELIsInHost(bits(2) el) - // ... - // when EL2 - // return EL2Enabled() && HCR_EL2.E2H == '1'; - // ... - // - // boolean EL2Enabled() - // return HaveEL(EL2) && (!HaveEL(EL3) || SCR_GEN[].NS == '1' || IsSecureEL2Enabled()); - auto currentel = aCore->_PSTATE().EL(); - auto HCR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(0, 3, 4, 0, 1, 1, false); - auto HCR_EL2_E2H = extract64(HCR_EL2, 34, 1); - - if (currentel == 1 || currentel == 3) return aCore->getSPSR_el(1); - if (currentel == 2) { - if (HCR_EL2_E2H == 1) - return aCore->getSPSR_el(2); - else - return aCore->getSPSR_el(1); - } + DBG_Assert(currentel == 1, (<< "EL must be EL1")); return aCore->getSPSR_el(1); } virtual void writefn(uArch* aCore, uint64_t aVal) override { auto currentel = aCore->_PSTATE().EL(); - auto HCR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(0, 3, 4, 0, 1, 1, false); - auto HCR_EL2_E2H = extract64(HCR_EL2, 34, 1); - - if (currentel == 1 || currentel == 3) return aCore->setSPSR_el(1, aVal); - if (currentel == 2) { - if (HCR_EL2_E2H == 1) - return aCore->setSPSR_el(2, aVal); - else - return aCore->setSPSR_el(1, aVal); - } + DBG_Assert(currentel == 1, (<< "EL must be EL1")); + return aCore->setSPSR_el(1, aVal); + } virtual void sync(uArch* aCore, size_t theNode) override { - auto currentel = aCore->_PSTATE().EL(); - auto HCR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(0, 3, 4, 0, 1, 1, true); - auto HCR_EL2_E2H = extract64(HCR_EL2, 34, 1); auto valSPSR_EL1 = Flexus::Qemu::API::qemu_api.read_sys_register(theNode, opc0, opc1, opc2, crn, crm, true); - auto valSPSR_EL2 = Flexus::Qemu::API::qemu_api.read_sys_register(theNode, - SPSR_EL2_::opc0, - SPSR_EL2_::opc1, - SPSR_EL2_::opc2, - SPSR_EL2_::crn, - SPSR_EL2_::crm, - true); - - if (currentel == 1 || currentel == 3) writefn(aCore, valSPSR_EL1); - if (currentel == 2) { - if (HCR_EL2_E2H == 1) - writefn(aCore, valSPSR_EL2); - else - writefn(aCore, valSPSR_EL1); - } + + aCore->setSPSR_el(1, valSPSR_EL1); } SPSR_EL1_() @@ -859,9 +667,6 @@ std::vector, ePrivRegs>> supported_sysRegs = { std::make_pair, ePrivRegs>( { TPIDR_EL0_::opc0, TPIDR_EL0_::opc1, TPIDR_EL0_::opc2, TPIDR_EL0_::crn, TPIDR_EL0_::crm }, kTPIDR_EL0), - std::make_pair, ePrivRegs>( - { TPIDR_EL2_::opc0, TPIDR_EL2_::opc1, TPIDR_EL2_::opc2, TPIDR_EL2_::crn, TPIDR_EL2_::crm }, - kTPIDR_EL2), std::make_pair, ePrivRegs>({ FPCR_::opc0, FPCR_::opc1, FPCR_::opc2, FPCR_::crn, FPCR_::crm }, kFPCR), std::make_pair, ePrivRegs>({ FPSR_::opc0, FPSR_::opc1, FPSR_::opc2, FPSR_::crn, FPSR_::crm }, @@ -935,7 +740,6 @@ getPriv(ePrivRegs aCode) case kSPSR_UND: return std::make_unique(); case kSPSR_FIQ: return std::make_unique(); case kTPIDR_EL0: return std::make_unique(); - case kTPIDR_EL2: return std::make_unique(); default: // FIXME: Only return default/abstract if implemented by QEMU return std::make_unique(); // DBG_Assert(false, (<< "Unimplemented SysReg Code" << aCode)); diff --git a/components/uArch/uArchInterfaces.hpp b/components/uArch/uArchInterfaces.hpp index 96601b2a..d4e97fdb 100644 --- a/components/uArch/uArchInterfaces.hpp +++ b/components/uArch/uArchInterfaces.hpp @@ -191,7 +191,6 @@ enum ePrivRegs kSPSR_UND, kSPSR_FIQ, kTPIDR_EL0, - kTPIDR_EL2, kAbstractSysReg, /* Msutherl: Blanket type for all registers to represent as hashed/encoded 5-tuple which are then read through QEMU */ kLastPrivReg