arch-arm: Read VMPIDR instead of MPIDR when EL2 is Enabled
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 18 Dec 2018 14:20:44 +0000 (14:20 +0000)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Wed, 16 Jan 2019 11:20:26 +0000 (11:20 +0000)
Trying to read MPIDR(_EL1) from EL1, should return the value of
VMPIDR_EL2 if EL2 is enabled. This patch is modifying the utility
function for reading MPIDR in order to match this behaviour for both
AArch32 and AArch64.

Change-Id: I32c2d4d5052f509e6e0542a5314844164221c6a3
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/15617
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/arch/arm/isa.cc
src/arch/arm/utility.cc
src/arch/arm/utility.hh

index 17c87ba84d72e748138b7b174473271a4fba0569..3d98aeacf101957a0eae8fa9d8114258ff5edc47 100644 (file)
@@ -477,18 +477,10 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
             return val;
         }
       case MISCREG_MPIDR:
-        cpsr = readMiscRegNoEffect(MISCREG_CPSR);
-        scr  = readMiscRegNoEffect(MISCREG_SCR);
-        if ((cpsr.mode == MODE_HYP) || inSecureState(scr, cpsr)) {
-            return getMPIDR(system, tc);
-        } else {
-            return readMiscReg(MISCREG_VMPIDR, tc);
-        }
-            break;
       case MISCREG_MPIDR_EL1:
-        // @todo in the absence of v8 virtualization support just return MPIDR_EL1
-        return getMPIDR(system, tc) & 0xffffffff;
+        return readMPIDR(system, tc);
       case MISCREG_VMPIDR:
+      case MISCREG_VMPIDR_EL2:
         // top bit defined as RES1
         return readMiscRegNoEffect(misc_reg) | 0x80000000;
       case MISCREG_ID_AFR0: // not implemented, so alias MIDR
index 1dc7fc04754e498927570a6ba5160ca07efe540e..58eb032c47b37c23421191139472cf6c3f39eda4 100644 (file)
@@ -205,7 +205,37 @@ longDescFormatInUse(ThreadContext *tc)
     return ArmSystem::haveLPAE(tc) && ttbcr.eae;
 }
 
-uint32_t
+MiscReg
+readMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
+{
+    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+    const ExceptionLevel current_el =
+        opModeToEL((OperatingMode) (uint8_t) cpsr.mode);
+
+    const bool is_secure = isSecureBelowEL3(tc);
+
+    switch (current_el) {
+      case EL0:
+        // Note: in MsrMrs instruction we read the register value before
+        // checking access permissions. This means that EL0 entry must
+        // be part of the table even if MPIDR is not accessible in user
+        // mode.
+        warn_once("Trying to read MPIDR at EL0\n");
+        M5_FALLTHROUGH;
+      case EL1:
+        if (ArmSystem::haveEL(tc, EL2) && !is_secure)
+            return tc->readMiscReg(MISCREG_VMPIDR_EL2);
+        else
+            return getMPIDR(arm_sys, tc);
+      case EL2:
+      case EL3:
+        return getMPIDR(arm_sys, tc);
+      default:
+        panic("Invalid EL for reading MPIDR register\n");
+    }
+}
+
+MiscReg
 getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
 {
     // Multiprocessor Affinity Register MPIDR from Cortex(tm)-A15 Technical
index 33696984ef71a6a3220164f15421adee2fc1d34e..01b95b3b5770f3c44091a0e074df3bd3e1e75b7e 100644 (file)
@@ -250,7 +250,13 @@ inline bool isSecureBelowEL3(ThreadContext *tc);
 
 bool longDescFormatInUse(ThreadContext *tc);
 
-uint32_t getMPIDR(ArmSystem *arm_sys, ThreadContext *tc);
+/** This helper function is either returing the value of
+ * MPIDR_EL1 (by calling getMPIDR), or it is issuing a read
+ * to VMPIDR_EL2 (as it happens in virtualized systems) */
+MiscReg readMPIDR(ArmSystem *arm_sys, ThreadContext *tc);
+
+/** This helper function is returing the value of MPIDR_EL1 */
+MiscReg getMPIDR(ArmSystem *arm_sys, ThreadContext *tc);
 
 static inline uint32_t
 mcrMrcIssBuild(bool isRead, uint32_t crm, IntRegIndex rt, uint32_t crn,