We add the following registers which are added by SME: * ID_AA64SMFR0_EL1 * SVCR * SMIDR_EL1 * SMPRI_EL1 * SMPRIMAP_EL2 * SMCR_EL3 * SMCR_EL2 * SMCR_EL12 * SMCR_EL1 * TPIDR2_EL0 * MPAMSM_EL1 In addition we extend some of the existing registers with SME support (SCR_EL3, CPACR_EL1, CPTR_EL2, CPTR_EL3, etc). These regisers are responsible for enabling SME itself, or for configuring the trapping behaviour for the differernt ELs. In addition we implement some dummy registers as they are officially required by SME, but gem5 itself doesn't actually support the features yet (FGT, HCX). Jira Issue: https://gem5.atlassian.net/browse/GEM5-1289 Change-Id: I18ba65fb9ac2b7a4b4f361998564fb5d472d1789 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/64335 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
309 lines
9.5 KiB
C++
309 lines
9.5 KiB
C++
/*
|
|
* Copyright (c) 2010, 2012-2013, 2015-2022 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 <memory>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "arch/arm/page_size.hh"
|
|
#include "arch/arm/types.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<ArmExtension, bool> _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;
|
|
|
|
/** SME vector length at reset, in quadwords */
|
|
const unsigned _smeVL;
|
|
|
|
/**
|
|
* 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 SME vector length at reset, in quadwords */
|
|
unsigned smeVL() const { return _smeVL; }
|
|
|
|
/** 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<ArmSystem *>(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
|