Hello Andreas Sandberg,
I'd like you to do a code review. Please visit
https://gem5-review.googlesource.com/6622
to review the following change.
Change subject: arch-arm: Fixed WFE/WFI trapping behaviour
......................................................................
arch-arm: Fixed WFE/WFI trapping behaviour
This patch fixes the WFx trapping behaviour by introducing the arm arm
v8 pseudocode functions: checkForWFxTrap32 and checkForWFxTrap64
Change-Id: I3db0d78b5c4ad46860e6d199c2f2fc7b41842840
Signed-off-by: Giacomo Travaglini <giacomo.travagl...@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandb...@arm.com>
---
M src/arch/arm/insts/static_inst.cc
M src/arch/arm/insts/static_inst.hh
M src/arch/arm/isa/insts/misc.isa
3 files changed, 164 insertions(+), 33 deletions(-)
diff --git a/src/arch/arm/insts/static_inst.cc
b/src/arch/arm/insts/static_inst.cc
index 8501715..eeda3ad 100644
--- a/src/arch/arm/insts/static_inst.cc
+++ b/src/arch/arm/insts/static_inst.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2014, 2016 ARM Limited
+ * Copyright (c) 2010-2014, 2016-2017 ARM Limited
* Copyright (c) 2013 Advanced Micro Devices, Inc.
* All rights reserved
*
@@ -735,6 +735,129 @@
return NoFault;
}
+inline bool
+ArmStaticInst::isWFxTrapping(ThreadContext *tc,
+ ExceptionLevel tgtEl,
+ bool isWfe) const
+{
+ bool trap = false;
+ SCTLR sctlr = ((SCTLR)tc->readMiscReg(MISCREG_SCTLR_EL1));
+ HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
+ SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3));
+
+ switch (tgtEl) {
+ case EL1:
+ trap = isWfe? !sctlr.ntwe : !sctlr.ntwi;
+ break;
+ case EL2:
+ trap = isWfe? hcr.twe : hcr.twi;
+ break;
+ case EL3:
+ trap = isWfe? scr.twe : scr.twi;
+ break;
+ default:
+ break;
+ }
+
+ return trap;
+}
+
+Fault
+ArmStaticInst::checkForWFxTrap32(ThreadContext *tc,
+ ExceptionLevel targetEL,
+ bool isWfe) const
+{
+ // Check if target exception level is implemented.
+ assert(ArmSystem::haveEL(tc, targetEL));
+
+ // Check for routing to AArch64: this happens if the
+ // target exception level (where the trap will be handled)
+ // is using aarch64
+ if (ELIs64(tc, targetEL)) {
+ return checkForWFxTrap64(tc, targetEL, isWfe);
+ }
+
+ // Check if processor needs to trap at selected exception level
+ bool trap = isWFxTrapping(tc, targetEL, isWfe);
+
+ if (trap) {
+ uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */
+ 0x1E00000; /* WFI Instruction syndrome */
+ switch (targetEL) {
+ case EL1:
+ return std::make_shared<UndefinedInstruction>(
+ machInst, iss,
+ EC_TRAPPED_WFI_WFE, mnemonic);
+ case EL2:
+ return std::make_shared<HypervisorTrap>(machInst, iss,
+ EC_TRAPPED_WFI_WFE);
+ case EL3:
+ return std::make_shared<SecureMonitorTrap>(machInst, iss,
+ EC_TRAPPED_WFI_WFE);
+ default:
+ panic("Unrecognized Exception Level: %d\n", targetEL);
+ }
+ }
+
+ return NoFault;
+}
+
+Fault
+ArmStaticInst::checkForWFxTrap64(ThreadContext *tc,
+ ExceptionLevel targetEL,
+ bool isWfe) const
+{
+ // Check if target exception level is implemented.
+ assert(ArmSystem::haveEL(tc, targetEL));
+
+ // Check if processor needs to trap at selected exception level
+ bool trap = isWFxTrapping(tc, targetEL, isWfe);
+
+ if (trap) {
+ uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */
+ 0x1E00000; /* WFI Instruction syndrome */
+ switch (targetEL) {
+ case EL1:
+ return std::make_shared<SupervisorTrap>(machInst, iss,
+ EC_TRAPPED_WFI_WFE);
+ case EL2:
+ return std::make_shared<HypervisorTrap>(machInst, iss,
+ EC_TRAPPED_WFI_WFE);
+ case EL3:
+ return std::make_shared<SecureMonitorTrap>(machInst, iss,
+ EC_TRAPPED_WFI_WFE);
+ default:
+ panic("Unrecognized Exception Level: %d\n", targetEL);
+ }
+ }
+
+ return NoFault;
+}
+
+Fault
+ArmStaticInst::trapWFx(ThreadContext *tc,
+ CPSR cpsr, SCR scr,
+ bool isWfe) const
+{
+ Fault fault = NoFault;
+ if (cpsr.el == EL0) {
+ fault = checkForWFxTrap32(tc, EL1, isWfe);
+ }
+
+ if ((fault == NoFault) &&
+ ArmSystem::haveEL(tc, EL2) && !inSecureState(scr, cpsr) &&
+ ((cpsr.el == EL0) || (cpsr.el == EL1))) {
+
+ fault = checkForWFxTrap32(tc, EL2, isWfe);
+ }
+
+ if ((fault == NoFault) &&
+ ArmSystem::haveEL(tc, EL3) && cpsr.el != EL3) {
+ fault = checkForWFxTrap32(tc, EL3, isWfe);
+ }
+
+ return fault;
+}
static uint8_t
getRestoredITBits(ThreadContext *tc, CPSR spsr)
diff --git a/src/arch/arm/insts/static_inst.hh
b/src/arch/arm/insts/static_inst.hh
index 431e81b..f9414f1 100644
--- a/src/arch/arm/insts/static_inst.hh
+++ b/src/arch/arm/insts/static_inst.hh
@@ -364,6 +364,11 @@
mnemonic, true);
}
+ // Utility function used by checkForWFxTrap32 and checkForWFxTrap64
+ // Returns true if processor has to trap a WFI/WFE instruction.
+ bool isWFxTrapping(ThreadContext *tc,
+ ExceptionLevel targetEL, bool isWfe) const;
+
/**
* Trap an access to Advanced SIMD or FP registers due to access
* control bits.
@@ -406,6 +411,29 @@
bool fpexc_check, bool advsimd) const;
/**
+ * Check if WFE/WFI instruction execution in aarch32 should be trapped.
+ *
+ * See aarch32/exceptions/traps/AArch32.checkForWFxTrap in the
+ * ARM ARM psueodcode library.
+ */
+ Fault checkForWFxTrap32(ThreadContext *tc,
+ ExceptionLevel tgtEl, bool isWfe) const;
+
+ /**
+ * Check if WFE/WFI instruction execution in aarch64 should be trapped.
+ *
+ * See aarch64/exceptions/traps/AArch64.checkForWFxTrap in the
+ * ARM ARM psueodcode library.
+ */
+ Fault checkForWFxTrap64(ThreadContext *tc,
+ ExceptionLevel tgtEl, bool isWfe) const;
+
+ /**
+ * WFE/WFI trapping helper function.
+ */
+ Fault trapWFx(ThreadContext *tc, CPSR cpsr, SCR scr, bool isWfe) const;
+
+ /**
* Get the new PSTATE from a SPSR register in preparation for an
* exception return.
*
diff --git a/src/arch/arm/isa/insts/misc.isa
b/src/arch/arm/isa/insts/misc.isa
index ef0a670..ae8474f 100644
--- a/src/arch/arm/isa/insts/misc.isa
+++ b/src/arch/arm/isa/insts/misc.isa
@@ -670,10 +670,8 @@
exec_output += PredOpExecute.subst(yieldIop)
wfeCode = '''
- HCR hcr = Hcr;
CPSR cpsr = Cpsr;
SCR scr = Scr64;
- SCTLR sctlr = Sctlr;
// WFE Sleeps if SevMailbox==0 and no unmasked interrupts are pending,
ThreadContext *tc = xc->tcBase();
@@ -683,22 +681,13 @@
} else if (tc->getCpuPtr()->getInterruptController(
tc->threadId())->checkInterrupts(tc)) {
PseudoInst::quiesceSkip(tc);
- } else if (cpsr.el == EL0 && !sctlr.ntwe) {
- PseudoInst::quiesceSkip(tc);
- fault = std::make_shared<SupervisorTrap>(machInst, 0x1E00001,
- EC_TRAPPED_WFI_WFE);
- } else if (ArmSystem::haveVirtualization(tc) &&
- !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP) &&
- hcr.twe) {
- PseudoInst::quiesceSkip(tc);
- fault = std::make_shared<HypervisorTrap>(machInst, 0x1E00001,
- EC_TRAPPED_WFI_WFE);
- } else if (ArmSystem::haveSecurity(tc) && cpsr.el != EL3 && scr.twe) {
- PseudoInst::quiesceSkip(tc);
- fault = std::make_shared<SecureMonitorTrap>(machInst, 0x1E00001,
- EC_TRAPPED_WFI_WFE);
} else {
- PseudoInst::quiesce(tc);
+ fault = trapWFx(tc, cpsr, scr, true);
+ if (fault == NoFault) {
+ PseudoInst::quiesce(tc);
+ } else {
+ PseudoInst::quiesceSkip(tc);
+ }
}
'''
wfePredFixUpCode = '''
@@ -720,28 +709,19 @@
HCR hcr = Hcr;
CPSR cpsr = Cpsr;
SCR scr = Scr64;
- SCTLR sctlr = Sctlr;
// WFI doesn't sleep if interrupts are pending (masked or not)
ThreadContext *tc = xc->tcBase();
if (tc->getCpuPtr()->getInterruptController(
tc->threadId())->checkWfiWake(hcr, cpsr, scr)) {
PseudoInst::quiesceSkip(tc);
- } else if (cpsr.el == EL0 && !sctlr.ntwi) {
- PseudoInst::quiesceSkip(tc);
- fault = std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
- EC_TRAPPED_WFI_WFE);
- } else if (ArmSystem::haveVirtualization(tc) && hcr.twi &&
- (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr)) {
- PseudoInst::quiesceSkip(tc);
- fault = std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
- EC_TRAPPED_WFI_WFE);
- } else if (ArmSystem::haveSecurity(tc) && cpsr.el != EL3 && scr.twi) {
- PseudoInst::quiesceSkip(tc);
- fault = std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
- EC_TRAPPED_WFI_WFE);
} else {
- PseudoInst::quiesce(tc);
+ fault = trapWFx(tc, cpsr, scr, false);
+ if (fault == NoFault) {
+ PseudoInst::quiesce(tc);
+ } else {
+ PseudoInst::quiesceSkip(tc);
+ }
}
tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
'''
--
To view, visit https://gem5-review.googlesource.com/6622
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I3db0d78b5c4ad46860e6d199c2f2fc7b41842840
Gerrit-Change-Number: 6622
Gerrit-PatchSet: 1
Gerrit-Owner: Giacomo Travaglini <giacomo.travagl...@arm.com>
Gerrit-Reviewer: Andreas Sandberg <andreas.sandb...@arm.com>
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev