From cba75858ab94b525c2daad973b8197e9ebd1f1af Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 18 Dec 2018 14:20:44 +0000 Subject: [PATCH] arch-arm: Read VMPIDR instead of MPIDR when EL2 is Enabled 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 Reviewed-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/c/15617 Maintainer: Andreas Sandberg --- src/arch/arm/isa.cc | 12 ++---------- src/arch/arm/utility.cc | 32 +++++++++++++++++++++++++++++++- src/arch/arm/utility.hh | 8 +++++++- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 17c87ba84..3d98aeacf 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -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 diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 1dc7fc047..58eb032c4 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -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 diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 33696984e..01b95b3b5 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -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, -- 2.30.2