/*
- * Copyright (c) 2010, 2012-2014 ARM Limited
+ * Copyright (c) 2010, 2012-2014, 2016 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
*/
#include "arch/arm/faults.hh"
+
+#include "arch/arm/insts/static_inst.hh"
#include "arch/arm/system.hh"
#include "arch/arm/utility.hh"
-#include "arch/arm/insts/static_inst.hh"
#include "base/compiler.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
assert(ArmSystem::haveSecurity(tc));
vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
break;
- // @todo: uncomment this to enable Virtualization
- // case EL2:
- // assert(ArmSystem::haveVirtualization(tc));
- // vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
- // break;
+ case EL2:
+ assert(ArmSystem::haveVirtualization(tc));
+ vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
+ break;
case EL1:
vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
break;
}
void
-ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
+ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
// Determine target exception level
if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc))
toEL = EL3;
+ else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc))
+ toEL = EL2;
else
toEL = opModeToEL(nextMode());
if (fromEL > toEL)
}
void
-ArmFault::invoke64(ThreadContext *tc, StaticInstPtr inst)
+ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
{
// Determine actual misc. register indices for ELR_ELx and SPSR_ELx
MiscRegIndex elr_idx, spsr_idx;
elr_idx = MISCREG_ELR_EL1;
spsr_idx = MISCREG_SPSR_EL1;
break;
- // @todo: uncomment this to enable Virtualization
- // case EL2:
- // assert(ArmSystem::haveVirtualization());
- // elr_idx = MISCREG_ELR_EL2;
- // spsr_idx = MISCREG_SPSR_EL2;
- // break;
+ case EL2:
+ assert(ArmSystem::haveVirtualization(tc));
+ elr_idx = MISCREG_ELR_EL2;
+ spsr_idx = MISCREG_SPSR_EL2;
+ break;
case EL3:
assert(ArmSystem::haveSecurity(tc));
elr_idx = MISCREG_ELR_EL3;
}
void
-Reset::invoke(ThreadContext *tc, StaticInstPtr inst)
+Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
if (FullSystem) {
- tc->getCpuPtr()->clearInterrupts();
+ tc->getCpuPtr()->clearInterrupts(tc->threadId());
tc->clearArchRegs();
}
if (!ArmSystem::highestELIs64(tc)) {
}
void
-UndefinedInstruction::invoke(ThreadContext *tc, StaticInstPtr inst)
+UndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
if (FullSystem) {
ArmFault::invoke(tc, inst);
}
void
-SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst)
+SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
if (FullSystem) {
ArmFault::invoke(tc, inst);
callNum = tc->readIntReg(INTREG_X8);
else
callNum = tc->readIntReg(INTREG_R7);
- tc->syscall(callNum);
+ Fault fault;
+ tc->syscall(callNum, &fault);
// Advance the PC since that won't happen automatically.
PCState pc = tc->pcState();
ArmFaultVals<HypervisorCall>(_machInst, _imm)
{}
+ExceptionClass
+HypervisorCall::ec(ThreadContext *tc) const
+{
+ return from64 ? EC_HVC_64 : vals.ec;
+}
+
ExceptionClass
HypervisorTrap::ec(ThreadContext *tc) const
{
// }
void
-SecureMonitorCall::invoke(ThreadContext *tc, StaticInstPtr inst)
+SecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
if (FullSystem) {
ArmFault::invoke(tc, inst);
template<class T>
void
-AbortFault<T>::invoke(ThreadContext *tc, StaticInstPtr inst)
+AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
if (tranMethod == ArmFault::UnknownTran) {
tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
}
if (source == ArmFault::AsynchronousExternalAbort) {
- tc->getCpuPtr()->clearInterrupt(INT_ABT, 0);
+ tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
}
// Get effective fault source encoding
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
// try to set hsr etc. and are based upon source!
ArmFaultVals<T>::invoke(tc, inst);
- if (cpsr.width) { // AArch32
+ if (!this->to64) { // AArch32
if (cpsr.mode == MODE_HYP) {
tc->setMiscReg(T::HFarIndex, faultAddr);
} else if (stage2) {
} else { // AArch64
// Set the FAR register. Nothing else to do if we are in AArch64 state
// because the syndrome register has already been set inside invoke64()
- tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
+ if (stage2) {
+ // stage 2 fault, set HPFAR_EL2 to the faulting IPA
+ // and FAR_EL2 to the Original VA
+ tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
+ tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
+
+ DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
+ OVAddr, faultAddr);
+ } else {
+ tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
+ }
}
}
toHyp |= (stage2 ||
( (source == DebugEvent) && hdcr.tde && (cpsr.mode != MODE_HYP)) ||
( (source == SynchronousExternalAbort) && hcr.tge && (cpsr.mode == MODE_USER))
- ) && !inSecureState(scr, cpsr);
+ ) && !inSecureState(tc);
return toHyp;
}
if (to64) {
// AArch64
if (source == ArmFault::AsynchronousExternalAbort) {
- panic("Asynchronous External Abort should be handled with \
- SystemErrors (SErrors)!");
+ panic("Asynchronous External Abort should be handled with "
+ "SystemErrors (SErrors)!");
}
if (toEL == fromEL)
return EC_DATA_ABORT_CURR_EL;
((source == AlignmentFault) ||
(source == SynchronousExternalAbort))
)
- ) && !inSecureState(scr, cpsr);
+ ) && !inSecureState(tc);
return toHyp;
}
}
void
-VirtualDataAbort::invoke(ThreadContext *tc, StaticInstPtr inst)
+VirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
AbortFault<VirtualDataAbort>::invoke(tc, inst);
HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
// Determine whether IRQs are routed to Hyp mode.
- toHyp = (!scr.irq && hcr.imo && !inSecureState(scr, cpsr)) ||
+ toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
(cpsr.mode == MODE_HYP);
return toHyp;
}
HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
// Determine whether IRQs are routed to Hyp mode.
- toHyp = (!scr.fiq && hcr.fmo && !inSecureState(scr, cpsr)) ||
+ toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
(cpsr.mode == MODE_HYP);
return toHyp;
}
{}
void
-PCAlignmentFault::invoke(ThreadContext *tc, StaticInstPtr inst)
+PCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
assert(from64);
{}
void
-SystemError::invoke(ThreadContext *tc, StaticInstPtr inst)
+SystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
- tc->getCpuPtr()->clearInterrupt(INT_ABT, 0);
+ tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
ArmFault::invoke(tc, inst);
}
SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
- CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
- toHyp = (!scr.ea && hcr.amo && !inSecureState(scr, cpsr)) ||
- (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(scr,cpsr));
+ toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
+ (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
return toHyp;
}
void
-FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) {
+FlushPipe::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
DPRINTF(Faults, "Invoking FlushPipe Fault\n");
// Set the PC to the next instruction of the faulting instruction.
}
void
-ArmSev::invoke(ThreadContext *tc, StaticInstPtr inst) {
+ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
DPRINTF(Faults, "Invoking ArmSev Fault\n");
if (!FullSystem)
return;
// SEV execution and let pipeline continue as pcState is still
// valid.
tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
- tc->getCpuPtr()->clearInterrupt(INT_SEV, 0);
+ tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
}
// Instantiate all the templates to make the linker happy