}
bool
-ArmISA::Interrupts::takeInt(ThreadContext *tc, InterruptTypes int_type) const
+ArmISA::Interrupts::takeInt(InterruptTypes int_type) const
{
// Table G1-17~19 of ARM V8 ARM
InterruptMask mask;
class Interrupts : public BaseInterrupts
{
private:
- BaseCPU * cpu;
-
bool interrupts[NumInterruptTypes];
uint64_t intStatus;
public:
- void
- setCPU(BaseCPU * _cpu)
- {
- cpu = _cpu;
- }
-
typedef ArmInterruptsParams Params;
const Params *
return dynamic_cast<const Params *>(_params);
}
- Interrupts(Params * p) : BaseInterrupts(p), cpu(NULL)
+ Interrupts(Params * p) : BaseInterrupts(p)
{
clearAll();
}
INT_MASK_P // pending
};
- bool takeInt(ThreadContext *tc, InterruptTypes int_type) const;
+ bool takeInt(InterruptTypes int_type) const;
bool
- checkInterrupts(ThreadContext *tc) const
+ checkInterrupts() const
{
HCR hcr = tc->readMiscReg(MISCREG_HCR);
(hcr.va && allowVAbort)) )
return false;
- bool take_irq = takeInt(tc, INT_IRQ);
- bool take_fiq = takeInt(tc, INT_FIQ);
- bool take_ea = takeInt(tc, INT_ABT);
+ bool take_irq = takeInt(INT_IRQ);
+ bool take_fiq = takeInt(INT_FIQ);
+ bool take_ea = takeInt(INT_ABT);
return ((interrupts[INT_IRQ] && take_irq) ||
(interrupts[INT_FIQ] && take_fiq) ||
}
Fault
- getInterrupt(ThreadContext *tc)
+ getInterrupt() override
{
- assert(checkInterrupts(tc));
+ assert(checkInterrupts());
HCR hcr = tc->readMiscReg(MISCREG_HCR);
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
bool allowVFiq = !cpsr.f && hcr.fmo && !isSecure && !isHypMode;
bool allowVAbort = !cpsr.a && hcr.amo && !isSecure && !isHypMode;
- bool take_irq = takeInt(tc, INT_IRQ);
- bool take_fiq = takeInt(tc, INT_FIQ);
- bool take_ea = takeInt(tc, INT_ABT);
+ bool take_irq = takeInt(INT_IRQ);
+ bool take_fiq = takeInt(INT_FIQ);
+ bool take_ea = takeInt(INT_ABT);
if (interrupts[INT_IRQ] && take_irq)
return std::make_shared<Interrupt>();
panic("intStatus and interrupts not in sync\n");
}
- void
- updateIntrInfo(ThreadContext *tc)
- {
- ; // nothing to do
- }
+ void updateIntrInfo() override {} // nothing to do
void
- serialize(CheckpointOut &cp) const
+ serialize(CheckpointOut &cp) const override
{
SERIALIZE_ARRAY(interrupts, NumInterruptTypes);
SERIALIZE_SCALAR(intStatus);
}
void
- unserialize(CheckpointIn &cp)
+ unserialize(CheckpointIn &cp) override
{
UNSERIALIZE_ARRAY(interrupts, NumInterruptTypes);
UNSERIALIZE_SCALAR(intStatus);
SevMailbox = 0;
PseudoInst::quiesceSkip(tc);
} else if (tc->getCpuPtr()->getInterruptController(
- tc->threadId())->checkInterrupts(tc)) {
+ tc->threadId())->checkInterrupts()) {
PseudoInst::quiesceSkip(tc);
} else {
fault = trapWFx(tc, cpsr, scr, true);
class BaseInterrupts : public SimObject
{
protected:
- BaseCPU *cpu;
+ ThreadContext *tc = nullptr;
public:
typedef BaseInterruptsParams Params;
BaseInterrupts(Params *p) : SimObject(p) {}
- virtual void setCPU(BaseCPU * newCPU) = 0;
+ virtual void setThreadContext(ThreadContext *_tc) { tc = _tc; }
const Params *
params() const
/*
* Return whether there are any interrupts waiting to be recognized.
*/
- virtual bool checkInterrupts(ThreadContext *tc) const = 0;
+ virtual bool checkInterrupts() const = 0;
/*
* Return an interrupt to process. This should return an interrupt exactly
* when checkInterrupts returns true.
*/
- virtual Fault getInterrupt(ThreadContext *tc) = 0;
+ virtual Fault getInterrupt() = 0;
/*
* Update interrupt related state after an interrupt has been processed.
*/
- virtual void updateIntrInfo(ThreadContext *tc) = 0;
+ virtual void updateIntrInfo() = 0;
/*
* Old functions needed for compatability but which will be phased out
{
static inline uint8_t
-getCauseIP(ThreadContext *tc) {
+getCauseIP(ThreadContext *tc)
+{
CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
return cause.ip;
}
static inline void
-setCauseIP(ThreadContext *tc, uint8_t val) {
+setCauseIP(ThreadContext *tc, uint8_t val)
+{
CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
cause.ip = val;
tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
}
void
-Interrupts::post(int int_num, ThreadContext* tc)
+Interrupts::post(int int_num)
{
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
if (int_num < 0 || int_num >= NumInterruptLevels)
}
void
-Interrupts::clear(int int_num, ThreadContext* tc)
+Interrupts::clear(int int_num)
{
DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
if (int_num < 0 || int_num >= NumInterruptLevels)
}
void
-Interrupts::clearAll(ThreadContext *tc)
+Interrupts::clearAll()
{
DPRINTF(Interrupt, "Interrupts all cleared\n");
uint8_t intstatus = 0;
setCauseIP(tc, intstatus);
}
-void
-Interrupts::clearAll()
-{
- fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
-}
-
bool
-Interrupts::checkInterrupts(ThreadContext *tc) const
+Interrupts::checkInterrupts() const
{
- if (!interruptsPending(tc))
+ if (!interruptsPending())
return false;
//Check if there are any outstanding interrupts
}
Fault
-Interrupts::getInterrupt(ThreadContext * tc)
+Interrupts::getInterrupt()
{
- assert(checkInterrupts(tc));
+ assert(checkInterrupts());
StatusReg M5_VAR_USED status = tc->readMiscRegNoEffect(MISCREG_STATUS);
CauseReg M5_VAR_USED cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
}
bool
-Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
+Interrupts::onCpuTimerInterrupt() const
{
RegVal compare = tc->readMiscRegNoEffect(MISCREG_COMPARE);
RegVal count = tc->readMiscRegNoEffect(MISCREG_COUNT);
return false;
}
-void
-Interrupts::updateIntrInfo(ThreadContext *tc)
-{
- //Nothing needs to be done.
-}
+void Interrupts::updateIntrInfo() {} // Nothing needs to be done.
bool
-Interrupts::interruptsPending(ThreadContext *tc) const
+Interrupts::interruptsPending() const
{
//if there is a on cpu timer interrupt (i.e. Compare == Count)
//update CauseIP before proceeding to interrupt
- if (onCpuTimerInterrupt(tc)) {
- DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc) == true\n");
+ if (onCpuTimerInterrupt()) {
+ DPRINTF(Interrupt, "Interrupts OnCpuTimerInterrupt() == true\n");
//determine timer interrupt IP #
IntCtlReg intCtl = tc->readMiscRegNoEffect(MISCREG_INTCTL);
uint8_t intStatus = getCauseIP(tc);
return dynamic_cast<const Params *>(_params);
}
- Interrupts(Params * p) : BaseInterrupts(p)
- {
- }
-
- void setCPU(BaseCPU *_cpu) override {}
+ Interrupts(Params * p) : BaseInterrupts(p) {}
// post(int int_num, int index) is responsible
// for posting an interrupt. It sets a bit
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
- void post(int int_num, ThreadContext *tc);
+ void post(int int_num);
void post(int int_num, int index) override;
// clear(int int_num, int index) is responsible
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
- void clear(int int_num, ThreadContext* tc);
+ void clear(int int_num);
void clear(int int_num, int index) override;
// clearAll() is responsible
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
- void clearAll(ThreadContext *tc);
void clearAll() override;
- // getInterrupt(ThreadContext * tc) checks if an interrupt
+ // getInterrupt() checks if an interrupt
// should be returned. It ands the interrupt mask and
// and interrupt pending bits to see if one exists. It
// also makes sure interrupts are enabled (IE) and
// that ERL and ERX are not set
//
- Fault getInterrupt(ThreadContext *tc) override;
+ Fault getInterrupt() override;
- // updateIntrInfo(ThreadContext *tc) const syncs the
+ // updateIntrInfo() const syncs the
// MIPS cause register with the instatus variable. instatus
// is essentially a copy of the MIPS cause[IP7:IP0]
//
- void updateIntrInfo(ThreadContext *tc) override;
- bool interruptsPending(ThreadContext *tc) const;
- bool onCpuTimerInterrupt(ThreadContext *tc) const;
- bool checkInterrupts(ThreadContext *tc) const override;
+ void updateIntrInfo() override;
+ bool interruptsPending() const;
+ bool onCpuTimerInterrupt() const;
+ bool checkInterrupts() const override;
void
serialize(CheckpointOut &cp) const override
class Interrupts : public BaseInterrupts
{
- private:
- BaseCPU * cpu;
-
public:
typedef PowerInterruptsParams Params;
return dynamic_cast<const Params *>(_params);
}
- Interrupts(Params * p) : BaseInterrupts(p), cpu(NULL)
- {}
-
- void
- setCPU(BaseCPU * _cpu)
- {
- cpu = _cpu;
- }
+ Interrupts(Params *p) : BaseInterrupts(p) {}
void
post(int int_num, int index)
}
bool
- checkInterrupts(ThreadContext *tc) const
+ checkInterrupts() const
{
panic("Interrupts::checkInterrupts not implemented.\n");
}
Fault
- getInterrupt(ThreadContext *tc)
+ getInterrupt()
{
- assert(checkInterrupts(tc));
+ assert(checkInterrupts());
panic("Interrupts::getInterrupt not implemented.\n");
}
void
- updateIntrInfo(ThreadContext *tc)
+ updateIntrInfo()
{
panic("Interrupts::updateIntrInfo not implemented.\n");
}
class Interrupts : public BaseInterrupts
{
private:
- BaseCPU * cpu;
std::bitset<NumInterruptTypes> ip;
std::bitset<NumInterruptTypes> ie;
return dynamic_cast<const Params *>(_params);
}
- Interrupts(Params * p) : BaseInterrupts(p), cpu(nullptr), ip(0), ie(0) {}
-
- void setCPU(BaseCPU * _cpu) { cpu = _cpu; }
+ Interrupts(Params * p) : BaseInterrupts(p), ip(0), ie(0) {}
std::bitset<NumInterruptTypes>
- globalMask(ThreadContext *tc) const
+ globalMask() const
{
INTERRUPT mask = 0;
STATUS status = tc->readMiscReg(MISCREG_STATUS);
}
bool checkInterrupt(int num) const { return ip[num] && ie[num]; }
- bool checkInterrupts(ThreadContext *tc) const
+ bool checkInterrupts() const
{
- return (ip & ie & globalMask(tc)).any();
+ return (ip & ie & globalMask()).any();
}
Fault
- getInterrupt(ThreadContext *tc)
+ getInterrupt()
{
- assert(checkInterrupts(tc));
- std::bitset<NumInterruptTypes> mask = globalMask(tc);
+ assert(checkInterrupts());
+ std::bitset<NumInterruptTypes> mask = globalMask();
for (int c = 0; c < NumInterruptTypes; c++)
if (checkInterrupt(c) && mask[c])
return std::make_shared<InterruptFault>(c);
return NoFault;
}
- void updateIntrInfo(ThreadContext *tc) {}
+ void updateIntrInfo() {}
void
post(int int_num, int index)
class Interrupts : public BaseInterrupts
{
private:
- BaseCPU * cpu;
-
uint64_t interrupts[NumInterruptTypes];
uint64_t intStatus;
public:
- void
- setCPU(BaseCPU * _cpu) override
- {
- cpu = _cpu;
- }
-
typedef SparcInterruptsParams Params;
const Params *
return dynamic_cast<const Params *>(_params);
}
- Interrupts(Params * p) : BaseInterrupts(p), cpu(NULL)
+ Interrupts(Params * p) : BaseInterrupts(p)
{
clearAll();
}
}
bool
- checkInterrupts(ThreadContext *tc) const override
+ checkInterrupts() const override
{
if (!intStatus)
return false;
}
Fault
- getInterrupt(ThreadContext *tc) override
+ getInterrupt() override
{
- assert(checkInterrupts(tc));
+ assert(checkInterrupts());
HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
return NoFault;
}
- void updateIntrInfo(ThreadContext *tc) override {}
+ void updateIntrInfo() override {}
uint64_t
get_vec(int int_num)
}
}
if (FullSystem)
- cpu->wakeup(0);
+ tc->getCpuPtr()->wakeup(0);
}
void
-X86ISA::Interrupts::setCPU(BaseCPU * newCPU)
+X86ISA::Interrupts::setThreadContext(ThreadContext *_tc)
{
- assert(newCPU);
- if (cpu != NULL && cpu->cpuId() != newCPU->cpuId()) {
- panic("Local APICs can't be moved between CPUs"
- " with different IDs.\n");
- }
- cpu = newCPU;
- initialApicId = cpu->cpuId();
+ assert(_tc);
+ panic_if(tc != NULL && tc->cpuId() != _tc->cpuId(),
+ "Local APICs can't be moved between CPUs with different IDs.");
+
+ BaseInterrupts::setThreadContext(_tc);
+
+ initialApicId = tc->cpuId();
regs[APIC_ID] = (initialApicId << 24);
pioAddr = x86LocalAPICAddress(initialApicId, 0);
}
AddrRangeList
X86ISA::Interrupts::getAddrRanges() const
{
- assert(cpu);
+ assert(tc);
AddrRangeList ranges;
ranges.push_back(RangeSize(pioAddr, PageBytes));
return ranges;
}
-X86ISA::Interrupts::Interrupts(Params * p)
+X86ISA::Interrupts::Interrupts(Params *p)
: BaseInterrupts(p), sys(p->system), clockDomain(*p->clk_domain),
apicTimerEvent([this]{ processApicTimerEvent(); }, name()),
pendingSmi(false), smiVector(0),
pendingInit(false), initVector(0),
pendingStartup(false), startupVector(0),
startedUp(false), pendingUnmaskableInt(false),
- pendingIPIs(0), cpu(NULL),
+ pendingIPIs(0),
intSlavePort(name() + ".int_slave", this, this),
intMasterPort(name() + ".int_master", this, this, p->int_latency),
pioPort(this), pioDelay(p->pio_latency)
bool
-X86ISA::Interrupts::checkInterrupts(ThreadContext *tc) const
+X86ISA::Interrupts::checkInterrupts() const
{
RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS);
if (pendingUnmaskableInt) {
}
Fault
-X86ISA::Interrupts::getInterrupt(ThreadContext *tc)
+X86ISA::Interrupts::getInterrupt()
{
- assert(checkInterrupts(tc));
+ assert(checkInterrupts());
// These are all probably fairly uncommon, so we'll make them easier to
// check for.
if (pendingUnmaskableInt) {
}
void
-X86ISA::Interrupts::updateIntrInfo(ThreadContext *tc)
+X86ISA::Interrupts::updateIntrInfo()
{
- assert(checkInterrupts(tc));
+ assert(checkInterrupts());
if (pendingUnmaskableInt) {
if (pendingSmi) {
DPRINTF(LocalApic, "SMI sent to core.\n");
int divideFromConf(uint32_t conf);
-namespace X86ISA {
+namespace X86ISA
+{
ApicRegIndex decodeAddr(Addr paddr);
void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
- BaseCPU *cpu;
-
int initialApicId;
// Ports for interrupts.
*/
typedef X86LocalApicParams Params;
- void setCPU(BaseCPU * newCPU) override;
+ void setThreadContext(ThreadContext *_tc) override;
const Params *
params() const
* Functions for retrieving interrupts for the CPU to handle.
*/
- bool checkInterrupts(ThreadContext *tc) const override;
+ bool checkInterrupts() const override;
/**
* Check if there are pending interrupts without ignoring the
* interrupts disabled flag.
* @return true there are unmaskable interrupts pending.
*/
bool hasPendingUnmaskable() const { return pendingUnmaskableInt; }
- Fault getInterrupt(ThreadContext *tc) override;
- void updateIntrInfo(ThreadContext *tc) override;
+ Fault getInterrupt() override;
+ void updateIntrInfo() override;
/*
* Serialization.
}
}
- // The interrupts should always be present unless this CPU is
- // switched in later or in case it is a checker CPU
- if (!params()->switched_out && !is_checker) {
- fatal_if(interrupts.size() != numThreads,
- "CPU %s has %i interrupt controllers, but is expecting one "
- "per thread (%i)\n",
- name(), interrupts.size(), numThreads);
- for (ThreadID tid = 0; tid < numThreads; tid++)
- interrupts[tid]->setCPU(this);
- }
-
if (FullSystem) {
if (params()->profile)
profileEvent = new EventFunctionWrapper(
{
assert(system->multiThread || numThreads == 1);
+ fatal_if(interrupts.size() != numThreads,
+ "CPU %s has %i interrupt controllers, but is expecting one "
+ "per thread (%i)\n",
+ name(), interrupts.size(), numThreads);
+
ThreadID size = threadContexts.size();
for (ThreadID tid = 0; tid < size; ++tid) {
ThreadContext *tc = threadContexts[tid];
if (!FullSystem)
tc->getProcessPtr()->assignThreadContext(tc->contextId());
+
+ interrupts[tid]->setThreadContext(tc);
}
}
interrupts = oldCPU->interrupts;
for (ThreadID tid = 0; tid < numThreads; tid++) {
- interrupts[tid]->setCPU(this);
+ interrupts[tid]->setThreadContext(threadContexts[tid]);
}
oldCPU->interrupts.clear();
}
bool
- checkInterrupts(ThreadContext *tc) const
+ checkInterrupts(ThreadID tid) const
{
- return FullSystem && interrupts[tc->threadId()]->checkInterrupts(tc);
+ return FullSystem && interrupts[tid]->checkInterrupts();
}
void processProfileEvent();
{
DPRINTF(IntrControl, "Check pending interrupts for CPU %d\n", cpu_id);
auto *tc = sys->threads[cpu_id];
- return tc->getCpuPtr()->checkInterrupts(tc);
+ return tc->getCpuPtr()->checkInterrupts(tc->threadId());
}
IntrControl *
// they are getInterrupt() and updateIntrInfo() are called
// atomically.
EventQueue::ScopedMigration migrate(interrupts[0]->eventQueue());
- fault = interrupts[0]->getInterrupt(tc);
- interrupts[0]->updateIntrInfo(tc);
+ fault = interrupts[0]->getInterrupt();
+ interrupts[0]->updateIntrInfo();
}
X86Interrupt *x86int(dynamic_cast<X86Interrupt *>(fault.get()));
// the thread context and check if there are /really/
// interrupts that should be delivered now.
syncThreadContext();
- if (lapic->checkInterrupts(tc)) {
+ if (lapic->checkInterrupts()) {
DPRINTF(KvmInt,
"M5 has pending interrupts, delivering interrupt.\n");
bool
Execute::isInterrupted(ThreadID thread_id) const
{
- return cpu.checkInterrupts(cpu.getContext(thread_id));
+ return cpu.checkInterrupts(thread_id);
}
bool
DPRINTF(MinorInterrupt, "Considering interrupt status from PC: %s\n",
cpu.getContext(thread_id)->pcState());
- Fault interrupt = cpu.getInterruptController(thread_id)->getInterrupt
- (cpu.getContext(thread_id));
+ Fault interrupt = cpu.getInterruptController(thread_id)->getInterrupt();
if (interrupt != NoFault) {
/* The interrupt *must* set pcState */
- cpu.getInterruptController(thread_id)->updateIntrInfo
- (cpu.getContext(thread_id));
+ cpu.getInterruptController(thread_id)->updateIntrInfo();
interrupt->invoke(cpu.getContext(thread_id));
assert(!lsq.accessesInFlight());
DefaultCommit<Impl>::handleInterrupt()
{
// Verify that we still have an interrupt to handle
- if (!cpu->checkInterrupts(cpu->tcBase(0))) {
+ if (!cpu->checkInterrupts(0)) {
DPRINTF(Commit, "Pending interrupt is cleared by master before "
"it got handled. Restart fetching from the orig path.\n");
toIEW->commitInfo[0].clearInterrupt = true;
{
if (FullSystem) {
// Check if we have a interrupt and get read to handle it
- if (cpu->checkInterrupts(cpu->tcBase(0)))
+ if (cpu->checkInterrupts(0))
propagateInterrupt();
}
//
// If we don't do this, we might end up in a live lock situation
if (!interrupt && avoidQuiesceLiveLock &&
- onInstBoundary && cpu->checkInterrupts(cpu->tcBase(0)))
+ onInstBoundary && cpu->checkInterrupts(0))
squashAfter(tid, head_inst);
} else {
DPRINTF(Commit, "Unable to commit head instruction PC:%s "
FullO3CPU<Impl>::getInterrupts()
{
// Check if there are any outstanding interrupts
- return this->interrupts[0]->getInterrupt(this->threadContexts[0]);
+ return this->interrupts[0]->getInterrupt();
}
template <class Impl>
// @todo: Allow other threads to handle interrupts.
assert(interrupt != NoFault);
- this->interrupts[0]->updateIntrInfo(this->threadContexts[0]);
+ this->interrupts[0]->updateIntrInfo();
DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
this->trap(interrupt, 0, nullptr);
SimpleThread* thread = t_info.thread;
ThreadContext* tc = thread->getTC();
- if (checkInterrupts(tc)) {
- Fault interrupt = interrupts[curThread]->getInterrupt(tc);
+ if (checkInterrupts(curThread)) {
+ Fault interrupt = interrupts[curThread]->getInterrupt();
if (interrupt != NoFault) {
t_info.fetchOffset = 0;
- interrupts[curThread]->updateIntrInfo(tc);
+ interrupts[curThread]->updateIntrInfo();
interrupt->invoke(tc);
thread->decoder.reset();
}