arch-arm: Properly implement IPASpace in the MMU (#1313)

This PR is introducing the concept of IPA space in gem5, which is
necessary after the implementation
of FEAT_SEL2. In fact we can now have Secure and Non-Secure intermediate
physical address spaces when the PE is
executing in Secure state.
This commit is contained in:
Giacomo Travaglini
2024-07-03 08:20:53 +01:00
committed by GitHub
17 changed files with 605 additions and 466 deletions

View File

@@ -411,12 +411,13 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
TLBIALL tlbiOp(TranslationRegime::EL10, secure);
TLBIALL tlbiOp(TranslationRegime::EL10, ss);
if (shareable) {
tlbiOp.broadcast(tc);
} else {
@@ -429,8 +430,9 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIALL tlbiOp(TranslationRegime::EL10, secure);
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIALL tlbiOp(TranslationRegime::EL10, ss);
tlbiOp.broadcast(tc);
return;
}
@@ -440,12 +442,13 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
ITLBIALL tlbiOp(TranslationRegime::EL10, secure);
ITLBIALL tlbiOp(TranslationRegime::EL10, ss);
if (shareable) {
tlbiOp.broadcast(tc);
} else {
@@ -459,12 +462,13 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
DTLBIALL tlbiOp(TranslationRegime::EL10, secure);
DTLBIALL tlbiOp(TranslationRegime::EL10, ss);
if (shareable) {
tlbiOp.broadcast(tc);
} else {
@@ -478,13 +482,14 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
TLBIMVA tlbiOp(TranslationRegime::EL10,
secure,
ss,
mbits(value, 31, 12),
bits(value, 7, 0),
false);
@@ -502,13 +507,14 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
TLBIMVA tlbiOp(TranslationRegime::EL10,
secure,
ss,
mbits(value, 31, 12),
bits(value, 7, 0),
true);
@@ -525,9 +531,10 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVA tlbiOp(TranslationRegime::EL10,
secure,
ss,
mbits(value, 31, 12),
bits(value, 7, 0),
false);
@@ -540,9 +547,10 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVA tlbiOp(TranslationRegime::EL10,
secure,
ss,
mbits(value, 31, 12),
bits(value, 7, 0),
true);
@@ -556,13 +564,14 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
TLBIASID tlbiOp(TranslationRegime::EL10,
secure,
ss,
bits(value, 7, 0));
if (shareable) {
@@ -577,9 +586,10 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIASID tlbiOp(TranslationRegime::EL10,
secure,
ss,
bits(value, 7, 0));
tlbiOp.broadcast(tc);
@@ -591,11 +601,12 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
TLBIMVAA tlbiOp(TranslationRegime::EL10, secure,
TLBIMVAA tlbiOp(TranslationRegime::EL10, ss,
mbits(value, 31, 12), false);
if (shareable) {
@@ -611,12 +622,13 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
TLBIMVAA tlbiOp(TranslationRegime::EL10, secure,
TLBIMVAA tlbiOp(TranslationRegime::EL10, ss,
mbits(value, 31, 12), true);
if (shareable) {
@@ -631,8 +643,9 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIMVAA tlbiOp(TranslationRegime::EL10, secure,
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVAA tlbiOp(TranslationRegime::EL10, ss,
mbits(value, 31, 12), false);
tlbiOp.broadcast(tc);
@@ -643,8 +656,9 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIMVAA tlbiOp(TranslationRegime::EL10, secure,
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVAA tlbiOp(TranslationRegime::EL10, ss,
mbits(value, 31, 12), true);
tlbiOp.broadcast(tc);
@@ -655,8 +669,9 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIMVAA tlbiOp(TranslationRegime::EL2, secure,
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVAA tlbiOp(TranslationRegime::EL2, ss,
mbits(value, 31, 12), false);
tlbiOp(tc);
@@ -667,8 +682,9 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIMVAA tlbiOp(TranslationRegime::EL2, secure,
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVAA tlbiOp(TranslationRegime::EL2, ss,
mbits(value, 31, 12), true);
tlbiOp(tc);
@@ -679,8 +695,9 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIMVAA tlbiOp(TranslationRegime::EL2, secure,
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVAA tlbiOp(TranslationRegime::EL2, ss,
mbits(value, 31, 12), false);
tlbiOp.broadcast(tc);
@@ -691,8 +708,9 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIMVAA tlbiOp(TranslationRegime::EL2, secure,
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIMVAA tlbiOp(TranslationRegime::EL2, ss,
mbits(value, 31, 12), true);
tlbiOp.broadcast(tc);
@@ -703,9 +721,10 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIIPA tlbiOp(TranslationRegime::EL10,
secure,
ss,
static_cast<Addr>(bits(value, 35, 0)) << 12,
false);
@@ -718,9 +737,10 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIIPA tlbiOp(TranslationRegime::EL10,
secure,
ss,
static_cast<Addr>(bits(value, 35, 0)) << 12,
true);
@@ -733,9 +753,10 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIIPA tlbiOp(TranslationRegime::EL10,
secure,
ss,
static_cast<Addr>(bits(value, 35, 0)) << 12,
false);
@@ -748,9 +769,10 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
TLBIIPA tlbiOp(TranslationRegime::EL10,
secure,
ss,
static_cast<Addr>(bits(value, 35, 0)) << 12,
true);
@@ -763,12 +785,14 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
ITLBIMVA tlbiOp(TranslationRegime::EL10,
secure,
ss,
mbits(value, 31, 12),
bits(value, 7, 0));
@@ -785,13 +809,14 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
DTLBIMVA tlbiOp(TranslationRegime::EL10,
secure,
ss,
mbits(value, 31, 12),
bits(value, 7, 0));
@@ -808,13 +833,14 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
ITLBIASID tlbiOp(TranslationRegime::EL10,
secure,
ss,
bits(value, 7, 0));
if (shareable) {
@@ -830,13 +856,14 @@ TlbiOp::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) const
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
auto ss = release->has(ArmExtension::SECURITY) && !scr.ns ?
SecurityState::Secure : SecurityState::NonSecure;
// Check for Force Broadcast. Ignored if HCR_EL2.TGE == 1
bool shareable = currEL(tc) == EL1 && EL2Enabled(tc) &&
hcr.fb && !hcr.tge;
DTLBIASID tlbiOp(TranslationRegime::EL10,
secure,
ss,
bits(value, 7, 0));
if (shareable) {

File diff suppressed because it is too large Load Diff

View File

@@ -292,40 +292,40 @@ class TlbiOp64 : public MiscRegRegImmOp64
static std::unordered_map<ArmISA::MiscRegIndex, TlbiFunc> tlbiOps;
static void tlbiAll(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, TlbiAttr attrs=TlbiAttr::None);
static void tlbiVmall(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
bool stage2=false, TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, bool stage2=false, TlbiAttr attrs=TlbiAttr::None);
static void tlbiVa(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
bool last_level, TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, bool last_level, TlbiAttr attrs=TlbiAttr::None);
static void tlbiVaa(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
bool last_level, TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, bool last_level, TlbiAttr attrs=TlbiAttr::None);
static void tlbiAsid(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, TlbiAttr attrs=TlbiAttr::None);
static void tlbiIpaS2(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
bool last_level, TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, bool last_level, TlbiAttr attrs=TlbiAttr::None);
static void tlbiRvaa(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
bool last_level, TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, bool last_level, TlbiAttr attrs=TlbiAttr::None);
static void tlbiRva(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
bool last_level, TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, bool last_level, TlbiAttr attrs=TlbiAttr::None);
static void tlbiRipaS2(ThreadContext *tc, RegVal value,
bool secure, ArmISA::TranslationRegime regime, bool shareable,
bool last_level, TlbiAttr attrs=TlbiAttr::None);
ArmISA::SecurityState ss, ArmISA::TranslationRegime regime,
bool shareable, bool last_level, TlbiAttr attrs=TlbiAttr::None);
static bool fnxsAttrs(ThreadContext *tc);

View File

@@ -179,7 +179,7 @@ MMU::translateFunctional(ThreadContext *tc, Addr va, Addr &pa)
lookup_data.asn = state.asid;
lookup_data.ignoreAsn = false;
lookup_data.vmid = state.vmid;
lookup_data.secure = state.isSecure;
lookup_data.ss = state.securityState;
lookup_data.functional = true;
lookup_data.targetRegime = state.currRegime;
lookup_data.mode = BaseMMU::Read;
@@ -459,7 +459,8 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode,
(ap == 3 && state.sctlr.uwxn && is_priv);
if (is_fetch && (abt || xn ||
(te->longDescFormat && te->pxn && is_priv) ||
(state.isSecure && te->ns && state.scr.sif))) {
(state.securityState == SecurityState::Secure &&
te->ns && state.scr.sif))) {
stats.permsFaults++;
DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. AP:%d "
"priv:%d write:%d ns:%d sif:%d sctlr.afe: %d \n",
@@ -615,7 +616,8 @@ MMU::s2PermBits64(TlbEntry *te, const RequestPtr &req, Mode mode,
uint8_t xn = te->xn;
uint8_t pxn = te->pxn;
if (ArmSystem::haveEL(tc, EL3) && state.isSecure &&
if (ArmSystem::haveEL(tc, EL3) &&
state.securityState == SecurityState::Secure &&
te->ns && state.scr.sif) {
xn = true;
}
@@ -705,7 +707,8 @@ MMU::s1PermBits64(TlbEntry *te, const RequestPtr &req, Mode mode,
// if wxn is set
grant_exec = grant_exec && !(wxn && grant_write);
if (ArmSystem::haveEL(tc, EL3) && state.isSecure && te->ns) {
if (ArmSystem::haveEL(tc, EL3) &&
state.securityState == SecurityState::Secure && te->ns) {
grant_exec = grant_exec && !state.scr.sif;
}
@@ -811,7 +814,7 @@ MMU::translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode,
req->setPaddr(vaddr);
// When the MMU is off the security attribute corresponds to the
// security state of the processor
if (state.isSecure)
if (state.securityState == SecurityState::Secure)
req->setFlags(Request::SECURE);
else
req->clearFlags(Request::SECURE);
@@ -846,8 +849,9 @@ MMU::translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode,
}
// Set memory attributes
bool in_secure_state = state.securityState == SecurityState::Secure;
TlbEntry temp_te;
temp_te.ns = !state.isSecure;
temp_te.ns = !in_secure_state;
bool dc = (HaveExt(tc, ArmExtension::FEAT_VHE) &&
state.hcr.e2h == 1 && state.hcr.tge == 1) ? 0: state.hcr.dc;
bool i_cacheability = state.sctlr.i && !state.sctlr.m;
@@ -916,7 +920,7 @@ MMU::translateMmuOn(ThreadContext* tc, const RequestPtr &req, Mode mode,
Addr pa = te->pAddr(vaddr);
req->setPaddr(pa);
if (state.isSecure && !te->ns) {
if (state.securityState == SecurityState::Secure && !te->ns) {
req->setFlags(Request::SECURE);
} else {
req->clearFlags(Request::SECURE);
@@ -969,7 +973,8 @@ MMU::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
DPRINTF(TLBVerbose,
"CPSR is priv:%d UserMode:%d secure:%d S1S2NsTran:%d\n",
state.isPriv, flags & UserMode, state.isSecure,
state.isPriv, flags & UserMode,
state.securityState == SecurityState::Secure,
tran_type & S1S2NsTran);
DPRINTF(TLB, "translateFs addr %#x, mode %d, st2 %d, scr %#x sctlr %#x "
@@ -1214,8 +1219,9 @@ MMU::CachedState::updateMiscReg(ThreadContext *tc,
scr = tc->readMiscReg(MISCREG_SCR_EL3);
// Dependencies: SCR/SCR_EL3, CPSR
isSecure = ArmISA::isSecure(tc) &&
!(tran_type & HypMode) && !(tran_type & S1S2NsTran);
securityState = ArmISA::isSecure(tc) &&
!(tran_type & HypMode) && !(tran_type & S1S2NsTran) ?
SecurityState::Secure : SecurityState::NonSecure;
exceptionLevel = tranTypeEL(cpsr, scr, tran_type);
currRegime = translationRegime(tc, exceptionLevel);
@@ -1296,27 +1302,27 @@ MMU::CachedState::updateMiscReg(ThreadContext *tc,
}
} else { // AArch32
sctlr = tc->readMiscReg(snsBankedIndex(MISCREG_SCTLR, tc,
!isSecure));
securityState == SecurityState::NonSecure));
ttbcr = tc->readMiscReg(snsBankedIndex(MISCREG_TTBCR, tc,
!isSecure));
securityState == SecurityState::NonSecure));
isPriv = cpsr.mode != MODE_USER;
if (longDescFormatInUse(tc)) {
uint64_t ttbr_asid = tc->readMiscReg(
snsBankedIndex(ttbcr.a1 ? MISCREG_TTBR1 :
MISCREG_TTBR0,
tc, !isSecure));
snsBankedIndex(ttbcr.a1 ? MISCREG_TTBR1 : MISCREG_TTBR0,
tc, securityState == SecurityState::NonSecure));
asid = bits(ttbr_asid, 55, 48);
} else { // Short-descriptor translation table format in use
CONTEXTIDR context_id = tc->readMiscReg(snsBankedIndex(
MISCREG_CONTEXTIDR, tc,!isSecure));
MISCREG_CONTEXTIDR, tc,
securityState == SecurityState::NonSecure));
asid = context_id.asid;
}
prrr = tc->readMiscReg(snsBankedIndex(MISCREG_PRRR, tc,
!isSecure));
securityState == SecurityState::NonSecure));
nmrr = tc->readMiscReg(snsBankedIndex(MISCREG_NMRR, tc,
!isSecure));
securityState == SecurityState::NonSecure));
dacr = tc->readMiscReg(snsBankedIndex(MISCREG_DACR, tc,
!isSecure));
securityState == SecurityState::NonSecure));
if (mmu->release()->has(ArmExtension::VIRTUALIZATION)) {
vmid = bits(tc->readMiscReg(MISCREG_VTTBR), 55, 48);
@@ -1379,15 +1385,15 @@ MMU::tranTypeEL(CPSR cpsr, SCR scr, ArmTranslationType type)
Fault
MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
Translation *translation, bool timing, bool functional,
bool is_secure, ArmTranslationType tran_type,
SecurityState ss, PASpace ipaspace, ArmTranslationType tran_type,
bool stage2)
{
return getTE(te, req, tc, mode, translation, timing, functional,
is_secure, tran_type, stage2 ? s2State : s1State);
ss, ipaspace, tran_type, stage2 ? s2State : s1State);
}
TlbEntry*
MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, bool secure,
MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, SecurityState ss,
bool functional, bool ignore_asn, TranslationRegime regime,
bool stage2, BaseMMU::Mode mode)
{
@@ -1399,7 +1405,7 @@ MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, bool secure,
lookup_data.asn = asid;
lookup_data.ignoreAsn = ignore_asn;
lookup_data.vmid = vmid;
lookup_data.secure = secure;
lookup_data.ss = ss;
lookup_data.functional = functional;
lookup_data.targetRegime = regime;
lookup_data.mode = mode;
@@ -1410,7 +1416,7 @@ MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, bool secure,
Fault
MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
Translation *translation, bool timing, bool functional,
bool is_secure, ArmTranslationType tran_type,
SecurityState ss, PASpace ipaspace, ArmTranslationType tran_type,
CachedState& state)
{
// In a 2-stage system, the IPA->PA translation can be started via this
@@ -1430,7 +1436,7 @@ MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
vaddr = vaddr_tainted;
}
*te = lookup(vaddr, state.asid, state.vmid, is_secure, false,
*te = lookup(vaddr, state.asid, state.vmid, ss, false,
false, regime, state.isStage2, mode);
if (!isCompleteTranslation(*te)) {
@@ -1452,15 +1458,15 @@ MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
Fault fault;
fault = getTableWalker(mode, state.isStage2)->walk(
req, tc, state.asid, state.vmid, mode,
translation, timing, functional, is_secure,
tran_type, state.stage2DescReq, *te);
translation, timing, functional, ss,
ipaspace, tran_type, state.stage2DescReq, *te);
// for timing mode, return and wait for table walk,
if (timing || fault != NoFault) {
return fault;
}
*te = lookup(vaddr, state.asid, state.vmid, is_secure,
*te = lookup(vaddr, state.asid, state.vmid, ss,
true, false, regime, state.isStage2, mode);
assert(*te);
}
@@ -1476,12 +1482,16 @@ MMU::getResultTe(TlbEntry **te, const RequestPtr &req,
Fault fault;
if (state.isStage2) {
PASpace ipaspace = state.securityState == SecurityState::Secure ?
PASpace::Secure : PASpace::NonSecure;
// We are already in the stage 2 TLB. Grab the table entry for stage
// 2 only. We are here because stage 1 translation is disabled.
TlbEntry *s2_te = nullptr;
// Get the stage 2 table entry
fault = getTE(&s2_te, req, tc, mode, translation, timing, functional,
state.isSecure, state.curTranType, state);
state.securityState, ipaspace,
state.curTranType, state);
// Check permissions of stage 2
if (isCompleteTranslation(s2_te) && (fault == NoFault)) {
if (state.aarch64)
@@ -1499,7 +1509,8 @@ MMU::getResultTe(TlbEntry **te, const RequestPtr &req,
// Get the stage 1 table entry
fault = getTE(&s1_te, req, tc, mode, translation, timing, functional,
state.isSecure, state.curTranType, state);
state.securityState, PASpace::NonSecure,
state.curTranType, state);
// only proceed if we have a valid table entry
if (isCompleteTranslation(s1_te) && (fault == NoFault)) {
// Check stage 1 permissions before checking stage 2
@@ -1509,8 +1520,8 @@ MMU::getResultTe(TlbEntry **te, const RequestPtr &req,
fault = checkPermissions(s1_te, req, mode, state);
if (state.stage2Req & (fault == NoFault)) {
Stage2LookUp *s2_lookup = new Stage2LookUp(this, *s1_te,
req, translation, mode, timing, functional, state.isSecure,
state.curTranType);
req, translation, mode, timing, functional,
state.securityState, state.curTranType);
fault = s2_lookup->getTe(tc, mergeTe);
if (s2_lookup->isComplete()) {
*te = mergeTe;

View File

@@ -149,7 +149,7 @@ class MMU : public BaseMMU
sctlr = rhs.sctlr;
scr = rhs.scr;
isPriv = rhs.isPriv;
isSecure = rhs.isSecure;
securityState = rhs.securityState;
ttbcr = rhs.ttbcr;
asid = rhs.asid;
vmid = rhs.vmid;
@@ -184,7 +184,7 @@ class MMU : public BaseMMU
SCTLR sctlr = 0;
SCR scr = 0;
bool isPriv = false;
bool isSecure = false;
SecurityState securityState = SecurityState::NonSecure;
TTBCR ttbcr = 0;
uint16_t asid = 0;
vmid_t vmid = 0;
@@ -306,7 +306,7 @@ class MMU : public BaseMMU
}
if (tlbi_op.stage2Flush()) {
flushStage2(tlbi_op.makeStage2());
flushStage2(tlbi_op);
}
}
@@ -397,7 +397,7 @@ class MMU : public BaseMMU
* @param vpn virtual address
* @param asn context id/address space id to use
* @param vmid The virtual machine ID used for stage 2 translation
* @param secure if the lookup is secure
* @param ss security state of the PE
* @param functional if the lookup should modify state
* @param ignore_asn if on lookup asn should be ignored
* @param target_regime selecting the translation regime
@@ -405,19 +405,21 @@ class MMU : public BaseMMU
* @return pointer to TLB entry if it exists
*/
TlbEntry *lookup(Addr vpn, uint16_t asn, vmid_t vmid,
bool secure, bool functional,
SecurityState ss, bool functional,
bool ignore_asn, TranslationRegime target_regime,
bool stage2, BaseMMU::Mode mode);
Fault getTE(TlbEntry **te, const RequestPtr &req,
ThreadContext *tc, Mode mode,
Translation *translation, bool timing, bool functional,
bool is_secure, ArmTranslationType tran_type,
SecurityState ss, PASpace ipaspace,
ArmTranslationType tran_type,
bool stage2);
Fault getTE(TlbEntry **te, const RequestPtr &req,
ThreadContext *tc, Mode mode,
Translation *translation, bool timing, bool functional,
bool is_secure, ArmTranslationType tran_type,
SecurityState ss, PASpace ipaspace,
ArmTranslationType tran_type,
CachedState &state);
Fault getResultTe(TlbEntry **te, const RequestPtr &req,

View File

@@ -199,7 +199,7 @@ struct TlbEntry : public Serializable
// The virtual machine ID used for stage 2 translation
vmid_t vmid = 0;
// if the lookup is secure
bool secure = false;
SecurityState ss = SecurityState::NonSecure;
// if the lookup should modify state
bool functional = false;
// selecting the translation regime
@@ -239,8 +239,10 @@ struct TlbEntry : public Serializable
// True if the entry targets the non-secure physical address space
bool ns;
// True if the entry was brought in from a non-secure page table
bool nstid;
// Security state of the translation regime
SecurityState ss;
// IPA Space (stage2 entries only)
PASpace ipaSpace;
// Translation regime on insert, AARCH64 EL0&1, AARCH32 -> el=1
TranslationRegime regime;
// This is used to distinguish between instruction and data entries
@@ -271,7 +273,9 @@ struct TlbEntry : public Serializable
innerAttrs(0), outerAttrs(0), ap(read_only ? 0x3 : 0), hap(0x3),
domain(DomainType::Client), mtype(MemoryType::StronglyOrdered),
longDescFormat(false), global(false), valid(true),
ns(true), nstid(true), regime(TranslationRegime::EL10),
ns(true), ss(SecurityState::NonSecure),
ipaSpace(PASpace::NonSecure),
regime(TranslationRegime::EL10),
type(TypeTLB::unified), partial(false),
nonCacheable(uncacheable),
shareable(false), outerShareable(false), xn(0), pxn(0),
@@ -290,7 +294,9 @@ struct TlbEntry : public Serializable
innerAttrs(0), outerAttrs(0), ap(0), hap(0x3),
domain(DomainType::Client), mtype(MemoryType::StronglyOrdered),
longDescFormat(false), global(false), valid(false),
ns(true), nstid(true), regime(TranslationRegime::EL10),
ns(true), ss(SecurityState::NonSecure),
ipaSpace(PASpace::NonSecure),
regime(TranslationRegime::EL10),
type(TypeTLB::unified), partial(false), nonCacheable(false),
shareable(false), outerShareable(false), xn(0), pxn(0),
xs(true)
@@ -330,8 +336,7 @@ struct TlbEntry : public Serializable
match(const Lookup &lookup) const
{
bool match = false;
if (valid && matchAddress(lookup) &&
(lookup.secure == !nstid))
if (valid && matchAddress(lookup) && lookup.ss == ss)
{
match = checkRegime(lookup.targetRegime);
@@ -410,8 +415,8 @@ struct TlbEntry : public Serializable
print() const
{
return csprintf("%#x, asn %d vmn %d ppn %#x size: %#x ap:%d "
"ns:%d nstid:%d g:%d xs: %d regime:%s", vpn << N, asid, vmid,
pfn << N, size, ap, ns, nstid, global,
"ns:%d ss:%s g:%d xs: %d regime:%s", vpn << N, asid, vmid,
pfn << N, size, ap, ns, ss, global,
xs, regimeToStr(regime));
}
@@ -428,7 +433,7 @@ struct TlbEntry : public Serializable
SERIALIZE_SCALAR(global);
SERIALIZE_SCALAR(valid);
SERIALIZE_SCALAR(ns);
SERIALIZE_SCALAR(nstid);
SERIALIZE_ENUM(ss);
SERIALIZE_ENUM(type);
SERIALIZE_SCALAR(nonCacheable);
SERIALIZE_ENUM(lookupLevel);
@@ -458,7 +463,7 @@ struct TlbEntry : public Serializable
UNSERIALIZE_SCALAR(global);
UNSERIALIZE_SCALAR(valid);
UNSERIALIZE_SCALAR(ns);
UNSERIALIZE_SCALAR(nstid);
UNSERIALIZE_ENUM(ss);
UNSERIALIZE_ENUM(type);
UNSERIALIZE_SCALAR(nonCacheable);
UNSERIALIZE_ENUM(lookupLevel);

View File

@@ -655,6 +655,10 @@ namespace ArmISA
Bitfield<19> vs; // Only defined for VTCR_EL2
Bitfield<21> ha; // Only defined for VTCR_EL2
Bitfield<22> hd; // Only defined for VTCR_EL2
Bitfield<29> nsw; // Only defined for VTCR_EL2
Bitfield<29> sw; // Only defined for VSTCR_EL2
Bitfield<30> nsa; // Only defined for VTCR_EL2
Bitfield<30> sa; // Only defined for VSTCR_EL2
EndBitUnion(VTCR_t)
BitUnion32(PRRR)

View File

@@ -57,7 +57,7 @@ Fault
Stage2LookUp::getTe(ThreadContext *tc, TlbEntry *destTe)
{
fault = mmu->getTE(&stage2Te, req, tc, mode, this, timing,
functional, secure, tranType, true);
functional, ss, ipaSpace, tranType, true);
// Call finish if we're done already
if ((fault != NoFault) || (stage2Te != NULL)) {
@@ -193,7 +193,7 @@ Stage2LookUp::finish(const Fault &_fault, const RequestPtr &req,
if ((fault == NoFault) && (stage2Te == NULL)) {
// OLD_LOOK: stage2Tlb
fault = mmu->getTE(&stage2Te, req, tc, mode, this,
timing, functional, secure, tranType, true);
timing, functional, ss, ipaSpace, tranType, true);
}
// Now we have the stage 2 table entry we need to merge it with the stage

View File

@@ -72,16 +72,19 @@ class Stage2LookUp : public BaseMMU::Translation
Fault fault;
bool complete;
bool selfDelete;
bool secure;
SecurityState ss;
PASpace ipaSpace;
public:
Stage2LookUp(MMU *_mmu, TlbEntry s1_te, const RequestPtr &_req,
MMU::Translation *_transState, BaseMMU::Mode _mode, bool _timing,
bool _functional, bool _secure, MMU::ArmTranslationType _tranType) :
mmu(_mmu), stage1Te(s1_te), s1Req(_req),
bool _functional, SecurityState _ss,
MMU::ArmTranslationType _tranType)
: mmu(_mmu), stage1Te(s1_te), s1Req(_req),
transState(_transState), mode(_mode), timing(_timing),
functional(_functional), tranType(_tranType), stage2Te(nullptr),
fault(NoFault), complete(false), selfDelete(false), secure(_secure)
fault(NoFault), complete(false), selfDelete(false), ss(_ss),
ipaSpace(s1_te.ns ? PASpace::NonSecure : PASpace::Secure)
{
req = std::make_shared<Request>();
req->setVirt(s1_te.pAddr(s1Req->getVaddr()), s1Req->getSize(),

View File

@@ -131,7 +131,7 @@ TableWalker::WalkerState::WalkerState() :
vaddr(0), vaddr_tainted(0),
sctlr(0), scr(0), cpsr(0), tcr(0),
htcr(0), hcr(0), vtcr(0),
isWrite(false), isFetch(false), isSecure(false),
isWrite(false), isFetch(false), ss(SecurityState::NonSecure),
isUncacheable(false), longDescData(std::nullopt),
hpd(false), sh(0), irgn(0), orgn(0), stage2Req(false),
stage2Tran(nullptr), timing(false), functional(false),
@@ -295,7 +295,8 @@ Fault
TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
vmid_t _vmid, MMU::Mode _mode,
MMU::Translation *_trans, bool _timing, bool _functional,
bool secure, MMU::ArmTranslationType tranType,
SecurityState ss, PASpace ipaspace,
MMU::ArmTranslationType tranType,
bool _stage2Req, const TlbEntry *walk_entry)
{
assert(!(_functional && _timing));
@@ -344,6 +345,7 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
if (isStage2) {
currState->regime = TranslationRegime::EL10;
currState->aarch64 = ELIs64(_tc, EL2);
currState->ipaSpace = ipaspace;
} else {
currState->regime =
translationRegime(_tc, currState->el);
@@ -364,8 +366,8 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
currState->functional = _functional;
currState->mode = _mode;
currState->tranType = tranType;
currState->isSecure = secure;
currState->secureLookup = secure;
currState->ss = ss;
currState->secureLookup = currState->ss == SecurityState::Secure;
currState->physAddrRange = _physAddrRange;
/** @todo These should be cached or grabbed from cached copies in
@@ -382,7 +384,8 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
currState->hcr = currState->tc->readMiscReg(MISCREG_HCR_EL2);
if (isStage2) {
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
if (currState->secureLookup) {
if (currState->ss == SecurityState::Secure &&
currState->ipaSpace == PASpace::Secure) {
currState->vtcr =
currState->tc->readMiscReg(MISCREG_VSTCR_EL2);
} else {
@@ -411,9 +414,11 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
}
} else {
currState->sctlr = currState->tc->readMiscReg(snsBankedIndex(
MISCREG_SCTLR, currState->tc, !currState->isSecure));
MISCREG_SCTLR, currState->tc,
currState->ss == SecurityState::NonSecure));
currState->ttbcr = currState->tc->readMiscReg(snsBankedIndex(
MISCREG_TTBCR, currState->tc, !currState->isSecure));
MISCREG_TTBCR, currState->tc,
currState->ss == SecurityState::NonSecure));
currState->htcr = currState->tc->readMiscReg(MISCREG_HTCR);
currState->hcr = currState->tc->readMiscReg(MISCREG_HCR);
currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR);
@@ -504,7 +509,7 @@ TableWalker::processWalkWrapper()
// Check if a previous walk filled this request already
// @TODO Should this always be the TLB or should we look in the stage2 TLB?
TlbEntry* te = mmu->lookup(currState->vaddr, currState->asid,
currState->vmid, currState->isSecure, true, false,
currState->vmid, currState->ss, true, false,
currState->regime, isStage2, currState->mode);
// Check if we still need to have a walk for this request. If the requesting
@@ -585,7 +590,7 @@ TableWalker::processWalkWrapper()
if (pendingQueue.size()) {
currState = pendingQueue.front();
te = mmu->lookup(currState->vaddr, currState->asid,
currState->vmid, currState->isSecure, true,
currState->vmid, currState->ss, true,
false, currState->regime, isStage2, currState->mode);
} else {
// Terminate the loop, nothing more to do
@@ -607,7 +612,8 @@ TableWalker::processWalk()
// For short descriptors, translation configs are held in
// TTBR1.
RegVal ttbr1 = currState->tc->readMiscReg(snsBankedIndex(
MISCREG_TTBR1, currState->tc, !currState->isSecure));
MISCREG_TTBR1, currState->tc,
currState->ss == SecurityState::NonSecure));
const auto irgn0_mask = 0x1;
const auto irgn1_mask = 0x40;
@@ -644,7 +650,8 @@ TableWalker::processWalk()
ArmFault::VmsaTran);
}
ttbr = currState->tc->readMiscReg(snsBankedIndex(
MISCREG_TTBR0, currState->tc, !currState->isSecure));
MISCREG_TTBR0, currState->tc,
currState->ss == SecurityState::NonSecure));
} else {
DPRINTF(TLB, " - Selecting TTBR1\n");
// Check if table walk is allowed when Security Extensions are enabled
@@ -670,7 +677,7 @@ TableWalker::processWalk()
Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) |
(bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2);
DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr,
currState->isSecure ? "s" : "ns");
currState->ss == SecurityState::Secure ? "s" : "ns");
Request::Flags flag = Request::PT_WALK;
if (uncacheableWalk()) {
@@ -762,7 +769,8 @@ TableWalker::processWalkLPAE()
ArmFault::LpaeTran);
}
ttbr = currState->tc->readMiscReg(snsBankedIndex(
MISCREG_TTBR0, currState->tc, !currState->isSecure));
MISCREG_TTBR0, currState->tc,
currState->ss == SecurityState::NonSecure));
tsz = currState->ttbcr.t0sz;
currState->isUncacheable = currState->ttbcr.irgn0 == 0;
if (ttbr0_max < (1ULL << 30)) // Upper limit < 1 GiB
@@ -787,7 +795,8 @@ TableWalker::processWalkLPAE()
ArmFault::LpaeTran);
}
ttbr = currState->tc->readMiscReg(snsBankedIndex(
MISCREG_TTBR1, currState->tc, !currState->isSecure));
MISCREG_TTBR1, currState->tc,
currState->ss == SecurityState::NonSecure));
tsz = currState->ttbcr.t1sz;
currState->isUncacheable = currState->ttbcr.irgn1 == 0;
// Lower limit >= 3 GiB
@@ -818,14 +827,16 @@ TableWalker::processWalkLPAE()
desc_addr = mbits(ttbr, 39, n) |
(bits(currState->vaddr, n + 26, 30) << 3);
DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
desc_addr, currState->isSecure ? "s" : "ns");
desc_addr, currState->ss == SecurityState::Secure ?
"s" : "ns");
} else {
// Skip first-level lookup
n = (tsz >= 2 ? 14 - tsz : 12);
desc_addr = mbits(ttbr, 39, n) |
(bits(currState->vaddr, n + 17, 21) << 3);
DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
desc_addr, currState->isSecure ? "s" : "ns");
desc_addr, currState->ss == SecurityState::Secure ?
"s" : "ns");
}
if (uncacheableWalk()) {
@@ -835,6 +846,7 @@ TableWalker::processWalkLPAE()
currState->longDesc.lookupLevel = start_lookup_level;
currState->longDesc.aarch64 = false;
currState->longDesc.grainSize = Grain4KB;
currState->longDesc.isStage2 = isStage2;
fetchDescriptor(
desc_addr, currState->longDesc,
@@ -896,12 +908,19 @@ TableWalker::processWalkAArch64()
switch (currState->regime) {
case TranslationRegime::EL10:
if (isStage2) {
if (currState->secureLookup) {
if (currState->ss == SecurityState::Secure &&
currState->ipaSpace == PASpace::Secure) {
// Secure EL1&0 Secure IPA
DPRINTF(TLB, " - Selecting VSTTBR_EL2 (AArch64 stage 2)\n");
ttbr = currState->tc->readMiscReg(MISCREG_VSTTBR_EL2);
currState->secureLookup = !currState->vtcr.sw;
} else {
// Secure EL1&0 NonSecure IPA or NonSecure EL1&0
DPRINTF(TLB, " - Selecting VTTBR_EL2 (AArch64 stage 2)\n");
ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2);
currState->secureLookup = currState->ss == SecurityState::Secure ?
!currState->vtcr.nsw : // Secure EL1&0 NonSecure IPA
false; // NonSecure EL1&0
}
tsz = 64 - currState->vtcr.t0sz64;
tg = GrainMap_tg0[currState->vtcr.tg0];
@@ -1087,6 +1106,7 @@ TableWalker::processWalkAArch64()
currState->longDesc.aarch64 = true;
currState->longDesc.grainSize = tg;
currState->longDesc.physAddrRange = _physAddrRange;
currState->longDesc.isStage2 = isStage2;
fetchDescriptor(desc_addr, currState->longDesc,
sizeof(uint64_t), flag, start_lookup_level,
@@ -1227,9 +1247,9 @@ TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
} else {
assert(tc);
PRRR prrr = tc->readMiscReg(snsBankedIndex(MISCREG_PRRR,
currState->tc, !currState->isSecure));
currState->tc, currState->ss == SecurityState::NonSecure));
NMRR nmrr = tc->readMiscReg(snsBankedIndex(MISCREG_NMRR,
currState->tc, !currState->isSecure));
currState->tc, currState->ss == SecurityState::NonSecure));
DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
switch(bits(texcb, 2,0)) {
@@ -1391,7 +1411,7 @@ TableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
// value of SCTLR.TRE
MiscRegIndex reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0;
int reg_as_int = snsBankedIndex(reg, currState->tc,
!currState->isSecure);
currState->ss == SecurityState::NonSecure);
uint32_t mair = currState->tc->readMiscReg(reg_as_int);
attr = (mair >> (8 * (attrIndx % 4))) & 0xff;
uint8_t attr_7_4 = bits(attr, 7, 4);
@@ -1674,7 +1694,8 @@ TableWalker::doL1Descriptor()
l2desc_addr = currState->l1Desc.l2Addr() |
(bits(currState->vaddr, 19, 12) << 2);
DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n",
l2desc_addr, currState->isSecure ? "s" : "ns");
l2desc_addr, currState->ss == SecurityState::Secure ?
"s" : "ns");
Request::Flags flag = Request::PT_WALK;
@@ -1798,8 +1819,10 @@ TableWalker::doLongDescriptor()
case LongDescriptor::Table:
{
// Set hierarchical permission flags
currState->secureLookup = currState->secureLookup &&
currState->longDesc.secureTable();
if (!isStage2) {
currState->secureLookup = currState->secureLookup &&
currState->longDesc.secureTable();
}
currState->longDescData->rwTable =
currState->longDescData->rwTable &&
(currState->longDesc.rwTable() || currState->hpd);
@@ -2234,7 +2257,8 @@ TableWalker::insertPartialTableEntry(LongDescriptor &descriptor)
te.domain = descriptor.domain();
te.lookupLevel = descriptor.lookupLevel;
te.ns = !descriptor.secure(have_security, currState);
te.nstid = !currState->isSecure;
te.ss = currState->ss;
te.ipaSpace = currState->ipaSpace; // Used by stage2 entries only
te.type = TypeTLB::unified;
te.regime = currState->regime;
@@ -2280,7 +2304,8 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool long_descriptor)
te.domain = descriptor.domain();
te.lookupLevel = descriptor.lookupLevel;
te.ns = !descriptor.secure(have_security, currState);
te.nstid = !currState->isSecure;
te.ss = currState->ss;
te.ipaSpace = currState->ipaSpace; // Used by stage2 entries only
te.xn = descriptor.xn();
te.type = currState->mode == BaseMMU::Execute ?
TypeTLB::instruction : TypeTLB::data;
@@ -2379,7 +2404,8 @@ TableWalker::testWalk(const RequestPtr &walk_req, TlbEntry::DomainType domain,
if (!test) {
return NoFault;
} else {
return test->walkCheck(walk_req, currState->vaddr, currState->isSecure,
return test->walkCheck(walk_req, currState->vaddr,
currState->ss == SecurityState::Secure,
currState->el != EL0,
currState->mode, domain, lookup_level);
}

View File

@@ -436,7 +436,7 @@ class TableWalker : public ClockedObject
LongDescriptor()
: data(0), _dirty(false), aarch64(false), grainSize(Grain4KB),
physAddrRange(0)
physAddrRange(0), isStage2(false)
{}
/** The raw bits of the entry */
@@ -454,6 +454,8 @@ class TableWalker : public ClockedObject
uint8_t physAddrRange;
bool isStage2;
uint8_t*
getRawPtr() override
{
@@ -491,8 +493,13 @@ class TableWalker : public ClockedObject
secure(bool have_security, WalkerState *currState) const override
{
if (type() == Block || type() == Page) {
return have_security &&
(currState->secureLookup && !bits(data, 5));
if (isStage2) {
return have_security && currState->secureLookup &&
!currState->vtcr.nsa;
} else {
return have_security &&
(currState->secureLookup && !bits(data, 5));
}
} else {
return have_security && currState->secureLookup;
}
@@ -662,8 +669,9 @@ class TableWalker : public ClockedObject
global(WalkerState *currState) const override
{
assert(currState && (type() == Block || type() == Page));
if (!currState->aarch64 && (currState->isSecure &&
!currState->secureLookup)) {
const bool secure_state = currState->ss == SecurityState::Secure;
if (!currState->aarch64 && secure_state &&
!currState->secureLookup) {
return false; // ARM ARM issue C B3.6.3
} else if (currState->aarch64) {
if (!MMU::hasUnprivRegime(currState->regime)) {
@@ -671,7 +679,7 @@ class TableWalker : public ClockedObject
// in AArch64 for regimes without an unpriviledged
// component
return true;
} else if (currState->isSecure && !currState->secureLookup) {
} else if (secure_state && !currState->secureLookup) {
return false;
}
}
@@ -896,13 +904,18 @@ class TableWalker : public ClockedObject
/** If the access is a fetch (for execution, and no-exec) must be checked?*/
bool isFetch;
/** If the access comes from the secure state. */
bool isSecure;
/** Security State of the access */
SecurityState ss;
/** Whether lookups should be treated as using the secure state.
* This is usually the same as isSecure, but can be set to false by the
* long descriptor table attributes. */
bool secureLookup = false;
/** IPA space (Secure vs NonSecure); stage2 only.
* This depends on whether the stage1 translation targeted
* a secure or non-secure IPA space */
PASpace ipaSpace;
/** True if table walks are uncacheable (for table descriptors) */
bool isUncacheable;
@@ -1139,7 +1152,8 @@ class TableWalker : public ClockedObject
Fault walk(const RequestPtr &req, ThreadContext *tc,
uint16_t asid, vmid_t _vmid,
BaseMMU::Mode mode, BaseMMU::Translation *_trans,
bool timing, bool functional, bool secure,
bool timing, bool functional, SecurityState ss,
PASpace ipaspace,
MMU::ArmTranslationType tran_type, bool stage2,
const TlbEntry *walk_entry);

View File

@@ -160,15 +160,16 @@ TLB::lookup(const Lookup &lookup_data)
TlbEntry *retval = match(lookup_data);
DPRINTF(TLBVerbose, "Lookup %#x, asn %#x -> %s vmn 0x%x secure %d "
"ppn %#x size: %#x pa: %#x ap:%d ns:%d nstid:%d g:%d asid: %d "
DPRINTF(TLBVerbose, "Lookup %#x, asn %#x -> %s vmn 0x%x ss %s "
"ppn %#x size: %#x pa: %#x ap:%d ns:%d ss:%s g:%d asid: %d "
"xs: %d regime: %s\n",
lookup_data.va, lookup_data.asn, retval ? "hit" : "miss",
lookup_data.vmid, lookup_data.secure,
lookup_data.vmid, lookup_data.ss,
retval ? retval->pfn : 0, retval ? retval->size : 0,
retval ? retval->pAddr(lookup_data.va) : 0,
retval ? retval->ap : 0,
retval ? retval->ns : 0, retval ? retval->nstid : 0,
retval ? retval->ns : 0,
retval ? retval->ss : SecurityState::NonSecure,
retval ? retval->global : 0, retval ? retval->asid : 0,
retval ? retval->xs : 0,
retval ? regimeToStr(retval->regime) : "None");
@@ -243,19 +244,19 @@ TLB::insert(TlbEntry &entry)
{
DPRINTF(TLB, "Inserting entry into TLB with pfn:%#x size:%#x vpn: %#x"
" asid:%d vmid:%d N:%d global:%d valid:%d nc:%d xn:%d"
" ap:%#x domain:%#x ns:%d nstid:%d, xs:%d regime: %s\n", entry.pfn,
" ap:%#x domain:%#x ns:%d ss:%s xs:%d regime: %s\n", entry.pfn,
entry.size, entry.vpn, entry.asid, entry.vmid, entry.N,
entry.global, entry.valid, entry.nonCacheable, entry.xn,
entry.ap, static_cast<uint8_t>(entry.domain), entry.ns,
entry.nstid, entry.xs, regimeToStr(entry.regime));
entry.ss, entry.xs, regimeToStr(entry.regime));
if (table[size - 1].valid)
DPRINTF(TLB, " - Replacing Valid entry %#x, asn %d vmn %d ppn %#x "
"size: %#x ap:%d ns:%d nstid:%d g:%d xs:%d regime: %s\n",
"size: %#x ap:%d ns:%d ss:%s g:%d xs:%d regime: %s\n",
table[size-1].vpn << table[size-1].N, table[size-1].asid,
table[size-1].vmid, table[size-1].pfn << table[size-1].N,
table[size-1].size, table[size-1].ap, table[size-1].ns,
table[size-1].nstid, table[size-1].global,
table[size-1].ss, table[size-1].global,
table[size-1].xs, regimeToStr(table[size-1].regime));
// inserting to MRU position and evicting the LRU one

View File

@@ -69,7 +69,7 @@ TLBIALL::operator()(ThreadContext* tc)
bool
TLBIALL::matchEntry(TlbEntry* te, vmid_t vmid) const
{
return te->valid && secureLookup == !te->nstid &&
return te->valid && ss == te->ss &&
(te->vmid == vmid || el2Enabled) &&
te->checkRegime(targetRegime);
}
@@ -115,7 +115,7 @@ TLBIALLEL::operator()(ThreadContext* tc)
bool
TLBIALLEL::matchEntry(TlbEntry* te, vmid_t vmid) const
{
return te->valid && secureLookup == !te->nstid &&
return te->valid && ss == te->ss &&
te->checkRegime(targetRegime);
}
@@ -136,7 +136,7 @@ TLBIVMALL::operator()(ThreadContext* tc)
bool
TLBIVMALL::matchEntry(TlbEntry* te, vmid_t vmid) const
{
return te->valid && secureLookup == !te->nstid &&
return te->valid && ss == te->ss &&
te->checkRegime(targetRegime) &&
(te->vmid == vmid || !el2Enabled || !useVMID(targetRegime));
}
@@ -157,7 +157,7 @@ bool
TLBIASID::matchEntry(TlbEntry* te, vmid_t vmid) const
{
return te->valid && te->asid == asid &&
secureLookup == !te->nstid &&
ss == te->ss &&
te->checkRegime(targetRegime) &&
(te->vmid == vmid || !el2Enabled || !useVMID(targetRegime));
}
@@ -202,7 +202,7 @@ TLBIALLN::operator()(ThreadContext* tc)
bool
TLBIALLN::matchEntry(TlbEntry* te, vmid_t vmid) const
{
return te->valid && te->nstid &&
return te->valid && te->ss == SecurityState::NonSecure &&
te->checkRegime(targetRegime);
}
@@ -213,7 +213,7 @@ TLBIMVAA::lookupGen(vmid_t vmid) const
lookup_data.va = sext<56>(addr);
lookup_data.ignoreAsn = true;
lookup_data.vmid = vmid;
lookup_data.secure = secureLookup;
lookup_data.ss = ss;
lookup_data.functional = true;
lookup_data.targetRegime = targetRegime;
lookup_data.mode = BaseMMU::Read;
@@ -247,7 +247,7 @@ TLBIMVA::lookupGen(vmid_t vmid) const
lookup_data.asn = asid;
lookup_data.ignoreAsn = false;
lookup_data.vmid = vmid;
lookup_data.secure = secureLookup;
lookup_data.ss = ss;
lookup_data.functional = true;
lookup_data.targetRegime = targetRegime;
lookup_data.mode = BaseMMU::Read;
@@ -301,14 +301,37 @@ DTLBIMVA::matchEntry(TlbEntry* te, vmid_t vmid) const
void
TLBIIPA::operator()(ThreadContext* tc)
{
getMMUPtr(tc)->flushStage2(makeStage2());
getMMUPtr(tc)->flushStage2(*this);
CheckerCPU *checker = tc->getCheckerCpuPtr();
if (checker) {
getMMUPtr(checker)->flushStage2(makeStage2());
getMMUPtr(checker)->flushStage2(*this);
}
}
TlbEntry::Lookup
TLBIIPA::lookupGen(vmid_t vmid) const
{
TlbEntry::Lookup lookup_data;
lookup_data.va = szext<56>(addr);
lookup_data.ignoreAsn = true;
lookup_data.vmid = vmid;
lookup_data.ss = ss;
lookup_data.functional = true;
lookup_data.targetRegime = targetRegime;
lookup_data.mode = BaseMMU::Read;
return lookup_data;
}
bool
TLBIIPA::matchEntry(TlbEntry* te, vmid_t vmid) const
{
TlbEntry::Lookup lookup_data = lookupGen(vmid);
return te->match(lookup_data) && (!lastLevel || !te->partial) &&
ipaSpace == te->ipaSpace;
}
bool
TLBIRMVA::matchEntry(TlbEntry* te, vmid_t vmid) const
{
@@ -341,5 +364,22 @@ TLBIRMVAA::matchEntry(TlbEntry* te, vmid_t vmid) const
}
}
bool
TLBIRIPA::matchEntry(TlbEntry* te, vmid_t vmid) const
{
TlbEntry::Lookup lookup_data = lookupGen(vmid);
lookup_data.size = rangeSize();
auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial);
if (addr_match) {
return ipaSpace == te->ipaSpace &&
tgMap[rangeData.tg] == te->tg &&
(resTLBIttl(rangeData.tg, rangeData.ttl) ||
rangeData.ttl == te->lookupLevel);
} else {
return false;
}
}
} // namespace ArmISA
} // namespace gem5

View File

@@ -63,8 +63,8 @@ class TLBIOp
ExcludeXS
};
TLBIOp(TranslationRegime _target_regime, bool _secure, Attr _attr)
: secureLookup(_secure), targetRegime(_target_regime), attr(_attr)
TLBIOp(TranslationRegime _target_regime, SecurityState _ss, Attr _attr)
: ss(_ss), targetRegime(_target_regime), attr(_attr)
{}
virtual ~TLBIOp() {}
@@ -108,7 +108,7 @@ class TLBIOp
return false;
}
bool secureLookup;
SecurityState ss;
TranslationRegime targetRegime;
Attr attr;
};
@@ -117,9 +117,9 @@ class TLBIOp
class TLBIALL : public TLBIOp
{
public:
TLBIALL(TranslationRegime _target_regime, bool _secure,
TLBIALL(TranslationRegime _target_regime, SecurityState _ss,
Attr _attr=Attr::None)
: TLBIOp(_target_regime, _secure, _attr), el2Enabled(false),
: TLBIOp(_target_regime, _ss, _attr), el2Enabled(false),
currentEL(EL0)
{}
@@ -135,12 +135,6 @@ class TLBIALL : public TLBIOp
return currentEL == EL2;
}
TLBIALL
makeStage2() const
{
return TLBIALL(targetRegime, secureLookup, attr);
}
bool el2Enabled;
ExceptionLevel currentEL;
};
@@ -149,8 +143,8 @@ class TLBIALL : public TLBIOp
class ITLBIALL : public TLBIALL
{
public:
ITLBIALL(TranslationRegime _target_regime, bool _secure)
: TLBIALL(_target_regime, _secure)
ITLBIALL(TranslationRegime _target_regime, SecurityState _ss)
: TLBIALL(_target_regime, _ss)
{}
void operator()(ThreadContext* tc) override;
@@ -162,8 +156,8 @@ class ITLBIALL : public TLBIALL
class DTLBIALL : public TLBIALL
{
public:
DTLBIALL(TranslationRegime _target_regime, bool _secure)
: TLBIALL(_target_regime, _secure)
DTLBIALL(TranslationRegime _target_regime, SecurityState _ss)
: TLBIALL(_target_regime, _ss)
{}
void operator()(ThreadContext* tc) override;
@@ -175,8 +169,8 @@ class DTLBIALL : public TLBIALL
class TLBIALLEL : public TLBIOp
{
public:
TLBIALLEL(TranslationRegime _target_regime, bool _secure, Attr _attr)
: TLBIOp(_target_regime, _secure, _attr)
TLBIALLEL(TranslationRegime _target_regime, SecurityState _ss, Attr _attr)
: TLBIOp(_target_regime, _ss, _attr)
{}
void operator()(ThreadContext* tc) override;
@@ -190,22 +184,15 @@ class TLBIALLEL : public TLBIOp
return targetRegime == TranslationRegime::EL10 ||
targetRegime == TranslationRegime::EL20;
}
TLBIALLEL
makeStage2() const
{
return TLBIALLEL(targetRegime, secureLookup, attr);
}
};
/** Implementaton of AArch64 TLBI VMALLE1(IS)/VMALLS112E1(IS) instructions */
class TLBIVMALL : public TLBIOp
{
public:
TLBIVMALL(TranslationRegime _target_regime, bool _secure,
bool _stage2, Attr _attr)
: TLBIOp(_target_regime, _secure, _attr), el2Enabled(false),
TLBIVMALL(TranslationRegime _target_regime,
SecurityState _ss, bool _stage2, Attr _attr)
: TLBIOp(_target_regime, _ss, _attr), el2Enabled(false),
stage2(_stage2)
{}
@@ -219,12 +206,6 @@ class TLBIVMALL : public TLBIOp
return stage2;
}
TLBIVMALL
makeStage2() const
{
return TLBIVMALL(targetRegime, secureLookup, false, attr);
}
bool el2Enabled;
bool stage2;
};
@@ -233,9 +214,9 @@ class TLBIVMALL : public TLBIOp
class TLBIASID : public TLBIOp
{
public:
TLBIASID(TranslationRegime _target_regime, bool _secure,
TLBIASID(TranslationRegime _target_regime, SecurityState _ss,
uint16_t _asid, Attr _attr=Attr::None)
: TLBIOp(_target_regime, _secure, _attr), asid(_asid),
: TLBIOp(_target_regime, _ss, _attr), asid(_asid),
el2Enabled(false)
{}
@@ -251,8 +232,9 @@ class TLBIASID : public TLBIOp
class ITLBIASID : public TLBIASID
{
public:
ITLBIASID(TranslationRegime _target_regime, bool _secure, uint16_t _asid)
: TLBIASID(_target_regime, _secure, _asid)
ITLBIASID(TranslationRegime _target_regime,
SecurityState _ss, uint16_t _asid)
: TLBIASID(_target_regime, _ss, _asid)
{}
void operator()(ThreadContext* tc) override;
@@ -264,8 +246,9 @@ class ITLBIASID : public TLBIASID
class DTLBIASID : public TLBIASID
{
public:
DTLBIASID(TranslationRegime _target_regime, bool _secure, uint16_t _asid)
: TLBIASID(_target_regime, _secure, _asid)
DTLBIASID(TranslationRegime _target_regime,
SecurityState _ss, uint16_t _asid)
: TLBIASID(_target_regime, _ss, _asid)
{}
void operator()(ThreadContext* tc) override;
@@ -278,7 +261,7 @@ class TLBIALLN : public TLBIOp
{
public:
TLBIALLN(TranslationRegime _target_regime)
: TLBIOp(_target_regime, false, Attr::None)
: TLBIOp(_target_regime, SecurityState::NonSecure, Attr::None)
{}
void operator()(ThreadContext* tc) override;
@@ -290,12 +273,6 @@ class TLBIALLN : public TLBIOp
{
return targetRegime != TranslationRegime::EL2;
}
TLBIALLN
makeStage2() const
{
return TLBIALLN(targetRegime);
}
};
/** TLB Invalidate by VA, All ASID */
@@ -304,9 +281,9 @@ class TLBIMVAA : public TLBIOp
protected:
TlbEntry::Lookup lookupGen(vmid_t vmid) const;
public:
TLBIMVAA(TranslationRegime _target_regime, bool _secure,
TLBIMVAA(TranslationRegime _target_regime, SecurityState _ss,
Addr _addr, bool last_level, Attr _attr=Attr::None)
: TLBIOp(_target_regime, _secure, _attr), addr(_addr),
: TLBIOp(_target_regime, _ss, _attr), addr(_addr),
lastLevel(last_level)
{}
@@ -325,10 +302,10 @@ class TLBIMVA : public TLBIOp
TlbEntry::Lookup lookupGen(vmid_t vmid) const;
public:
TLBIMVA(TranslationRegime _target_regime, bool _secure,
TLBIMVA(TranslationRegime _target_regime, SecurityState _ss,
Addr _addr, uint16_t _asid, bool last_level,
Attr _attr=Attr::None)
: TLBIOp(_target_regime, _secure, _attr), addr(_addr), asid(_asid),
: TLBIOp(_target_regime, _ss, _attr), addr(_addr), asid(_asid),
lastLevel(last_level)
{}
@@ -345,9 +322,9 @@ class TLBIMVA : public TLBIOp
class ITLBIMVA : public TLBIMVA
{
public:
ITLBIMVA(TranslationRegime _target_regime, bool _secure,
ITLBIMVA(TranslationRegime _target_regime, SecurityState _ss,
Addr _addr, uint16_t _asid)
: TLBIMVA(_target_regime, _secure, _addr, _asid, false)
: TLBIMVA(_target_regime, _ss, _addr, _asid, false)
{}
void operator()(ThreadContext* tc) override;
@@ -359,9 +336,9 @@ class ITLBIMVA : public TLBIMVA
class DTLBIMVA : public TLBIMVA
{
public:
DTLBIMVA(TranslationRegime _target_regime, bool _secure,
DTLBIMVA(TranslationRegime _target_regime, SecurityState _ss,
Addr _addr, uint16_t _asid)
: TLBIMVA(_target_regime, _secure, _addr, _asid, false)
: TLBIMVA(_target_regime, _ss, _addr, _asid, false)
{}
void operator()(ThreadContext* tc) override;
@@ -427,20 +404,45 @@ class TLBIRange
/** TLB Invalidate by Intermediate Physical Address */
class TLBIIPA : public TLBIOp
{
protected:
TlbEntry::Lookup lookupGen(vmid_t vmid) const;
public:
TLBIIPA(TranslationRegime _target_regime, bool _secure, Addr _addr,
TLBIIPA(TranslationRegime _target_regime, SecurityState _ss, Addr _addr,
bool last_level, Attr _attr=Attr::None)
: TLBIOp(_target_regime, _secure, _attr),
addr(_addr), lastLevel(last_level)
: TLBIOp(_target_regime, _ss, _attr),
addr(_addr),
lastLevel(last_level),
ipaSpace(PASpace::NonSecure)
{}
TLBIIPA(ThreadContext *tc, TranslationRegime _target_regime,
SecurityState _ss, RegVal val,
bool last_level, Attr _attr=Attr::None)
: TLBIOp(_target_regime, _ss, _attr),
addr(0),
lastLevel(last_level),
ipaSpace(PASpace::NonSecure)
{
const int top_bit = ArmSystem::physAddrRange(tc) == 52 ?
39 : 35;
addr = static_cast<Addr>(bits(val, top_bit, 0)) << 12;
switch (ss) {
case SecurityState::NonSecure:
ipaSpace = PASpace::NonSecure;
break;
case SecurityState::Secure:
ipaSpace = bits(val, 63) ?
PASpace::NonSecure : PASpace::Secure;
break;
default:
panic("Invalid SecurityState\n");
}
}
void operator()(ThreadContext* tc) override;
bool
matchEntry(TlbEntry *entry, vmid_t curr_vmid) const override
{
panic("This shouldn't be called\n");
}
bool matchEntry(TlbEntry *entry, vmid_t curr_vmid) const override;
bool
stage1Flush() const override
@@ -448,26 +450,19 @@ class TLBIIPA : public TLBIOp
return false;
}
/** TLBIIPA is basically a TLBIMVAA for stage2 TLBs */
virtual TLBIMVAA
makeStage2() const
{
return TLBIMVAA(targetRegime, secureLookup, addr, lastLevel, attr);
}
Addr addr;
bool lastLevel;
PASpace ipaSpace;
};
/** TLB Range Invalidate by VA */
class TLBIRMVA : public TLBIRange, public TLBIMVA
{
public:
TLBIRMVA(TranslationRegime _target_regime, bool _secure,
TLBIRMVA(TranslationRegime _target_regime, SecurityState _ss,
RegVal val, uint16_t _asid, bool last_level, Attr _attr)
: TLBIRange(val),
TLBIMVA(_target_regime, _secure, startAddress(),
_asid, last_level, _attr)
TLBIMVA(_target_regime, _ss, startAddress(), _asid, last_level, _attr)
{}
bool matchEntry(TlbEntry *entry, vmid_t curr_vmid) const override;
@@ -477,10 +472,10 @@ class TLBIRMVA : public TLBIRange, public TLBIMVA
class TLBIRMVAA : public TLBIRange, public TLBIMVAA
{
public:
TLBIRMVAA(TranslationRegime _target_regime, bool _secure,
TLBIRMVAA(TranslationRegime _target_regime, SecurityState _ss,
RegVal val, bool last_level, Attr _attr)
: TLBIRange(val),
TLBIMVAA(_target_regime, _secure, startAddress(), last_level, _attr)
TLBIMVAA(_target_regime, _ss, startAddress(), last_level, _attr)
{}
bool matchEntry(TlbEntry *entry, vmid_t curr_vmid) const override;
@@ -490,18 +485,15 @@ class TLBIRMVAA : public TLBIRange, public TLBIMVAA
class TLBIRIPA : public TLBIRange, public TLBIIPA
{
public:
TLBIRIPA(TranslationRegime _target_regime, bool _secure,
TLBIRIPA(ThreadContext *tc, TranslationRegime _target_regime, SecurityState _ss,
RegVal val, bool last_level, Attr _attr)
: TLBIRange(val),
TLBIIPA(_target_regime, _secure, startAddress(), last_level, _attr)
{}
virtual TLBIMVAA
makeStage2() const
TLBIIPA(tc, _target_regime, _ss, val, last_level, _attr)
{
return TLBIRMVAA(targetRegime, secureLookup, rangeData,
lastLevel, attr);
addr = startAddress();
}
bool matchEntry(TlbEntry *entry, vmid_t curr_vmid) const override;
};
} // namespace ArmISA

View File

@@ -268,6 +268,20 @@ namespace ArmISA
RND_NEAREST
};
/** Security State */
enum class SecurityState
{
NonSecure,
Secure
};
/** Physical Address Space */
enum class PASpace
{
NonSecure,
Secure
};
enum ExceptionLevel
{
EL0 = 0,
@@ -487,6 +501,22 @@ namespace ArmISA
}
}
static inline std::ostream&
operator<<(std::ostream& os, SecurityState ss)
{
switch (ss) {
case SecurityState::NonSecure:
os << "NonSecure";
break;
case SecurityState::Secure:
os << "Secure";
break;
default:
panic("Invalid SecurityState\n");
}
return os;
}
constexpr unsigned MaxSveVecLenInBits = 2048;
static_assert(MaxSveVecLenInBits >= 128 &&
MaxSveVecLenInBits <= 2048 &&

View File

@@ -89,13 +89,14 @@ isSecureBelowEL3(ThreadContext *tc)
static_cast<SCR>(tc->readMiscRegNoEffect(MISCREG_SCR_EL3)).ns == 0;
}
bool
isSecureAtEL(ThreadContext *tc, ExceptionLevel el)
SecurityState
securityStateAtEL(ThreadContext *tc, ExceptionLevel el)
{
if (ArmSystem::haveEL(tc, EL3) && el == EL3)
return true;
return SecurityState::Secure;
else
return isSecureBelowEL3(tc);
return isSecureBelowEL3(tc) ? SecurityState::Secure :
SecurityState::NonSecure;
}
ExceptionLevel

View File

@@ -217,7 +217,7 @@ int computeAddrTop(ThreadContext *tc, bool selbit, bool isInstr,
bool isSecureBelowEL3(ThreadContext *tc);
bool isSecureAtEL(ThreadContext *tc, ExceptionLevel el);
SecurityState securityStateAtEL(ThreadContext *tc, ExceptionLevel el);
bool longDescFormatInUse(ThreadContext *tc);