ARM: Implement ARM CPU interrupts

This commit is contained in:
Ali Saidi 2010-06-02 12:58:16 -05:00
parent 3aea20d143
commit b8ec214553
14 changed files with 150 additions and 23 deletions

View file

@ -77,11 +77,11 @@ ArmFault::getVector(ThreadContext *tc)
// ARM ARM B1-3
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
// panic if SCTLR.VE because I have no idea what to do with vectored
// interrupts
assert(!sctlr.ve);
if (!sctlr.v)
return offset();
return offset() + HighVecs;
@ -137,14 +137,22 @@ ArmFault::invoke(ThreadContext *tc)
}
Addr pc = tc->readPC();
DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x\n",
name(), cpsr, pc, tc->readIntReg(INTREG_LR));
Addr newPc = getVector(tc) | (sctlr.te ? (ULL(1) << PcTBitShift) : 0);
DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x newVector: %#x\n",
name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc);
tc->setPC(newPc);
tc->setNextPC(newPc + cpsr.t ? 2 : 4 );
tc->setMicroPC(0);
}
void
Reset::invoke(ThreadContext *tc)
{
tc->getCpuPtr()->clearInterrupts();
tc->clearArchRegs();
ArmFault::invoke(tc);
}
#else
void

View file

@ -128,8 +128,15 @@ class ArmFaultVals : public ArmFault
bool fiqDisable() { return vals.fiqDisable; }
};
class Reset : public ArmFaultVals<Reset> {};
class Reset : public ArmFaultVals<Reset>
#if FULL_SYSTEM
{
public:
void invoke(ThreadContext *tc);
};
#else
{};
#endif //FULL_SYSTEM
class UndefinedInstruction : public ArmFaultVals<UndefinedInstruction>
{

View file

@ -156,7 +156,7 @@ class ArmStaticInst : public StaticInst
static uint32_t
cpsrWriteByInstr(CPSR cpsr, uint32_t val,
uint8_t byteMask, bool affectState)
uint8_t byteMask, bool affectState, bool nmfi)
{
bool privileged = (cpsr.mode != MODE_USER);
@ -187,7 +187,11 @@ class ArmStaticInst : public StaticInst
bitMask = bitMask | (1 << 5);
}
return ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
bool cpsr_f = cpsr.f;
uint32_t new_cpsr = ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
if (nmfi && !cpsr_f)
new_cpsr &= ~(1 << 6);
return new_cpsr;
}
static uint32_t

View file

@ -2,6 +2,15 @@
* Copyright (c) 2009 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright

View file

@ -1,6 +1,17 @@
/*
* Copyright (c) 2010 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2006 The Regents of The University of Michigan
* Copyright (c) 2009 ARM Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,6 +45,7 @@
#include "arch/arm/faults.hh"
#include "arch/arm/isa_traits.hh"
#include "arch/arm/miscregs.hh"
#include "arch/arm/registers.hh"
#include "cpu/thread_context.hh"
#include "params/ArmInterrupts.hh"
@ -47,6 +59,7 @@ class Interrupts : public SimObject
private:
BaseCPU * cpu;
bool interrupts[NumInterruptTypes];
uint64_t intStatus;
public:
@ -74,46 +87,95 @@ class Interrupts : public SimObject
void
post(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
if (int_num < 0 || int_num >= NumInterruptTypes)
panic("int_num out of bounds\n");
if (index != 0)
panic("No support for other interrupt indexes\n");
interrupts[int_num] = true;
intStatus |= ULL(1) << int_num;
}
void
clear(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
if (int_num < 0 || int_num >= NumInterruptTypes)
panic("int_num out of bounds\n");
if (index != 0)
panic("No support for other interrupt indexes\n");
interrupts[int_num] = false;
intStatus &= ~(ULL(1) << int_num);
}
void
clearAll()
{
DPRINTF(Interrupt, "Interrupts all cleared\n");
intStatus = 0;
memset(interrupts, 0, sizeof(interrupts));
}
bool
checkInterrupts(ThreadContext *tc) const
{
return intStatus;
if (!intStatus)
return false;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
return ((interrupts[INT_IRQ] && !cpsr.i) ||
(interrupts[INT_FIQ] && !cpsr.f) ||
(interrupts[INT_ABT] && !cpsr.a) ||
(interrupts[INT_RST]));
}
Fault
getInterrupt(ThreadContext *tc)
{
warn_once("ARM Interrupts not handled\n");
return NoFault;
if (!intStatus)
return NoFault;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
if (interrupts[INT_IRQ] && !cpsr.i)
return new Interrupt;
if (interrupts[INT_FIQ] && !cpsr.f)
return new FastInterrupt;
if (interrupts[INT_ABT] && !cpsr.a)
return new DataAbort(0, false, 0,
ArmFault::AsynchronousExternalAbort);
if (interrupts[INT_RST])
return new Reset;
panic("intStatus and interrupts not in sync\n");
}
void
updateIntrInfo(ThreadContext *tc)
{
; // nothing to do
}
void
serialize(std::ostream &os)
{
SERIALIZE_ARRAY(interrupts, NumInterruptTypes);
SERIALIZE_SCALAR(intStatus);
}
void
unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(interrupts, NumInterruptTypes);
UNSERIALIZE_SCALAR(intStatus);
}
};
} // namespace ARM_ISA

View file

@ -92,6 +92,8 @@ namespace ArmISA
public:
void clear()
{
SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST];
memset(miscRegs, 0, sizeof(miscRegs));
CPSR cpsr = 0;
cpsr.mode = MODE_USER;
@ -99,12 +101,16 @@ namespace ArmISA
updateRegMap(cpsr);
SCTLR sctlr = 0;
sctlr.nmfi = 1;
sctlr.nmfi = (bool)sctlr_rst.nmfi;
sctlr.v = (bool)sctlr_rst.v;
sctlr.u = 1;
sctlr.rao1 = 1;
sctlr.rao2 = 1;
sctlr.rao3 = 1;
sctlr.rao4 = 1;
miscRegs[MISCREG_SCTLR] = sctlr;
miscRegs[MISCREG_SCTLR_RST] = sctlr_rst;
/*
* Technically this should be 0, but we don't support those
@ -327,6 +333,14 @@ namespace ArmISA
(miscRegs[MISCREG_FPEXC] & ~fpexcMask);
}
break;
case MISCREG_SCTLR:
{
SCTLR sctlr = miscRegs[MISCREG_SCTLR];
SCTLR new_sctlr = newVal;
new_sctlr.nmfi = (bool)sctlr.nmfi;
miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr;
return;
}
case MISCREG_TLBTR:
case MISCREG_MVFR0:
case MISCREG_MVFR1:
@ -334,7 +348,7 @@ namespace ArmISA
case MISCREG_FPSID:
return;
}
return setMiscRegNoEffect(misc_reg, newVal);
setMiscRegNoEffect(misc_reg, newVal);
}
int
@ -384,6 +398,10 @@ namespace ArmISA
ISA()
{
SCTLR sctlr;
sctlr = 0;
miscRegs[MISCREG_SCTLR_RST] = sctlr;
clear();
}
};

View file

@ -109,9 +109,10 @@ format DataOp {
#endif
}
default: PredImmOp::msr_i_cpsr({{
SCTLR sctlr = Sctlr;
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes,
rotated_imm, RN, false);
rotated_imm, RN, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
}});

View file

@ -233,8 +233,9 @@ let {{
buildRegRegDataInst(mnem, regRegCode, flagType)
if subsPcLr:
code += '''
SCTLR sctlr = Sctlr;
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true);
cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
'''

View file

@ -137,11 +137,12 @@ let {{
wbDiff = 8
accCode = '''
CPSR cpsr = Cpsr;
SCTLR sctlr = Sctlr;
NPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
uint32_t newCpsr =
cpsrWriteByInstr(cpsr | CondCodes,
cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
0xF, true);
0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
'''

View file

@ -69,8 +69,9 @@ let {{
microLdrRetUopCode = '''
CPSR cpsr = Cpsr;
SCTLR sctlr = Sctlr;
uint32_t newCpsr =
cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true);
cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);

View file

@ -77,8 +77,9 @@ let {{
exec_output += PredOpExecute.subst(mrsSpsrIop)
msrCpsrRegCode = '''
SCTLR sctlr = Sctlr;
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false);
cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
'''
@ -98,8 +99,9 @@ let {{
exec_output += PredOpExecute.subst(msrSpsrRegIop)
msrCpsrImmCode = '''
SCTLR sctlr = Sctlr;
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false);
cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
'''
@ -577,13 +579,14 @@ let {{
bool setMode = bits(imm, 8);
bool enable = bits(imm, 9);
CPSR cpsr = Cpsr;
SCTLR sctlr = Sctlr;
if (cpsr.mode != MODE_USER) {
if (enable) {
if (f) cpsr.f = 0;
if (i) cpsr.i = 0;
if (a) cpsr.a = 0;
} else {
if (f) cpsr.f = 1;
if (f && !sctlr.nmfi) cpsr.f = 1;
if (i) cpsr.i = 1;
if (a) cpsr.a = 1;
}

View file

@ -110,6 +110,7 @@ namespace ArmISA
const int LogVMPageSize = 12; // 4K bytes
const int VMPageSize = (1 << LogVMPageSize);
// Shouldn't this be 1 because of Thumb?! Dynamic? --Ali
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
const int MachineBytes = 4;
@ -122,6 +123,15 @@ namespace ArmISA
// Memory accesses cannot be unaligned
const bool HasUnalignedMemAcc = false;
enum InterruptTypes
{
INT_RST,
INT_ABT,
INT_IRQ,
INT_FIQ,
NumInterruptTypes
};
// These otherwise unused bits of the PC are used to select a mode
// like the J and T bits of the CPSR.
static const Addr PcJBitShift = 33;

View file

@ -80,6 +80,7 @@ namespace ArmISA
MISCREG_FPEXC,
MISCREG_MVFR0,
MISCREG_MVFR1,
MISCREG_SCTLR_RST,
MISCREG_SEV_MAILBOX,
// CP15 registers
@ -191,7 +192,7 @@ namespace ArmISA
"cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc",
"spsr_mon", "spsr_und", "spsr_abt",
"fpsr", "fpsid", "fpscr", "fpexc", "mvfr0", "mvfr1",
"sev_mailbox",
"sctlr_rst", "sev_mailbox",
"sctlr", "dccisw", "dccimvac", "dccmvac",
"contextidr", "tpidrurw", "tpidruro", "tpidrprw",
"cp15isb", "cp15dsb", "cp15dmb", "cpacr",

View file

@ -254,6 +254,7 @@ class SimpleThread : public ThreadState
PC = nextPC = nextNPC = 0;
memset(intRegs, 0, sizeof(intRegs));
memset(floatRegs.i, 0, sizeof(floatRegs.i));
isa.clear();
}
//