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>
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index e9c487e..8941f9e 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -898,7 +898,7 @@
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 @@
}
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 @@
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 @@
// 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
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index 3d399c6..72e8803 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -259,7 +259,7 @@
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