diff --git a/configs/example/arm/baremetal.py b/configs/example/arm/baremetal.py index 9a56c11650..9655bb165a 100644 --- a/configs/example/arm/baremetal.py +++ b/configs/example/arm/baremetal.py @@ -143,8 +143,8 @@ def create(args): system.realview.gic.gicv4 = False system.highest_el_is_64 = True - system.have_virtualization = True - system.have_security = True + system.release.add(ArmExtension('SECURITY')) + system.release.add(ArmExtension('VIRTUALIZATION')) workload_class = workloads.workload_list.get(args.workload) system.workload = workload_class( diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index 585df3bf73..6c42db0990 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -43,20 +43,72 @@ from m5.objects.ArmSemihosting import ArmSemihosting class SveVectorLength(UInt8): min = 1; max = 16 +class ArmExtension(ScopedEnum): + vals = [ + # Armv8.1 + 'FEAT_VHE', + 'FEAT_PAN', + 'FEAT_LSE', + + # Armv8.2 + 'FEAT_SVE', + + # Armv8.4 + 'FEAT_SEL2', + + # Others + 'SECURITY', + 'LPAE', + 'VIRTUALIZATION', + 'CRYPTO', + 'TME' + ] + +class ArmRelease(SimObject): + type = 'ArmRelease' + cxx_header = "arch/arm/system.hh" + cxx_class = 'gem5::ArmRelease' + + extensions = VectorParam.ArmExtension([], "ISA extensions") + + def add(self, new_ext: ArmExtension) -> None: + """ + Add the provided extension (ArmExtension) to the system + The method is discarding pre-existing values + """ + if (new_ext.value not in + [ ext.value for ext in self.extensions ]): + self.extensions.append(new_ext) + + def has(self, new_ext: ArmExtension) -> bool: + """ + Is the system implementing the provided extension (ArmExtension) ? + """ + if (new_ext.value not in + [ ext.value for ext in self.extensions ]): + return False + else: + return True + +class Armv8(ArmRelease): + extensions = [ + 'LPAE' + ] + +class ArmDefaultRelease(Armv8): + extensions = Armv8.extensions + [ + 'FEAT_SVE', 'FEAT_LSE', 'FEAT_PAN', 'FEAT_SEL2' + ] + class ArmSystem(System): type = 'ArmSystem' cxx_header = "arch/arm/system.hh" cxx_class = 'gem5::ArmSystem' + release = Param.ArmRelease(ArmDefaultRelease(), "Arm Release") + multi_proc = Param.Bool(True, "Multiprocessor system?") gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface") - have_security = Param.Bool(False, - "True if Security Extensions are implemented") - have_virtualization = Param.Bool(False, - "True if Virtualization Extensions are implemented") - have_crypto = Param.Bool(False, - "True if Crypto Extensions is implemented") - have_lpae = Param.Bool(True, "True if LPAE is implemented") reset_addr = Param.Addr(0x0, "Reset address (ARMv8)") auto_reset_addr = Param.Bool(True, @@ -68,20 +120,8 @@ class ArmSystem(System): "Supported physical address range in bits when using AArch64 (ARMv8)") have_large_asid_64 = Param.Bool(False, "True if ASID is 16 bits in AArch64 (ARMv8)") - have_sve = Param.Bool(True, - "True if SVE is implemented (ARMv8)") sve_vl = Param.SveVectorLength(1, "SVE vector length in quadwords (128-bit)") - have_lse = Param.Bool(True, - "True if LSE is implemented (ARMv8.1)") - have_vhe = Param.Bool(False, - "True if FEAT_VHE (Virtualization Host Extensions) is implemented") - have_pan = Param.Bool(True, - "True if Priviledge Access Never is implemented (ARMv8.1)") - have_secel2 = Param.Bool(True, - "True if Secure EL2 is implemented (ARMv8)") - have_tme = Param.Bool(False, - "True if transactional memory extension (TME) is implemented") semihosting = Param.ArmSemihosting(NULL, "Enable support for the Arm semihosting by settings this parameter") diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index f10697ab3f..57836bbf3e 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -106,19 +106,19 @@ ISA::ISA(const Params &p) : BaseISA(p), system(NULL), // Cache system-level properties if (FullSystem && system) { highestELIs64 = system->highestELIs64(); - haveSecurity = system->haveSecurity(); - haveLPAE = system->haveLPAE(); - haveCrypto = system->haveCrypto(); - haveVirtualization = system->haveVirtualization(); + haveSecurity = system->has(ArmExtension::SECURITY); + haveLPAE = system->has(ArmExtension::LPAE); + haveCrypto = system->has(ArmExtension::CRYPTO); + haveVirtualization = system->has(ArmExtension::VIRTUALIZATION); haveLargeAsid64 = system->haveLargeAsid64(); physAddrRange = system->physAddrRange(); - haveSVE = system->haveSVE(); - haveVHE = system->haveVHE(); - havePAN = system->havePAN(); - haveSecEL2 = system->haveSecEL2(); + haveSVE = system->has(ArmExtension::FEAT_SVE); + haveVHE = system->has(ArmExtension::FEAT_VHE); + havePAN = system->has(ArmExtension::FEAT_PAN); + haveSecEL2 = system->has(ArmExtension::FEAT_SEL2); sveVL = system->sveVL(); - haveLSE = system->haveLSE(); - haveTME = system->haveTME(); + haveLSE = system->has(ArmExtension::FEAT_LSE); + haveTME = system->has(ArmExtension::TME); } else { highestELIs64 = true; // ArmSystem::highestELIs64 does the same haveSecurity = haveLPAE = haveVirtualization = false; diff --git a/src/arch/arm/mmu.cc b/src/arch/arm/mmu.cc index b73945743f..52606b0737 100644 --- a/src/arch/arm/mmu.cc +++ b/src/arch/arm/mmu.cc @@ -72,8 +72,8 @@ MMU::MMU(const ArmMMUParams &p) if (FullSystem) { ArmSystem *arm_sys = dynamic_cast(p.sys); assert(arm_sys); - haveLPAE = arm_sys->haveLPAE(); - haveVirtualization = arm_sys->haveVirtualization(); + haveLPAE = arm_sys->has(ArmExtension::LPAE); + haveVirtualization = arm_sys->has(ArmExtension::VIRTUALIZATION); haveLargeAsid64 = arm_sys->haveLargeAsid64(); physAddrRange = arm_sys->physAddrRange(); } else { diff --git a/src/arch/arm/system.cc b/src/arch/arm/system.cc index f19978e76d..4edc35083b 100644 --- a/src/arch/arm/system.cc +++ b/src/arch/arm/system.cc @@ -50,6 +50,7 @@ #include "dev/arm/fvp_base_pwr_ctrl.hh" #include "dev/arm/gic_v2.hh" #include "mem/physical.hh" +#include "params/ArmRelease.hh" namespace gem5 { @@ -57,26 +58,28 @@ namespace gem5 using namespace linux; using namespace ArmISA; +ArmRelease::ArmRelease(const ArmReleaseParams &p) + : SimObject(p) +{ + for (auto ext : p.extensions) { + fatal_if(_extensions.find(ext) != _extensions.end(), + "Duplicated FEAT_\n"); + + _extensions[ext] = true; + } +} + ArmSystem::ArmSystem(const Params &p) : System(p), - _haveSecurity(p.have_security), - _haveLPAE(p.have_lpae), - _haveVirtualization(p.have_virtualization), - _haveCrypto(p.have_crypto), _genericTimer(nullptr), _gic(nullptr), _pwrCtrl(nullptr), _highestELIs64(p.highest_el_is_64), _physAddrRange64(p.phys_addr_range_64), _haveLargeAsid64(p.have_large_asid_64), - _haveTME(p.have_tme), - _haveSVE(p.have_sve), _sveVL(p.sve_vl), - _haveLSE(p.have_lse), - _haveVHE(p.have_vhe), - _havePAN(p.have_pan), - _haveSecEL2(p.have_secel2), semihosting(p.semihosting), + release(p.release), multiProc(p.multi_proc) { if (p.auto_reset_addr) { @@ -105,21 +108,9 @@ ArmSystem::ArmSystem(const Params &p) } bool -ArmSystem::haveSecurity(ThreadContext *tc) +ArmSystem::has(ArmExtension ext, ThreadContext *tc) { - return FullSystem? getArmSystem(tc)->haveSecurity() : false; -} - -bool -ArmSystem::haveLPAE(ThreadContext *tc) -{ - return FullSystem? getArmSystem(tc)->haveLPAE() : false; -} - -bool -ArmSystem::haveVirtualization(ThreadContext *tc) -{ - return FullSystem? getArmSystem(tc)->haveVirtualization() : false; + return FullSystem? getArmSystem(tc)->has(ext) : false; } bool @@ -142,21 +133,15 @@ ArmSystem::haveEL(ThreadContext *tc, ExceptionLevel el) case EL1: return true; case EL2: - return haveVirtualization(tc); + return has(ArmExtension::VIRTUALIZATION, tc); case EL3: - return haveSecurity(tc); + return has(ArmExtension::SECURITY, tc); default: warn("Unimplemented Exception Level\n"); return false; } } -bool -ArmSystem::haveTME(ThreadContext *tc) -{ - return getArmSystem(tc)->haveTME(); -} - Addr ArmSystem::resetAddr(ThreadContext *tc) { diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh index f2ec5c313e..03326b325d 100644 --- a/src/arch/arm/system.hh +++ b/src/arch/arm/system.hh @@ -43,6 +43,7 @@ #include #include +#include #include #include "kern/linux/events.hh" @@ -50,6 +51,8 @@ #include "sim/full_system.hh" #include "sim/sim_object.hh" #include "sim/system.hh" +#include "enums/ArmExtension.hh" + namespace gem5 { @@ -59,29 +62,34 @@ class BaseGic; class FVPBasePwrCtrl; class ThreadContext; +struct ArmReleaseParams; + +class ArmRelease : public SimObject +{ + public: + PARAMS(ArmRelease); + ArmRelease(const Params &p); + + bool + has(ArmExtension ext) const + { + if (auto it = _extensions.find(ext); it != _extensions.end()) { + return it->second; + } else { + return false; + } + } + + protected: + /** + * List of implemented extensions + */ + std::unordered_map _extensions; +}; + class ArmSystem : public System { protected: - /** - * True if this system implements the Security Extensions - */ - const bool _haveSecurity; - - /** - * True if this system implements the Large Physical Address Extension - */ - const bool _haveLPAE; - - /** - * True if this system implements the virtualization Extensions - */ - const bool _haveVirtualization; - - /** - * True if this system implements the Crypto Extension - */ - const bool _haveCrypto; - /** * Pointer to the Generic Timer wrapper. */ @@ -115,38 +123,20 @@ class ArmSystem : public System */ const bool _haveLargeAsid64; - /** - * True if system implements the transactional memory extension (TME) - */ - const bool _haveTME; - - /** - * True if SVE is implemented (ARMv8) - */ - const bool _haveSVE; - /** SVE vector length at reset, in quadwords */ const unsigned _sveVL; - /** - * True if LSE is implemented (ARMv8.1) - */ - const bool _haveLSE; - - /** True if FEAT_VHE (Virtualization Host Extensions) is implemented */ - const bool _haveVHE; - - /** True if Priviledge Access Never is implemented */ - const unsigned _havePAN; - - /** True if Secure EL2 is implemented */ - const unsigned _haveSecEL2; - /** * True if the Semihosting interface is enabled. */ ArmSemihosting *const semihosting; + /** + * Arm Release object: contains a list of implemented + * features + */ + const ArmRelease *release; + public: static constexpr Addr PageBytes = ArmISA::PageBytes; static constexpr Addr PageShift = ArmISA::PageShift; @@ -158,22 +148,9 @@ class ArmSystem : public System /** true if this a multiprocessor system */ bool multiProc; - /** Returns true if this system implements the Security Extensions */ - bool haveSecurity() const { return _haveSecurity; } + const ArmRelease* releaseFS() const { return release; } - /** Returns true if this system implements the Large Physical Address - * Extension */ - bool haveLPAE() const { return _haveLPAE; } - - /** Returns true if this system implements the virtualization - * Extensions - */ - bool haveVirtualization() const { return _haveVirtualization; } - - /** Returns true if this system implements the Crypto - * Extension - */ - bool haveCrypto() const { return _haveCrypto; } + bool has(ArmExtension ext) const { return release->has(ext); } /** Sets the pointer to the Generic Timer. */ void @@ -208,9 +185,9 @@ class ArmSystem : public System ArmISA::ExceptionLevel highestEL() const { - if (_haveSecurity) + if (has(ArmExtension::SECURITY)) return ArmISA::EL3; - if (_haveVirtualization) + if (has(ArmExtension::VIRTUALIZATION)) return ArmISA::EL2; return ArmISA::EL1; } @@ -223,29 +200,9 @@ class ArmSystem : public System /** Returns true if ASID is 16 bits in AArch64 (ARMv8) */ bool haveLargeAsid64() const { return _haveLargeAsid64; } - /** Returns true if this system implements the transactional - * memory extension (ARMv9) - */ - bool haveTME() const { return _haveTME; } - - /** Returns true if SVE is implemented (ARMv8) */ - bool haveSVE() const { return _haveSVE; } - /** Returns the SVE vector length at reset, in quadwords */ unsigned sveVL() const { return _sveVL; } - /** Returns true if LSE is implemented (ARMv8.1) */ - bool haveLSE() const { return _haveLSE; } - - /** Returns true if Virtualization Host Extensions is implemented */ - bool haveVHE() const { return _haveVHE; } - - /** Returns true if Priviledge Access Never is implemented */ - bool havePAN() const { return _havePAN; } - - /** Returns true if Priviledge Access Never is implemented */ - bool haveSecEL2() const { return _haveSecEL2; } - /** Returns the supported physical address range in bits if the highest * implemented exception level is 64 bits (ARMv8) */ uint8_t physAddrRange64() const { return _physAddrRange64; } @@ -256,7 +213,7 @@ class ArmSystem : public System { if (_highestELIs64) return _physAddrRange64; - if (_haveLPAE) + if (has(ArmExtension::LPAE)) return 40; return 32; } @@ -278,24 +235,8 @@ class ArmSystem : public System return static_cast(tc->getSystemPtr()); } - /** Returns true if the system of a specific thread context implements the - * Security Extensions - */ - static bool haveSecurity(ThreadContext *tc); + static bool has(ArmExtension ext, ThreadContext *tc); - /** Returns true if the system of a specific thread context implements the - * virtualization Extensions - */ - static bool haveVirtualization(ThreadContext *tc); - - /** Returns true if the system of a specific thread context implements the - * Large Physical Address Extension - */ - static bool haveLPAE(ThreadContext *tc); - - /** Returns true if the register width of the highest implemented exception - * level for the system of a specific thread context is 64 bits (ARMv8) - */ static bool highestELIs64(ThreadContext *tc); /** Returns the highest implemented exception level for the system of a @@ -306,11 +247,6 @@ class ArmSystem : public System /** Return true if the system implements a specific exception level */ static bool haveEL(ThreadContext *tc, ArmISA::ExceptionLevel el); - /** Returns true if the system of a specific thread context implements the - * transactional memory extension (TME) - */ - static bool haveTME(ThreadContext *tc); - /** Returns the reset address if the highest implemented exception level * for the system of a specific thread context is 64 bits (ARMv8) */ diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 4cc0fffb02..8604d6fa9d 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -82,13 +82,13 @@ TableWalker::TableWalker(const Params &p) // Cache system-level properties if (FullSystem) { - ArmSystem *armSys = dynamic_cast(p.sys); - assert(armSys); - haveSecurity = armSys->haveSecurity(); - _haveLPAE = armSys->haveLPAE(); - _haveVirtualization = armSys->haveVirtualization(); - _physAddrRange = armSys->physAddrRange(); - _haveLargeAsid64 = armSys->haveLargeAsid64(); + ArmSystem *arm_sys = dynamic_cast(p.sys); + assert(arm_sys); + haveSecurity = arm_sys->has(ArmExtension::SECURITY); + _haveLPAE = arm_sys->has(ArmExtension::LPAE); + _haveVirtualization = arm_sys->has(ArmExtension::VIRTUALIZATION); + _physAddrRange = arm_sys->physAddrRange(); + _haveLargeAsid64 = arm_sys->haveLargeAsid64(); } else { haveSecurity = _haveLPAE = _haveVirtualization = false; _haveLargeAsid64 = false; diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 2baf9c0207..520716ebfe 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -128,7 +128,7 @@ bool longDescFormatInUse(ThreadContext *tc) { TTBCR ttbcr = tc->readMiscReg(MISCREG_TTBCR); - return ArmSystem::haveLPAE(tc) && ttbcr.eae; + return ArmSystem::has(ArmExtension::LPAE, tc) && ttbcr.eae; } RegVal diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py index 919ff63623..0ba929b3b3 100644 --- a/src/dev/arm/RealView.py +++ b/src/dev/arm/RealView.py @@ -40,6 +40,7 @@ from m5.defines import buildEnv from m5.params import * from m5.proxy import * from m5.util.fdthelper import * +from m5.objects.ArmSystem import ArmExtension from m5.objects.ClockDomain import ClockDomain, SrcClockDomain from m5.objects.VoltageDomain import VoltageDomain from m5.objects.Device import \ @@ -1308,7 +1309,7 @@ Interrupts: system = self.system.unproxy(self) if system._have_psci: # PSCI functions exposed to the kernel - if not system.have_security: + if not system.release.has(ArmExtension('SECURITY')): raise AssertionError("PSCI requires EL3 (have_security)") psci_node = FdtNode('psci') diff --git a/src/dev/arm/generic_timer.cc b/src/dev/arm/generic_timer.cc index 52f41fe18d..1c1d811063 100644 --- a/src/dev/arm/generic_timer.cc +++ b/src/dev/arm/generic_timer.cc @@ -1285,7 +1285,7 @@ GenericTimerMem::validateFrameRange(const AddrRange &range) bool GenericTimerMem::validateAccessPerm(ArmSystem &sys, bool is_sec) { - return !sys.haveSecurity() || is_sec; + return !sys.has(ArmExtension::SECURITY) || is_sec; } AddrRangeList diff --git a/src/dev/arm/gic_v3_cpu_interface.cc b/src/dev/arm/gic_v3_cpu_interface.cc index f4cdfc13b8..4ae6b9bd2a 100644 --- a/src/dev/arm/gic_v3_cpu_interface.cc +++ b/src/dev/arm/gic_v3_cpu_interface.cc @@ -2333,7 +2333,7 @@ Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group) const bool Gicv3CPUInterface::inSecureState() const { - if (!gic->getSystem()->haveSecurity()) { + if (!gic->getSystem()->has(ArmExtension::SECURITY)) { return false; } @@ -2376,10 +2376,10 @@ Gicv3CPUInterface::haveEL(ExceptionLevel el) const return true; case EL2: - return gic->getSystem()->haveVirtualization(); + return gic->getSystem()->has(ArmExtension::VIRTUALIZATION); case EL3: - return gic->getSystem()->haveSecurity(); + return gic->getSystem()->has(ArmExtension::SECURITY); default: warn("Unimplemented Exception Level\n"); diff --git a/src/dev/arm/gic_v3_distributor.cc b/src/dev/arm/gic_v3_distributor.cc index a4124ae62a..75c3df5ecd 100644 --- a/src/dev/arm/gic_v3_distributor.cc +++ b/src/dev/arm/gic_v3_distributor.cc @@ -118,14 +118,15 @@ Gicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines) * ITLinesNumber [4:0] == N * (MaxSPIIntId = 32 (N + 1) - 1) */ + bool have_security = gic->getSystem()->has(ArmExtension::SECURITY); int max_spi_int_id = itLines - 1; int it_lines_number = divCeil(max_spi_int_id + 1, 32) - 1; gicdTyper = (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) | (1 << 17) | (1 << 16) | - ((gic->getSystem()->haveSecurity() ? 1 : 0) << 10) | + ((have_security ? 1 : 0) << 10) | (it_lines_number << 0); - if (gic->getSystem()->haveSecurity()) { + if (have_security) { DS = false; } else { DS = true;