arch-arm: Update ARMv8.1-PAN to allow unprivileged instructions.

Update the ARMv8.1-PAN implementation to allow specified unprivileged
instructions to execute even when the cpsr.pan bit is set. The
specified instructions generate memory requests with the
TLB::ArmFlags::UserMode flags bit set.

See sections D5.4.2 (About PSTATE.PAN) and G5.6.2 (About the PAN bit)
of the Arm Architecture Reference Manual for details.
https://developer.arm.com/documentation/ddi0487/latest/

Change-Id: I9e904e0154de72c2e4cc70cbc49b3c8407a3cb1d
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/47779
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Richard Cooper
2021-07-01 10:34:58 +01:00
parent 04a4fb53ad
commit c25ef2d191
2 changed files with 18 additions and 11 deletions

View File

@@ -898,7 +898,7 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req,
break;
case EL1:
{
if (checkPAN(tc, ap, req, mode)) {
if (checkPAN(tc, ap, req, mode, is_priv)) {
grant = false;
grant_read = false;
break;
@@ -938,7 +938,7 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req,
}
break;
case EL2:
if (hcr.e2h && checkPAN(tc, ap, req, mode)) {
if (hcr.e2h && checkPAN(tc, ap, req, mode, is_priv)) {
grant = false;
grant_read = false;
break;
@@ -998,7 +998,7 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req,
bool
TLB::checkPAN(ThreadContext *tc, uint8_t ap, const RequestPtr &req,
BaseMMU::Mode mode)
BaseMMU::Mode mode, const bool is_priv)
{
// The PAN bit has no effect on:
// 1) Instruction accesses.
@@ -1006,15 +1006,22 @@ TLB::checkPAN(ThreadContext *tc, uint8_t ap, const RequestPtr &req,
// 3) Address translation instructions, other than ATS1E1RP and
// ATS1E1WP when ARMv8.2-ATS1E1 is implemented. (Unimplemented in
// gem5)
// 4) Unprivileged instructions (Unimplemented in gem5)
AA64MMFR1 mmfr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1);
if (mmfr1.pan && cpsr.pan && (ap & 0x1) && mode != BaseMMU::Execute &&
(!req->isCacheMaintenance() ||
(req->getFlags() & Request::CACHE_BLOCK_ZERO))) {
// 4) Instructions to be treated as unprivileged, unless
// HCR_EL2.{E2H, TGE} == {1, 0}
const AA64MMFR1 mmfr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1);
if (mmfr1.pan && cpsr.pan && (ap & 0x1) && mode != BaseMMU::Execute) {
if (req->isCacheMaintenance() &&
!(req->getFlags() & Request::CACHE_BLOCK_ZERO)) {
// Cache maintenance other than DC ZVA
return false;
} else if (!is_priv && !(hcr.e2h && !hcr.tge)) {
// Treated as unprivileged unless HCR_EL2.{E2H, TGE} == {1, 0}
return false;
}
return true;
} else {
return false;
}
return false;
}
Fault

View File

@@ -259,7 +259,7 @@ class TLB : public BaseTLB
Fault checkPermissions64(TlbEntry *te, const RequestPtr &req,
BaseMMU::Mode mode, ThreadContext *tc);
bool checkPAN(ThreadContext *tc, uint8_t ap, const RequestPtr &req,
BaseMMU::Mode mode);
BaseMMU::Mode mode, const bool is_priv);
/** Reset the entire TLB. Used for CPU switching to prevent stale
* translations after multiple switches