/* * Copyright (c) 2010, 2012-2013, 2015-2021 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall * not be construed as granting a license to any other intellectual * property including but not limited to intellectual property relating * to a hardware implementation of the functionality of the software * licensed hereunder. You may use the software subject to the license * terms below provided that you ensure that this notice is replicated * unmodified and in its entirety in all distributions of the software, * modified or unmodified, in source code or in binary form. * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __ARCH_ARM_SYSTEM_HH__ #define __ARCH_ARM_SYSTEM_HH__ #include #include #include #include #include "arch/arm/page_size.hh" #include "kern/linux/events.hh" #include "params/ArmSystem.hh" #include "sim/full_system.hh" #include "sim/sim_object.hh" #include "sim/system.hh" #include "enums/ArmExtension.hh" namespace gem5 { class GenericTimer; 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: /** * Pointer to the Generic Timer wrapper. */ GenericTimer *_genericTimer; BaseGic *_gic; /** * Pointer to the Power Controller (if any) */ FVPBasePwrCtrl *_pwrCtrl; /** * Reset address (ARMv8) */ Addr _resetAddr; /** * True if the register width of the highest implemented exception level is * 64 bits (ARMv8) */ bool _highestELIs64; /** * Supported physical address range in bits if the highest implemented * exception level is 64 bits (ARMv8) */ const uint8_t _physAddrRange64; /** * True if ASID is 16 bits in AArch64 (ARMv8) */ const bool _haveLargeAsid64; /** SVE vector length at reset, in quadwords */ const unsigned _sveVL; /** * 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; PARAMS(ArmSystem); ArmSystem(const Params &p); /** true if this a multiprocessor system */ bool multiProc; const ArmRelease* releaseFS() const { return release; } bool has(ArmExtension ext) const { return release->has(ext); } /** Sets the pointer to the Generic Timer. */ void setGenericTimer(GenericTimer *generic_timer) { _genericTimer = generic_timer; } /** Sets the pointer to the GIC. */ void setGIC(BaseGic *gic) { _gic = gic; } /** Sets the pointer to the Power Controller */ void setPowerController(FVPBasePwrCtrl *pwr_ctrl) { _pwrCtrl = pwr_ctrl; } /** Get a pointer to the system's generic timer model */ GenericTimer *getGenericTimer() const { return _genericTimer; } /** Get a pointer to the system's GIC */ BaseGic *getGIC() const { return _gic; } /** Get a pointer to the system's power controller */ FVPBasePwrCtrl *getPowerController() const { return _pwrCtrl; } /** Returns true if the register width of the highest implemented exception * level is 64 bits (ARMv8) */ bool highestELIs64() const { return _highestELIs64; } /** Returns the highest implemented exception level */ ArmISA::ExceptionLevel highestEL() const { if (has(ArmExtension::SECURITY)) return ArmISA::EL3; if (has(ArmExtension::VIRTUALIZATION)) return ArmISA::EL2; return ArmISA::EL1; } /** Returns the reset address if the highest implemented exception level is * 64 bits (ARMv8) */ Addr resetAddr() const { return _resetAddr; } void setResetAddr(Addr addr) { _resetAddr = addr; } /** Returns true if ASID is 16 bits in AArch64 (ARMv8) */ bool haveLargeAsid64() const { return _haveLargeAsid64; } /** Returns the SVE vector length at reset, in quadwords */ unsigned sveVL() const { return _sveVL; } /** Returns the supported physical address range in bits if the highest * implemented exception level is 64 bits (ARMv8) */ uint8_t physAddrRange64() const { return _physAddrRange64; } /** Returns the supported physical address range in bits */ uint8_t physAddrRange() const { if (_highestELIs64) return _physAddrRange64; if (has(ArmExtension::LPAE)) return 40; return 32; } /** Returns the physical address mask */ Addr physAddrMask() const { return mask(physAddrRange()); } /** Is Arm Semihosting support enabled? */ bool haveSemihosting() const { return semihosting != nullptr; } /** * Returns a valid ArmSystem pointer if using ARM ISA, it fails * otherwise. */ static ArmSystem* getArmSystem(ThreadContext *tc) { assert(FullSystem); return static_cast(tc->getSystemPtr()); } static bool has(ArmExtension ext, ThreadContext *tc); static bool highestELIs64(ThreadContext *tc); /** Returns the highest implemented exception level for the system of a * specific thread context */ static ArmISA::ExceptionLevel highestEL(ThreadContext *tc); /** Return true if the system implements a specific exception level */ static bool haveEL(ThreadContext *tc, ArmISA::ExceptionLevel el); /** Returns the reset address if the highest implemented exception level * for the system of a specific thread context is 64 bits (ARMv8) */ static Addr resetAddr(ThreadContext *tc); /** Returns the supported physical address range in bits for the system of a * specific thread context */ static uint8_t physAddrRange(ThreadContext *tc); /** Returns the physical address mask for the system of a specific thread * context */ static Addr physAddrMask(ThreadContext *tc); /** Returns true if ASID is 16 bits for the system of a specific thread * context while in AArch64 (ARMv8) */ static bool haveLargeAsid64(ThreadContext *tc); /** Is Arm Semihosting support enabled? */ static bool haveSemihosting(ThreadContext *tc); /** Make a Semihosting call from aarch64 */ static bool callSemihosting64(ThreadContext *tc, bool gem5_ops=false); /** Make a Semihosting call from aarch32 */ static bool callSemihosting32(ThreadContext *tc, bool gem5_ops=false); /** Make a Semihosting call from either aarch64 or aarch32 */ static bool callSemihosting(ThreadContext *tc, bool gem5_ops=false); /** Make a call to notify the power controller of STANDBYWFI assertion */ static void callSetStandByWfi(ThreadContext *tc); /** Make a call to notify the power controller of STANDBYWFI deassertion */ static void callClearStandByWfi(ThreadContext *tc); /** * Notify the power controller of WAKEREQUEST assertion. Returns true * if WAKEREQUEST is enabled as a power-on mechanism, and the core is now * powered, false otherwise */ static bool callSetWakeRequest(ThreadContext *tc); /** Notify the power controller of WAKEREQUEST deassertion */ static void callClearWakeRequest(ThreadContext *tc); }; } // namespace gem5 #endif