arch-arm: Define an ArmRelease class to handle ISA extensions

Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Change-Id: I3240853bd2123a6f24b2bb64c90ad457696f0d93
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/51010
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Giacomo Travaglini
2021-09-21 11:55:22 +01:00
parent 7756c5e908
commit 152760ee51
12 changed files with 147 additions and 184 deletions

View File

@@ -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(

View File

@@ -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")

View File

@@ -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;

View File

@@ -72,8 +72,8 @@ MMU::MMU(const ArmMMUParams &p)
if (FullSystem) {
ArmSystem *arm_sys = dynamic_cast<ArmSystem *>(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 {

View File

@@ -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)
{

View File

@@ -43,6 +43,7 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#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<ArmExtension, bool> _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<ArmSystem *>(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)
*/

View File

@@ -82,13 +82,13 @@ TableWalker::TableWalker(const Params &p)
// Cache system-level properties
if (FullSystem) {
ArmSystem *armSys = dynamic_cast<ArmSystem *>(p.sys);
assert(armSys);
haveSecurity = armSys->haveSecurity();
_haveLPAE = armSys->haveLPAE();
_haveVirtualization = armSys->haveVirtualization();
_physAddrRange = armSys->physAddrRange();
_haveLargeAsid64 = armSys->haveLargeAsid64();
ArmSystem *arm_sys = dynamic_cast<ArmSystem *>(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;

View File

@@ -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

View File

@@ -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')

View File

@@ -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

View File

@@ -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");

View File

@@ -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;