diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/alpha/interrupts.hh --- a/src/arch/alpha/interrupts.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/alpha/interrupts.hh Fri Feb 24 18:34:02 2012 +0000 @@ -73,7 +73,7 @@ } void - setCPU(BaseCPU * _cpu) + setCPU(BaseCPU * _cpu, bool defer_init) { cpu = _cpu; } diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/arm/interrupts.hh --- a/src/arch/arm/interrupts.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/arm/interrupts.hh Fri Feb 24 18:34:02 2012 +0000 @@ -66,7 +66,7 @@ public: void - setCPU(BaseCPU * _cpu) + setCPU(BaseCPU * _cpu, bool defer_init) { cpu = _cpu; } diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/mips/interrupts.hh --- a/src/arch/mips/interrupts.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/mips/interrupts.hh Fri Feb 24 18:34:02 2012 +0000 @@ -63,7 +63,7 @@ } void - setCPU(BaseCPU *_cpu) + setCPU(BaseCPU *_cpu, bool defer_init) {} // post(int int_num, int index) is responsible diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/power/interrupts.hh --- a/src/arch/power/interrupts.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/power/interrupts.hh Fri Feb 24 18:34:02 2012 +0000 @@ -57,7 +57,7 @@ {} void - setCPU(BaseCPU * _cpu) + setCPU(BaseCPU * _cpu, bool defer_init) { cpu = _cpu; } diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/sparc/interrupts.hh --- a/src/arch/sparc/interrupts.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/sparc/interrupts.hh Fri Feb 24 18:34:02 2012 +0000 @@ -54,7 +54,7 @@ public: void - setCPU(BaseCPU * _cpu) + setCPU(BaseCPU * _cpu, bool defer_init) { cpu = _cpu; } diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/x86/interrupts.hh --- a/src/arch/x86/interrupts.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/x86/interrupts.hh Fri Feb 24 18:34:02 2012 +0000 @@ -191,6 +191,9 @@ // Port for receiving interrupts IntPort intSlavePort; + // Should we defer initialisation or not + bool deferInit; + public: int getInitialApicId() { return initialApicId; } @@ -200,7 +203,7 @@ */ typedef X86LocalApicParams Params; - void setCPU(BaseCPU * newCPU); + void setCPU(BaseCPU * newCPU, bool defer_init); void setClock(Tick newClock) diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/x86/interrupts.cc --- a/src/arch/x86/interrupts.cc Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/x86/interrupts.cc Fri Feb 24 18:34:02 2012 +0000 @@ -281,8 +281,12 @@ void -X86ISA::Interrupts::setCPU(BaseCPU * newCPU) +X86ISA::Interrupts::setCPU(BaseCPU * newCPU, bool defer_init) { + // called both by the constructor of the CPU, and when switching a + // CPU in through takeOverFrom, and we need to know this to + // potentially defer initialisation (since it assumes our ports + // are connected) assert(newCPU); if (cpu != NULL && cpu->cpuId() != newCPU->cpuId()) { panic("Local APICs can't be moved between CPUs" @@ -291,19 +295,27 @@ cpu = newCPU; initialApicId = cpu->cpuId(); regs[APIC_ID] = (initialApicId << 24); + // if we previously deferred initialisation, and now we should + // not, go ahead and do it + if (deferInit && !defer_init) + init(); + deferInit = defer_init; } void X86ISA::Interrupts::init() { - // - // The local apic must register its address ranges on both its pio port - // via the basicpiodevice(piodevice) init() function and its int port - // that it inherited from IntDev. Note IntDev is not a SimObject itself. - // - BasicPioDevice::init(); - IntDev::init(); + // if the CPU is to be switched in later it is not yet connected and + // we have to defer the initialisation + if (!deferInit) { + // The local apic must register its address ranges on both its + // pio port via the basicpiodevice(piodevice) init() function + // and its int port that it inherited from IntDev. Note + // IntDev is not a SimObject itself. + BasicPioDevice::init(); + IntDev::init(); + } } @@ -613,7 +625,7 @@ pendingStartup(false), startupVector(0), startedUp(false), pendingUnmaskableInt(false), pendingIPIs(0), cpu(NULL), - intSlavePort(name() + ".int_slave", this, this, latency) + intSlavePort(name() + ".int_slave", this, this, latency), deferInit(true) { pioSize = PageBytes; memset(regs, 0, sizeof(regs)); diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/x86/pagetable_walker.hh --- a/src/arch/x86/pagetable_walker.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/x86/pagetable_walker.hh Fri Feb 24 18:34:02 2012 +0000 @@ -80,7 +80,6 @@ friend class WalkerPort; WalkerPort port; - Port *getPort(const std::string &if_name, int idx = -1); // State to track each walk of the page table class WalkerState : public FastAlloc @@ -168,6 +167,8 @@ Fault startFunctional(ThreadContext * _tc, Addr &addr, Addr &pageSize, BaseTLB::Mode mode); + Port *getPort(const std::string &if_name, int idx = -1); + protected: // The TLB we're supposed to load. TLB * tlb; diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/x86/tlb.hh --- a/src/arch/x86/tlb.hh Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/x86/tlb.hh Fri Feb 24 18:34:02 2012 +0000 @@ -120,6 +120,9 @@ // Checkpointing virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); + + // Get the port from the table walker and return it + virtual Port *getPort(); }; } diff -r 241ee47b0dc6 -r 0a27efea892b src/arch/x86/tlb.cc --- a/src/arch/x86/tlb.cc Fri Feb 24 11:52:49 2012 -0500 +++ b/src/arch/x86/tlb.cc Fri Feb 24 18:34:02 2012 +0000 @@ -421,6 +421,12 @@ { } +Port* +TLB::getPort() +{ + return walker->getPort("port"); +} + } // namespace X86ISA X86ISA::TLB * diff -r 241ee47b0dc6 -r 0a27efea892b src/cpu/base.cc --- a/src/cpu/base.cc Fri Feb 24 11:52:49 2012 -0500 +++ b/src/cpu/base.cc Fri Feb 24 18:34:02 2012 +0000 @@ -222,7 +222,9 @@ // Check if CPU model has interrupts connected. The CheckerCPU // cannot take interrupts directly for example. if (interrupts) - interrupts->setCPU(this); + // let the interrupt device know if it should defer its + // initialisation based on our deferred registration + interrupts->setCPU(this, params()->defer_registration); if (FullSystem) { profileEvent = NULL; @@ -455,7 +457,9 @@ } interrupts = oldCPU->interrupts; - interrupts->setCPU(this); + // let the interrupt device know if it should initialise at this + // point based on the CPU's deferred registration + interrupts->setCPU(this, params()->defer_registration); if (FullSystem) { for (ThreadID i = 0; i < size; ++i)