diff options
author | Mitch Hayenga <mitch.hayenga@arm.com> | 2015-09-30 11:14:19 -0500 |
---|---|---|
committer | Mitch Hayenga <mitch.hayenga@arm.com> | 2015-09-30 11:14:19 -0500 |
commit | a5c4eb3de9deb3a71a6a5230a25ff5962e584980 (patch) | |
tree | 874b659c6a5eaa1316cde9eb82ec7d08badf638a /src/cpu | |
parent | e255fa053f8d105de8d188077a318124a3aad9ce (diff) | |
download | gem5-a5c4eb3de9deb3a71a6a5230a25ff5962e584980.tar.xz |
isa,cpu: Add support for FS SMT Interrupts
Adds per-thread interrupt controllers and thread/context logic
so that interrupts properly get routed in SMT systems.
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/BaseCPU.py | 40 | ||||
-rw-r--r-- | src/cpu/base.cc | 17 | ||||
-rw-r--r-- | src/cpu/base.hh | 24 | ||||
-rw-r--r-- | src/cpu/dummy_checker.cc | 1 | ||||
-rw-r--r-- | src/cpu/intr_control.cc | 4 | ||||
-rw-r--r-- | src/cpu/kvm/x86_cpu.cc | 12 | ||||
-rw-r--r-- | src/cpu/minor/execute.cc | 6 | ||||
-rw-r--r-- | src/cpu/o3/checker.cc | 1 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 6 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 4 |
10 files changed, 61 insertions, 54 deletions
diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 9aa24c97b..a54a63b46 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -149,40 +149,40 @@ class BaseCPU(MemObject): if buildEnv['TARGET_ISA'] == 'sparc': dtb = Param.SparcTLB(SparcTLB(), "Data TLB") itb = Param.SparcTLB(SparcTLB(), "Instruction TLB") - interrupts = Param.SparcInterrupts( - NULL, "Interrupt Controller") + interrupts = VectorParam.SparcInterrupts( + [], "Interrupt Controller") isa = VectorParam.SparcISA([ isa_class() ], "ISA instance") elif buildEnv['TARGET_ISA'] == 'alpha': dtb = Param.AlphaTLB(AlphaDTB(), "Data TLB") itb = Param.AlphaTLB(AlphaITB(), "Instruction TLB") - interrupts = Param.AlphaInterrupts( - NULL, "Interrupt Controller") + interrupts = VectorParam.AlphaInterrupts( + [], "Interrupt Controller") isa = VectorParam.AlphaISA([ isa_class() ], "ISA instance") elif buildEnv['TARGET_ISA'] == 'x86': dtb = Param.X86TLB(X86TLB(), "Data TLB") itb = Param.X86TLB(X86TLB(), "Instruction TLB") - interrupts = Param.X86LocalApic(NULL, "Interrupt Controller") + interrupts = VectorParam.X86LocalApic([], "Interrupt Controller") isa = VectorParam.X86ISA([ isa_class() ], "ISA instance") elif buildEnv['TARGET_ISA'] == 'mips': dtb = Param.MipsTLB(MipsTLB(), "Data TLB") itb = Param.MipsTLB(MipsTLB(), "Instruction TLB") - interrupts = Param.MipsInterrupts( - NULL, "Interrupt Controller") + interrupts = VectorParam.MipsInterrupts( + [], "Interrupt Controller") isa = VectorParam.MipsISA([ isa_class() ], "ISA instance") elif buildEnv['TARGET_ISA'] == 'arm': dtb = Param.ArmTLB(ArmTLB(), "Data TLB") itb = Param.ArmTLB(ArmTLB(), "Instruction TLB") istage2_mmu = Param.ArmStage2MMU(ArmStage2IMMU(), "Stage 2 trans") dstage2_mmu = Param.ArmStage2MMU(ArmStage2DMMU(), "Stage 2 trans") - interrupts = Param.ArmInterrupts( - NULL, "Interrupt Controller") + interrupts = VectorParam.ArmInterrupts( + [], "Interrupt Controller") isa = VectorParam.ArmISA([ isa_class() ], "ISA instance") elif buildEnv['TARGET_ISA'] == 'power': UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") dtb = Param.PowerTLB(PowerTLB(), "Data TLB") itb = Param.PowerTLB(PowerTLB(), "Instruction TLB") - interrupts = Param.PowerInterrupts( - NULL, "Interrupt Controller") + interrupts = VectorParam.PowerInterrupts( + [], "Interrupt Controller") isa = VectorParam.PowerISA([ isa_class() ], "ISA instance") else: print "Don't know what TLB to use for ISA %s" % \ @@ -218,27 +218,29 @@ class BaseCPU(MemObject): _uncached_slave_ports = [] _uncached_master_ports = [] if buildEnv['TARGET_ISA'] == 'x86': - _uncached_slave_ports += ["interrupts.pio", "interrupts.int_slave"] - _uncached_master_ports += ["interrupts.int_master"] + _uncached_slave_ports += ["interrupts[0].pio", + "interrupts[0].int_slave"] + _uncached_master_ports += ["interrupts[0].int_master"] def createInterruptController(self): if buildEnv['TARGET_ISA'] == 'sparc': - self.interrupts = SparcInterrupts() + self.interrupts = [SparcInterrupts() for i in xrange(self.numThreads)] elif buildEnv['TARGET_ISA'] == 'alpha': - self.interrupts = AlphaInterrupts() + self.interrupts = [AlphaInterrupts() for i in xrange(self.numThreads)] elif buildEnv['TARGET_ISA'] == 'x86': self.apic_clk_domain = DerivedClockDomain(clk_domain = Parent.clk_domain, clk_divider = 16) - self.interrupts = X86LocalApic(clk_domain = self.apic_clk_domain, + self.interrupts = [X86LocalApic(clk_domain = self.apic_clk_domain, pio_addr=0x2000000000000000) + for i in xrange(self.numThreads)] _localApic = self.interrupts elif buildEnv['TARGET_ISA'] == 'mips': - self.interrupts = MipsInterrupts() + self.interrupts = [MipsInterrupts() for i in xrange(self.numThreads)] elif buildEnv['TARGET_ISA'] == 'arm': - self.interrupts = ArmInterrupts() + self.interrupts = [ArmInterrupts() for i in xrange(self.numThreads)] elif buildEnv['TARGET_ISA'] == 'power': - self.interrupts = PowerInterrupts() + self.interrupts = [PowerInterrupts() for i in xrange(self.numThreads)] else: print "Don't know what Interrupt Controller to use for ISA %s" % \ buildEnv['TARGET_ISA'] diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 3b0809d09..a1dfa42ce 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -237,8 +237,10 @@ BaseCPU::BaseCPU(Params *p, bool is_checker) // 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) { - if (interrupts) { - interrupts->setCPU(this); + if (!interrupts.empty()) { + for (ThreadID tid = 0; tid < numThreads; tid++) { + interrupts[tid]->setCPU(this); + } } else { fatal("CPU %s has no interrupt controller.\n" "Ensure createInterruptController() is called.\n", name()); @@ -583,8 +585,10 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) } interrupts = oldCPU->interrupts; - interrupts->setCPU(this); - oldCPU->interrupts = NULL; + for (ThreadID tid = 0; tid < numThreads; tid++) { + interrupts[tid]->setCPU(this); + } + oldCPU->interrupts.clear(); if (FullSystem) { for (ThreadID i = 0; i < size; ++i) @@ -656,11 +660,10 @@ BaseCPU::serialize(CheckpointOut &cp) const * system. */ SERIALIZE_SCALAR(_pid); - interrupts->serialize(cp); - // Serialize the threads, this is done by the CPU implementation. for (ThreadID i = 0; i < numThreads; ++i) { ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); + interrupts[i]->serialize(cp); serializeThread(cp, i); } } @@ -673,11 +676,11 @@ BaseCPU::unserialize(CheckpointIn &cp) if (!_switchedOut) { UNSERIALIZE_SCALAR(_pid); - interrupts->unserialize(cp); // Unserialize the threads, this is done by the CPU implementation. for (ThreadID i = 0; i < numThreads; ++i) { ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); + interrupts[i]->unserialize(cp); unserializeThread(cp, i); } } diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 0286ac45b..2a57c01ba 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -207,41 +207,45 @@ class BaseCPU : public MemObject TheISA::MicrocodeRom microcodeRom; protected: - TheISA::Interrupts *interrupts; + std::vector<TheISA::Interrupts*> interrupts; public: TheISA::Interrupts * - getInterruptController() + getInterruptController(ThreadID tid) { - return interrupts; + if (interrupts.empty()) + return NULL; + + assert(interrupts.size() > tid); + return interrupts[tid]; } virtual void wakeup() = 0; void - postInterrupt(int int_num, int index) + postInterrupt(ThreadID tid, int int_num, int index) { - interrupts->post(int_num, index); + interrupts[tid]->post(int_num, index); if (FullSystem) wakeup(); } void - clearInterrupt(int int_num, int index) + clearInterrupt(ThreadID tid, int int_num, int index) { - interrupts->clear(int_num, index); + interrupts[tid]->clear(int_num, index); } void - clearInterrupts() + clearInterrupts(ThreadID tid) { - interrupts->clearAll(); + interrupts[tid]->clearAll(); } bool checkInterrupts(ThreadContext *tc) const { - return FullSystem && interrupts->checkInterrupts(tc); + return FullSystem && interrupts[tc->threadId()]->checkInterrupts(tc); } class ProfileEvent : public Event diff --git a/src/cpu/dummy_checker.cc b/src/cpu/dummy_checker.cc index bbd905492..aa4d45e2f 100644 --- a/src/cpu/dummy_checker.cc +++ b/src/cpu/dummy_checker.cc @@ -73,7 +73,6 @@ DummyCheckerParams::create() params->system = system; params->cpu_id = cpu_id; params->profile = profile; - params->interrupts = NULL; params->workload = workload; DummyChecker *cpu = new DummyChecker(params); diff --git a/src/cpu/intr_control.cc b/src/cpu/intr_control.cc index 8f3808889..ca24495f4 100644 --- a/src/cpu/intr_control.cc +++ b/src/cpu/intr_control.cc @@ -51,7 +51,7 @@ IntrControl::post(int cpu_id, int int_num, int index) DPRINTF(IntrControl, "post %d:%d (cpu %d)\n", int_num, index, cpu_id); std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr(); - cpu->postInterrupt(int_num, index); + cpu->postInterrupt(tcvec[cpu_id]->threadId(), int_num, index); } void @@ -60,7 +60,7 @@ IntrControl::clear(int cpu_id, int int_num, int index) DPRINTF(IntrControl, "clear %d:%d (cpu %d)\n", int_num, index, cpu_id); std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr(); - cpu->clearInterrupt(int_num, index); + cpu->clearInterrupt(tcvec[cpu_id]->threadId(), int_num, index); } IntrControl * diff --git a/src/cpu/kvm/x86_cpu.cc b/src/cpu/kvm/x86_cpu.cc index cd46370a4..5312ca55a 100644 --- a/src/cpu/kvm/x86_cpu.cc +++ b/src/cpu/kvm/x86_cpu.cc @@ -1142,9 +1142,9 @@ X86KvmCPU::deliverInterrupts() // call across threads, we might still lose interrupts unless // they are getInterrupt() and updateIntrInfo() are called // atomically. - EventQueue::ScopedMigration migrate(interrupts->eventQueue()); - fault = interrupts->getInterrupt(tc); - interrupts->updateIntrInfo(tc); + EventQueue::ScopedMigration migrate(interrupts[0]->eventQueue()); + fault = interrupts[0]->getInterrupt(tc); + interrupts[0]->updateIntrInfo(tc); } X86Interrupt *x86int(dynamic_cast<X86Interrupt *>(fault.get())); @@ -1187,8 +1187,8 @@ X86KvmCPU::kvmRun(Tick ticks) { struct kvm_run &kvm_run(*getKvmRunState()); - if (interrupts->checkInterruptsRaw()) { - if (interrupts->hasPendingUnmaskable()) { + if (interrupts[0]->checkInterruptsRaw()) { + if (interrupts[0]->hasPendingUnmaskable()) { DPRINTF(KvmInt, "Delivering unmaskable interrupt.\n"); syncThreadContext(); @@ -1200,7 +1200,7 @@ X86KvmCPU::kvmRun(Tick ticks) // the thread context and check if there are /really/ // interrupts that should be delivered now. syncThreadContext(); - if (interrupts->checkInterrupts(tc)) { + if (interrupts[0]->checkInterrupts(tc)) { DPRINTF(KvmInt, "M5 has pending interrupts, delivering interrupt.\n"); diff --git a/src/cpu/minor/execute.cc b/src/cpu/minor/execute.cc index 001515eff..0a2c4b8c8 100644 --- a/src/cpu/minor/execute.cc +++ b/src/cpu/minor/execute.cc @@ -403,12 +403,12 @@ Execute::takeInterrupt(ThreadID thread_id, BranchData &branch) DPRINTF(MinorInterrupt, "Considering interrupt status from PC: %s\n", cpu.getContext(thread_id)->pcState()); - Fault interrupt = cpu.getInterruptController()->getInterrupt + Fault interrupt = cpu.getInterruptController(thread_id)->getInterrupt (cpu.getContext(thread_id)); if (interrupt != NoFault) { /* The interrupt *must* set pcState */ - cpu.getInterruptController()->updateIntrInfo + cpu.getInterruptController(thread_id)->updateIntrInfo (cpu.getContext(thread_id)); interrupt->invoke(cpu.getContext(thread_id)); @@ -1391,7 +1391,7 @@ Execute::evaluate() /* If there was an interrupt signalled, was it acted on now? */ bool took_interrupt = false; - if (cpu.getInterruptController()) { + if (cpu.getInterruptController(0)) { /* This is here because it seems that after drainResume the * interrupt controller isn't always set */ interrupted = drainState == NotDraining && isInterrupted(0); diff --git a/src/cpu/o3/checker.cc b/src/cpu/o3/checker.cc index ce7a99f0f..be685d7c2 100644 --- a/src/cpu/o3/checker.cc +++ b/src/cpu/o3/checker.cc @@ -86,7 +86,6 @@ O3CheckerParams::create() params->system = system; params->cpu_id = cpu_id; params->profile = profile; - params->interrupts = NULL; params->workload = workload; O3Checker *cpu = new O3Checker(params); diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 4ab004817..d4ee5ffe7 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -392,7 +392,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) } // FullO3CPU always requires an interrupt controller. - if (!params->switched_out && !interrupts) { + if (!params->switched_out && interrupts.empty()) { fatal("FullO3CPU %s has no interrupt controller.\n" "Ensure createInterruptController() is called.\n", name()); } @@ -935,7 +935,7 @@ Fault FullO3CPU<Impl>::getInterrupts() { // Check if there are any outstanding interrupts - return this->interrupts->getInterrupt(this->threadContexts[0]); + return this->interrupts[0]->getInterrupt(this->threadContexts[0]); } template <class Impl> @@ -949,7 +949,7 @@ FullO3CPU<Impl>::processInterrupts(const Fault &interrupt) // @todo: Allow other threads to handle interrupts. assert(interrupt != NoFault); - this->interrupts->updateIntrInfo(this->threadContexts[0]); + this->interrupts[0]->updateIntrInfo(this->threadContexts[0]); DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); this->trap(interrupt, 0, nullptr); diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 6e8845bf7..b0810517f 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -435,11 +435,11 @@ BaseSimpleCPU::checkForInterrupts() ThreadContext* tc = thread->getTC(); if (checkInterrupts(tc)) { - Fault interrupt = interrupts->getInterrupt(tc); + Fault interrupt = interrupts[curThread]->getInterrupt(tc); if (interrupt != NoFault) { t_info.fetchOffset = 0; - interrupts->updateIntrInfo(tc); + interrupts[curThread]->updateIntrInfo(tc); interrupt->invoke(tc); thread->decoder.reset(); } |