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.
This commit is contained in:
parent
e255fa053f
commit
a5c4eb3de9
23 changed files with 129 additions and 102 deletions
|
@ -176,9 +176,9 @@ def build_test_system(np):
|
||||||
cpu.itb.walker.port = test_sys.ruby._cpu_ports[i].slave
|
cpu.itb.walker.port = test_sys.ruby._cpu_ports[i].slave
|
||||||
cpu.dtb.walker.port = test_sys.ruby._cpu_ports[i].slave
|
cpu.dtb.walker.port = test_sys.ruby._cpu_ports[i].slave
|
||||||
|
|
||||||
cpu.interrupts.pio = test_sys.ruby._cpu_ports[i].master
|
cpu.interrupts[0].pio = test_sys.ruby._cpu_ports[i].master
|
||||||
cpu.interrupts.int_master = test_sys.ruby._cpu_ports[i].slave
|
cpu.interrupts[0].int_master = test_sys.ruby._cpu_ports[i].slave
|
||||||
cpu.interrupts.int_slave = test_sys.ruby._cpu_ports[i].master
|
cpu.interrupts[0].int_slave = test_sys.ruby._cpu_ports[i].master
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if options.caches or options.l2cache:
|
if options.caches or options.l2cache:
|
||||||
|
|
|
@ -265,9 +265,9 @@ if options.ruby:
|
||||||
system.cpu[i].icache_port = ruby_port.slave
|
system.cpu[i].icache_port = ruby_port.slave
|
||||||
system.cpu[i].dcache_port = ruby_port.slave
|
system.cpu[i].dcache_port = ruby_port.slave
|
||||||
if buildEnv['TARGET_ISA'] == 'x86':
|
if buildEnv['TARGET_ISA'] == 'x86':
|
||||||
system.cpu[i].interrupts.pio = ruby_port.master
|
system.cpu[i].interrupts[0].pio = ruby_port.master
|
||||||
system.cpu[i].interrupts.int_master = ruby_port.slave
|
system.cpu[i].interrupts[0].int_master = ruby_port.slave
|
||||||
system.cpu[i].interrupts.int_slave = ruby_port.master
|
system.cpu[i].interrupts[0].int_slave = ruby_port.master
|
||||||
system.cpu[i].itb.walker.port = ruby_port.slave
|
system.cpu[i].itb.walker.port = ruby_port.slave
|
||||||
system.cpu[i].dtb.walker.port = ruby_port.slave
|
system.cpu[i].dtb.walker.port = ruby_port.slave
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -943,7 +943,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
0x01: quiesce({{
|
0x01: quiesce({{
|
||||||
// Don't sleep if (unmasked) interrupts are pending
|
// Don't sleep if (unmasked) interrupts are pending
|
||||||
Interrupts* interrupts =
|
Interrupts* interrupts =
|
||||||
xc->tcBase()->getCpuPtr()->getInterruptController();
|
xc->tcBase()->getCpuPtr()->getInterruptController(0);
|
||||||
if (interrupts->checkInterrupts(xc->tcBase())) {
|
if (interrupts->checkInterrupts(xc->tcBase())) {
|
||||||
PseudoInst::quiesceSkip(xc->tcBase());
|
PseudoInst::quiesceSkip(xc->tcBase());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -681,7 +681,7 @@ void
|
||||||
Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
||||||
{
|
{
|
||||||
if (FullSystem) {
|
if (FullSystem) {
|
||||||
tc->getCpuPtr()->clearInterrupts();
|
tc->getCpuPtr()->clearInterrupts(tc->threadId());
|
||||||
tc->clearArchRegs();
|
tc->clearArchRegs();
|
||||||
}
|
}
|
||||||
if (!ArmSystem::highestELIs64(tc)) {
|
if (!ArmSystem::highestELIs64(tc)) {
|
||||||
|
@ -938,7 +938,7 @@ AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source == ArmFault::AsynchronousExternalAbort) {
|
if (source == ArmFault::AsynchronousExternalAbort) {
|
||||||
tc->getCpuPtr()->clearInterrupt(INT_ABT, 0);
|
tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
|
||||||
}
|
}
|
||||||
// Get effective fault source encoding
|
// Get effective fault source encoding
|
||||||
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
||||||
|
@ -1353,7 +1353,7 @@ SystemError::SystemError()
|
||||||
void
|
void
|
||||||
SystemError::invoke(ThreadContext *tc, const 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);
|
ArmFault::invoke(tc, inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1404,7 +1404,7 @@ ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
|
||||||
// SEV execution and let pipeline continue as pcState is still
|
// SEV execution and let pipeline continue as pcState is still
|
||||||
// valid.
|
// valid.
|
||||||
tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
|
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
|
// Instantiate all the templates to make the linker happy
|
||||||
|
|
|
@ -668,12 +668,12 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
|
||||||
case MISCREG_DBGDSCRint:
|
case MISCREG_DBGDSCRint:
|
||||||
return 0;
|
return 0;
|
||||||
case MISCREG_ISR:
|
case MISCREG_ISR:
|
||||||
return tc->getCpuPtr()->getInterruptController()->getISR(
|
return tc->getCpuPtr()->getInterruptController(tc->threadId())->getISR(
|
||||||
readMiscRegNoEffect(MISCREG_HCR),
|
readMiscRegNoEffect(MISCREG_HCR),
|
||||||
readMiscRegNoEffect(MISCREG_CPSR),
|
readMiscRegNoEffect(MISCREG_CPSR),
|
||||||
readMiscRegNoEffect(MISCREG_SCR));
|
readMiscRegNoEffect(MISCREG_SCR));
|
||||||
case MISCREG_ISR_EL1:
|
case MISCREG_ISR_EL1:
|
||||||
return tc->getCpuPtr()->getInterruptController()->getISR(
|
return tc->getCpuPtr()->getInterruptController(tc->threadId())->getISR(
|
||||||
readMiscRegNoEffect(MISCREG_HCR_EL2),
|
readMiscRegNoEffect(MISCREG_HCR_EL2),
|
||||||
readMiscRegNoEffect(MISCREG_CPSR),
|
readMiscRegNoEffect(MISCREG_CPSR),
|
||||||
readMiscRegNoEffect(MISCREG_SCR_EL3));
|
readMiscRegNoEffect(MISCREG_SCR_EL3));
|
||||||
|
@ -1929,7 +1929,7 @@ ISA::getGenericTimer(ThreadContext *tc)
|
||||||
"been configured to use a generic timer.\n");
|
"been configured to use a generic timer.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.reset(new GenericTimerISA(*generic_timer, tc->cpuId()));
|
timer.reset(new GenericTimerISA(*generic_timer, tc->contextId()));
|
||||||
return *timer.get();
|
return *timer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -649,7 +649,8 @@ let {{
|
||||||
if (SevMailbox == 1) {
|
if (SevMailbox == 1) {
|
||||||
SevMailbox = 0;
|
SevMailbox = 0;
|
||||||
PseudoInst::quiesceSkip(tc);
|
PseudoInst::quiesceSkip(tc);
|
||||||
} else if (tc->getCpuPtr()->getInterruptController()->checkInterrupts(tc)) {
|
} else if (tc->getCpuPtr()->getInterruptController(
|
||||||
|
tc->threadId())->checkInterrupts(tc)) {
|
||||||
PseudoInst::quiesceSkip(tc);
|
PseudoInst::quiesceSkip(tc);
|
||||||
} else if (cpsr.el == EL0 && !sctlr.ntwe) {
|
} else if (cpsr.el == EL0 && !sctlr.ntwe) {
|
||||||
PseudoInst::quiesceSkip(tc);
|
PseudoInst::quiesceSkip(tc);
|
||||||
|
@ -692,8 +693,8 @@ let {{
|
||||||
|
|
||||||
// WFI doesn't sleep if interrupts are pending (masked or not)
|
// WFI doesn't sleep if interrupts are pending (masked or not)
|
||||||
ThreadContext *tc = xc->tcBase();
|
ThreadContext *tc = xc->tcBase();
|
||||||
if (tc->getCpuPtr()->getInterruptController()->checkWfiWake(hcr, cpsr,
|
if (tc->getCpuPtr()->getInterruptController(
|
||||||
scr)) {
|
tc->threadId())->checkWfiWake(hcr, cpsr, scr)) {
|
||||||
PseudoInst::quiesceSkip(tc);
|
PseudoInst::quiesceSkip(tc);
|
||||||
} else if (cpsr.el == EL0 && !sctlr.ntwi) {
|
} else if (cpsr.el == EL0 && !sctlr.ntwi) {
|
||||||
PseudoInst::quiesceSkip(tc);
|
PseudoInst::quiesceSkip(tc);
|
||||||
|
@ -711,7 +712,7 @@ let {{
|
||||||
} else {
|
} else {
|
||||||
PseudoInst::quiesce(tc);
|
PseudoInst::quiesce(tc);
|
||||||
}
|
}
|
||||||
tc->getCpuPtr()->clearInterrupt(INT_ABT, 0);
|
tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
|
||||||
'''
|
'''
|
||||||
wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
|
wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
|
||||||
{ "code" : wfiCode, "predicate_test" : predicateTest },
|
{ "code" : wfiCode, "predicate_test" : predicateTest },
|
||||||
|
@ -731,7 +732,7 @@ let {{
|
||||||
// Wake CPU with interrupt if they were sleeping
|
// Wake CPU with interrupt if they were sleeping
|
||||||
if (oc->readMiscReg(MISCREG_SEV_MAILBOX) == 0) {
|
if (oc->readMiscReg(MISCREG_SEV_MAILBOX) == 0) {
|
||||||
// Post Interrupt and wake cpu if needed
|
// Post Interrupt and wake cpu if needed
|
||||||
oc->getCpuPtr()->postInterrupt(INT_SEV, 0);
|
oc->getCpuPtr()->postInterrupt(oc->threadId(), INT_SEV, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -591,9 +591,9 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
|
||||||
{
|
{
|
||||||
tl = val;
|
tl = val;
|
||||||
if (hpstate.tlz && tl == 0 && !hpstate.hpriv)
|
if (hpstate.tlz && tl == 0 && !hpstate.hpriv)
|
||||||
tc->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
tc->getCpuPtr()->postInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
|
||||||
else
|
else
|
||||||
tc->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
tc->getCpuPtr()->clearInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case MISCREG_CWP:
|
case MISCREG_CWP:
|
||||||
|
|
|
@ -1022,7 +1022,7 @@ TLB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
|
||||||
{
|
{
|
||||||
SparcISA::Interrupts * interrupts =
|
SparcISA::Interrupts * interrupts =
|
||||||
dynamic_cast<SparcISA::Interrupts *>(
|
dynamic_cast<SparcISA::Interrupts *>(
|
||||||
tc->getCpuPtr()->getInterruptController());
|
tc->getCpuPtr()->getInterruptController(0));
|
||||||
pkt->set(interrupts->get_vec(IT_INT_VEC));
|
pkt->set(interrupts->get_vec(IT_INT_VEC));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1030,9 +1030,9 @@ TLB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
|
||||||
{
|
{
|
||||||
SparcISA::Interrupts * interrupts =
|
SparcISA::Interrupts * interrupts =
|
||||||
dynamic_cast<SparcISA::Interrupts *>(
|
dynamic_cast<SparcISA::Interrupts *>(
|
||||||
tc->getCpuPtr()->getInterruptController());
|
tc->getCpuPtr()->getInterruptController(0));
|
||||||
temp = findMsbSet(interrupts->get_vec(IT_INT_VEC));
|
temp = findMsbSet(interrupts->get_vec(IT_INT_VEC));
|
||||||
tc->getCpuPtr()->clearInterrupt(IT_INT_VEC, temp);
|
tc->getCpuPtr()->clearInterrupt(0, IT_INT_VEC, temp);
|
||||||
pkt->set(temp);
|
pkt->set(temp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1278,16 +1278,16 @@ TLB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
|
||||||
// clear all the interrupts that aren't set in the write
|
// clear all the interrupts that aren't set in the write
|
||||||
SparcISA::Interrupts * interrupts =
|
SparcISA::Interrupts * interrupts =
|
||||||
dynamic_cast<SparcISA::Interrupts *>(
|
dynamic_cast<SparcISA::Interrupts *>(
|
||||||
tc->getCpuPtr()->getInterruptController());
|
tc->getCpuPtr()->getInterruptController(0));
|
||||||
while (interrupts->get_vec(IT_INT_VEC) & data) {
|
while (interrupts->get_vec(IT_INT_VEC) & data) {
|
||||||
msb = findMsbSet(interrupts->get_vec(IT_INT_VEC) & data);
|
msb = findMsbSet(interrupts->get_vec(IT_INT_VEC) & data);
|
||||||
tc->getCpuPtr()->clearInterrupt(IT_INT_VEC, msb);
|
tc->getCpuPtr()->clearInterrupt(0, IT_INT_VEC, msb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASI_SWVR_UDB_INTR_W:
|
case ASI_SWVR_UDB_INTR_W:
|
||||||
tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()->
|
tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()->
|
||||||
postInterrupt(bits(data, 5, 0), 0);
|
postInterrupt(0, bits(data, 5, 0), 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
doMmuWriteError:
|
doMmuWriteError:
|
||||||
|
|
|
@ -49,20 +49,20 @@ ISA::checkSoftInt(ThreadContext *tc)
|
||||||
|
|
||||||
// If PIL < 14, copy over the tm and sm bits
|
// If PIL < 14, copy over the tm and sm bits
|
||||||
if (pil < 14 && softint & 0x10000)
|
if (pil < 14 && softint & 0x10000)
|
||||||
cpu->postInterrupt(IT_SOFT_INT, 16);
|
cpu->postInterrupt(0, IT_SOFT_INT, 16);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_SOFT_INT, 16);
|
cpu->clearInterrupt(0, IT_SOFT_INT, 16);
|
||||||
if (pil < 14 && softint & 0x1)
|
if (pil < 14 && softint & 0x1)
|
||||||
cpu->postInterrupt(IT_SOFT_INT, 0);
|
cpu->postInterrupt(0, IT_SOFT_INT, 0);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_SOFT_INT, 0);
|
cpu->clearInterrupt(0, IT_SOFT_INT, 0);
|
||||||
|
|
||||||
// Copy over any of the other bits that are set
|
// Copy over any of the other bits that are set
|
||||||
for (int bit = 15; bit > 0; --bit) {
|
for (int bit = 15; bit > 0; --bit) {
|
||||||
if (1 << bit & softint && bit > pil)
|
if (1 << bit & softint && bit > pil)
|
||||||
cpu->postInterrupt(IT_SOFT_INT, bit);
|
cpu->postInterrupt(0, IT_SOFT_INT, bit);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_SOFT_INT, bit);
|
cpu->clearInterrupt(0, IT_SOFT_INT, bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,9 +149,9 @@ ISA::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
||||||
case MISCREG_HINTP:
|
case MISCREG_HINTP:
|
||||||
setMiscRegNoEffect(miscReg, val);
|
setMiscRegNoEffect(miscReg, val);
|
||||||
if (hintp)
|
if (hintp)
|
||||||
cpu->postInterrupt(IT_HINTP, 0);
|
cpu->postInterrupt(0, IT_HINTP, 0);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_HINTP, 0);
|
cpu->clearInterrupt(0, IT_HINTP, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MISCREG_HTBA:
|
case MISCREG_HTBA:
|
||||||
|
@ -163,25 +163,25 @@ ISA::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
||||||
case MISCREG_QUEUE_CPU_MONDO_TAIL:
|
case MISCREG_QUEUE_CPU_MONDO_TAIL:
|
||||||
setMiscRegNoEffect(miscReg, val);
|
setMiscRegNoEffect(miscReg, val);
|
||||||
if (cpu_mondo_head != cpu_mondo_tail)
|
if (cpu_mondo_head != cpu_mondo_tail)
|
||||||
cpu->postInterrupt(IT_CPU_MONDO, 0);
|
cpu->postInterrupt(0, IT_CPU_MONDO, 0);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_CPU_MONDO, 0);
|
cpu->clearInterrupt(0, IT_CPU_MONDO, 0);
|
||||||
break;
|
break;
|
||||||
case MISCREG_QUEUE_DEV_MONDO_HEAD:
|
case MISCREG_QUEUE_DEV_MONDO_HEAD:
|
||||||
case MISCREG_QUEUE_DEV_MONDO_TAIL:
|
case MISCREG_QUEUE_DEV_MONDO_TAIL:
|
||||||
setMiscRegNoEffect(miscReg, val);
|
setMiscRegNoEffect(miscReg, val);
|
||||||
if (dev_mondo_head != dev_mondo_tail)
|
if (dev_mondo_head != dev_mondo_tail)
|
||||||
cpu->postInterrupt(IT_DEV_MONDO, 0);
|
cpu->postInterrupt(0, IT_DEV_MONDO, 0);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_DEV_MONDO, 0);
|
cpu->clearInterrupt(0, IT_DEV_MONDO, 0);
|
||||||
break;
|
break;
|
||||||
case MISCREG_QUEUE_RES_ERROR_HEAD:
|
case MISCREG_QUEUE_RES_ERROR_HEAD:
|
||||||
case MISCREG_QUEUE_RES_ERROR_TAIL:
|
case MISCREG_QUEUE_RES_ERROR_TAIL:
|
||||||
setMiscRegNoEffect(miscReg, val);
|
setMiscRegNoEffect(miscReg, val);
|
||||||
if (res_error_head != res_error_tail)
|
if (res_error_head != res_error_tail)
|
||||||
cpu->postInterrupt(IT_RES_ERROR, 0);
|
cpu->postInterrupt(0, IT_RES_ERROR, 0);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_RES_ERROR, 0);
|
cpu->clearInterrupt(0, IT_RES_ERROR, 0);
|
||||||
break;
|
break;
|
||||||
case MISCREG_QUEUE_NRES_ERROR_HEAD:
|
case MISCREG_QUEUE_NRES_ERROR_HEAD:
|
||||||
case MISCREG_QUEUE_NRES_ERROR_TAIL:
|
case MISCREG_QUEUE_NRES_ERROR_TAIL:
|
||||||
|
@ -213,9 +213,9 @@ ISA::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
||||||
setMiscRegNoEffect(miscReg, newVal);
|
setMiscRegNoEffect(miscReg, newVal);
|
||||||
newVal = hpstate;
|
newVal = hpstate;
|
||||||
if (newVal.tlz && tl == 0 && !newVal.hpriv)
|
if (newVal.tlz && tl == 0 && !newVal.hpriv)
|
||||||
cpu->postInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
cpu->postInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
|
||||||
else
|
else
|
||||||
cpu->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
cpu->clearInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MISCREG_HTSTATE:
|
case MISCREG_HTSTATE:
|
||||||
|
|
|
@ -183,7 +183,7 @@ void initCPU(ThreadContext *tc, int cpuId)
|
||||||
tc->setMiscReg(MISCREG_APIC_BASE, lApicBase);
|
tc->setMiscReg(MISCREG_APIC_BASE, lApicBase);
|
||||||
|
|
||||||
Interrupts * interrupts = dynamic_cast<Interrupts *>(
|
Interrupts * interrupts = dynamic_cast<Interrupts *>(
|
||||||
tc->getCpuPtr()->getInterruptController());
|
tc->getCpuPtr()->getInterruptController(0));
|
||||||
assert(interrupts);
|
assert(interrupts);
|
||||||
|
|
||||||
interrupts->setRegNoEffect(APIC_ID, cpuId << 24);
|
interrupts->setRegNoEffect(APIC_ID, cpuId << 24);
|
||||||
|
|
|
@ -149,40 +149,40 @@ class BaseCPU(MemObject):
|
||||||
if buildEnv['TARGET_ISA'] == 'sparc':
|
if buildEnv['TARGET_ISA'] == 'sparc':
|
||||||
dtb = Param.SparcTLB(SparcTLB(), "Data TLB")
|
dtb = Param.SparcTLB(SparcTLB(), "Data TLB")
|
||||||
itb = Param.SparcTLB(SparcTLB(), "Instruction TLB")
|
itb = Param.SparcTLB(SparcTLB(), "Instruction TLB")
|
||||||
interrupts = Param.SparcInterrupts(
|
interrupts = VectorParam.SparcInterrupts(
|
||||||
NULL, "Interrupt Controller")
|
[], "Interrupt Controller")
|
||||||
isa = VectorParam.SparcISA([ isa_class() ], "ISA instance")
|
isa = VectorParam.SparcISA([ isa_class() ], "ISA instance")
|
||||||
elif buildEnv['TARGET_ISA'] == 'alpha':
|
elif buildEnv['TARGET_ISA'] == 'alpha':
|
||||||
dtb = Param.AlphaTLB(AlphaDTB(), "Data TLB")
|
dtb = Param.AlphaTLB(AlphaDTB(), "Data TLB")
|
||||||
itb = Param.AlphaTLB(AlphaITB(), "Instruction TLB")
|
itb = Param.AlphaTLB(AlphaITB(), "Instruction TLB")
|
||||||
interrupts = Param.AlphaInterrupts(
|
interrupts = VectorParam.AlphaInterrupts(
|
||||||
NULL, "Interrupt Controller")
|
[], "Interrupt Controller")
|
||||||
isa = VectorParam.AlphaISA([ isa_class() ], "ISA instance")
|
isa = VectorParam.AlphaISA([ isa_class() ], "ISA instance")
|
||||||
elif buildEnv['TARGET_ISA'] == 'x86':
|
elif buildEnv['TARGET_ISA'] == 'x86':
|
||||||
dtb = Param.X86TLB(X86TLB(), "Data TLB")
|
dtb = Param.X86TLB(X86TLB(), "Data TLB")
|
||||||
itb = Param.X86TLB(X86TLB(), "Instruction 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")
|
isa = VectorParam.X86ISA([ isa_class() ], "ISA instance")
|
||||||
elif buildEnv['TARGET_ISA'] == 'mips':
|
elif buildEnv['TARGET_ISA'] == 'mips':
|
||||||
dtb = Param.MipsTLB(MipsTLB(), "Data TLB")
|
dtb = Param.MipsTLB(MipsTLB(), "Data TLB")
|
||||||
itb = Param.MipsTLB(MipsTLB(), "Instruction TLB")
|
itb = Param.MipsTLB(MipsTLB(), "Instruction TLB")
|
||||||
interrupts = Param.MipsInterrupts(
|
interrupts = VectorParam.MipsInterrupts(
|
||||||
NULL, "Interrupt Controller")
|
[], "Interrupt Controller")
|
||||||
isa = VectorParam.MipsISA([ isa_class() ], "ISA instance")
|
isa = VectorParam.MipsISA([ isa_class() ], "ISA instance")
|
||||||
elif buildEnv['TARGET_ISA'] == 'arm':
|
elif buildEnv['TARGET_ISA'] == 'arm':
|
||||||
dtb = Param.ArmTLB(ArmTLB(), "Data TLB")
|
dtb = Param.ArmTLB(ArmTLB(), "Data TLB")
|
||||||
itb = Param.ArmTLB(ArmTLB(), "Instruction TLB")
|
itb = Param.ArmTLB(ArmTLB(), "Instruction TLB")
|
||||||
istage2_mmu = Param.ArmStage2MMU(ArmStage2IMMU(), "Stage 2 trans")
|
istage2_mmu = Param.ArmStage2MMU(ArmStage2IMMU(), "Stage 2 trans")
|
||||||
dstage2_mmu = Param.ArmStage2MMU(ArmStage2DMMU(), "Stage 2 trans")
|
dstage2_mmu = Param.ArmStage2MMU(ArmStage2DMMU(), "Stage 2 trans")
|
||||||
interrupts = Param.ArmInterrupts(
|
interrupts = VectorParam.ArmInterrupts(
|
||||||
NULL, "Interrupt Controller")
|
[], "Interrupt Controller")
|
||||||
isa = VectorParam.ArmISA([ isa_class() ], "ISA instance")
|
isa = VectorParam.ArmISA([ isa_class() ], "ISA instance")
|
||||||
elif buildEnv['TARGET_ISA'] == 'power':
|
elif buildEnv['TARGET_ISA'] == 'power':
|
||||||
UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
|
UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
|
||||||
dtb = Param.PowerTLB(PowerTLB(), "Data TLB")
|
dtb = Param.PowerTLB(PowerTLB(), "Data TLB")
|
||||||
itb = Param.PowerTLB(PowerTLB(), "Instruction TLB")
|
itb = Param.PowerTLB(PowerTLB(), "Instruction TLB")
|
||||||
interrupts = Param.PowerInterrupts(
|
interrupts = VectorParam.PowerInterrupts(
|
||||||
NULL, "Interrupt Controller")
|
[], "Interrupt Controller")
|
||||||
isa = VectorParam.PowerISA([ isa_class() ], "ISA instance")
|
isa = VectorParam.PowerISA([ isa_class() ], "ISA instance")
|
||||||
else:
|
else:
|
||||||
print "Don't know what TLB to use for ISA %s" % \
|
print "Don't know what TLB to use for ISA %s" % \
|
||||||
|
@ -218,27 +218,29 @@ class BaseCPU(MemObject):
|
||||||
_uncached_slave_ports = []
|
_uncached_slave_ports = []
|
||||||
_uncached_master_ports = []
|
_uncached_master_ports = []
|
||||||
if buildEnv['TARGET_ISA'] == 'x86':
|
if buildEnv['TARGET_ISA'] == 'x86':
|
||||||
_uncached_slave_ports += ["interrupts.pio", "interrupts.int_slave"]
|
_uncached_slave_ports += ["interrupts[0].pio",
|
||||||
_uncached_master_ports += ["interrupts.int_master"]
|
"interrupts[0].int_slave"]
|
||||||
|
_uncached_master_ports += ["interrupts[0].int_master"]
|
||||||
|
|
||||||
def createInterruptController(self):
|
def createInterruptController(self):
|
||||||
if buildEnv['TARGET_ISA'] == 'sparc':
|
if buildEnv['TARGET_ISA'] == 'sparc':
|
||||||
self.interrupts = SparcInterrupts()
|
self.interrupts = [SparcInterrupts() for i in xrange(self.numThreads)]
|
||||||
elif buildEnv['TARGET_ISA'] == 'alpha':
|
elif buildEnv['TARGET_ISA'] == 'alpha':
|
||||||
self.interrupts = AlphaInterrupts()
|
self.interrupts = [AlphaInterrupts() for i in xrange(self.numThreads)]
|
||||||
elif buildEnv['TARGET_ISA'] == 'x86':
|
elif buildEnv['TARGET_ISA'] == 'x86':
|
||||||
self.apic_clk_domain = DerivedClockDomain(clk_domain =
|
self.apic_clk_domain = DerivedClockDomain(clk_domain =
|
||||||
Parent.clk_domain,
|
Parent.clk_domain,
|
||||||
clk_divider = 16)
|
clk_divider = 16)
|
||||||
self.interrupts = X86LocalApic(clk_domain = self.apic_clk_domain,
|
self.interrupts = [X86LocalApic(clk_domain = self.apic_clk_domain,
|
||||||
pio_addr=0x2000000000000000)
|
pio_addr=0x2000000000000000)
|
||||||
|
for i in xrange(self.numThreads)]
|
||||||
_localApic = self.interrupts
|
_localApic = self.interrupts
|
||||||
elif buildEnv['TARGET_ISA'] == 'mips':
|
elif buildEnv['TARGET_ISA'] == 'mips':
|
||||||
self.interrupts = MipsInterrupts()
|
self.interrupts = [MipsInterrupts() for i in xrange(self.numThreads)]
|
||||||
elif buildEnv['TARGET_ISA'] == 'arm':
|
elif buildEnv['TARGET_ISA'] == 'arm':
|
||||||
self.interrupts = ArmInterrupts()
|
self.interrupts = [ArmInterrupts() for i in xrange(self.numThreads)]
|
||||||
elif buildEnv['TARGET_ISA'] == 'power':
|
elif buildEnv['TARGET_ISA'] == 'power':
|
||||||
self.interrupts = PowerInterrupts()
|
self.interrupts = [PowerInterrupts() for i in xrange(self.numThreads)]
|
||||||
else:
|
else:
|
||||||
print "Don't know what Interrupt Controller to use for ISA %s" % \
|
print "Don't know what Interrupt Controller to use for ISA %s" % \
|
||||||
buildEnv['TARGET_ISA']
|
buildEnv['TARGET_ISA']
|
||||||
|
|
|
@ -237,8 +237,10 @@ BaseCPU::BaseCPU(Params *p, bool is_checker)
|
||||||
// The interrupts should always be present unless this CPU is
|
// The interrupts should always be present unless this CPU is
|
||||||
// switched in later or in case it is a checker CPU
|
// switched in later or in case it is a checker CPU
|
||||||
if (!params()->switched_out && !is_checker) {
|
if (!params()->switched_out && !is_checker) {
|
||||||
if (interrupts) {
|
if (!interrupts.empty()) {
|
||||||
interrupts->setCPU(this);
|
for (ThreadID tid = 0; tid < numThreads; tid++) {
|
||||||
|
interrupts[tid]->setCPU(this);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fatal("CPU %s has no interrupt controller.\n"
|
fatal("CPU %s has no interrupt controller.\n"
|
||||||
"Ensure createInterruptController() is called.\n", name());
|
"Ensure createInterruptController() is called.\n", name());
|
||||||
|
@ -583,8 +585,10 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupts = oldCPU->interrupts;
|
interrupts = oldCPU->interrupts;
|
||||||
interrupts->setCPU(this);
|
for (ThreadID tid = 0; tid < numThreads; tid++) {
|
||||||
oldCPU->interrupts = NULL;
|
interrupts[tid]->setCPU(this);
|
||||||
|
}
|
||||||
|
oldCPU->interrupts.clear();
|
||||||
|
|
||||||
if (FullSystem) {
|
if (FullSystem) {
|
||||||
for (ThreadID i = 0; i < size; ++i)
|
for (ThreadID i = 0; i < size; ++i)
|
||||||
|
@ -656,11 +660,10 @@ BaseCPU::serialize(CheckpointOut &cp) const
|
||||||
* system. */
|
* system. */
|
||||||
SERIALIZE_SCALAR(_pid);
|
SERIALIZE_SCALAR(_pid);
|
||||||
|
|
||||||
interrupts->serialize(cp);
|
|
||||||
|
|
||||||
// Serialize the threads, this is done by the CPU implementation.
|
// Serialize the threads, this is done by the CPU implementation.
|
||||||
for (ThreadID i = 0; i < numThreads; ++i) {
|
for (ThreadID i = 0; i < numThreads; ++i) {
|
||||||
ScopedCheckpointSection sec(cp, csprintf("xc.%i", i));
|
ScopedCheckpointSection sec(cp, csprintf("xc.%i", i));
|
||||||
|
interrupts[i]->serialize(cp);
|
||||||
serializeThread(cp, i);
|
serializeThread(cp, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,11 +676,11 @@ BaseCPU::unserialize(CheckpointIn &cp)
|
||||||
|
|
||||||
if (!_switchedOut) {
|
if (!_switchedOut) {
|
||||||
UNSERIALIZE_SCALAR(_pid);
|
UNSERIALIZE_SCALAR(_pid);
|
||||||
interrupts->unserialize(cp);
|
|
||||||
|
|
||||||
// Unserialize the threads, this is done by the CPU implementation.
|
// Unserialize the threads, this is done by the CPU implementation.
|
||||||
for (ThreadID i = 0; i < numThreads; ++i) {
|
for (ThreadID i = 0; i < numThreads; ++i) {
|
||||||
ScopedCheckpointSection sec(cp, csprintf("xc.%i", i));
|
ScopedCheckpointSection sec(cp, csprintf("xc.%i", i));
|
||||||
|
interrupts[i]->unserialize(cp);
|
||||||
unserializeThread(cp, i);
|
unserializeThread(cp, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,41 +207,45 @@ class BaseCPU : public MemObject
|
||||||
TheISA::MicrocodeRom microcodeRom;
|
TheISA::MicrocodeRom microcodeRom;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TheISA::Interrupts *interrupts;
|
std::vector<TheISA::Interrupts*> interrupts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TheISA::Interrupts *
|
TheISA::Interrupts *
|
||||||
getInterruptController()
|
getInterruptController(ThreadID tid)
|
||||||
{
|
{
|
||||||
return interrupts;
|
if (interrupts.empty())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
assert(interrupts.size() > tid);
|
||||||
|
return interrupts[tid];
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void wakeup() = 0;
|
virtual void wakeup() = 0;
|
||||||
|
|
||||||
void
|
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)
|
if (FullSystem)
|
||||||
wakeup();
|
wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
clearInterrupts()
|
clearInterrupts(ThreadID tid)
|
||||||
{
|
{
|
||||||
interrupts->clearAll();
|
interrupts[tid]->clearAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
checkInterrupts(ThreadContext *tc) const
|
checkInterrupts(ThreadContext *tc) const
|
||||||
{
|
{
|
||||||
return FullSystem && interrupts->checkInterrupts(tc);
|
return FullSystem && interrupts[tc->threadId()]->checkInterrupts(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProfileEvent : public Event
|
class ProfileEvent : public Event
|
||||||
|
|
|
@ -73,7 +73,6 @@ DummyCheckerParams::create()
|
||||||
params->system = system;
|
params->system = system;
|
||||||
params->cpu_id = cpu_id;
|
params->cpu_id = cpu_id;
|
||||||
params->profile = profile;
|
params->profile = profile;
|
||||||
params->interrupts = NULL;
|
|
||||||
params->workload = workload;
|
params->workload = workload;
|
||||||
|
|
||||||
DummyChecker *cpu = new DummyChecker(params);
|
DummyChecker *cpu = new DummyChecker(params);
|
||||||
|
|
|
@ -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);
|
DPRINTF(IntrControl, "post %d:%d (cpu %d)\n", int_num, index, cpu_id);
|
||||||
std::vector<ThreadContext *> &tcvec = sys->threadContexts;
|
std::vector<ThreadContext *> &tcvec = sys->threadContexts;
|
||||||
BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr();
|
BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr();
|
||||||
cpu->postInterrupt(int_num, index);
|
cpu->postInterrupt(tcvec[cpu_id]->threadId(), int_num, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
DPRINTF(IntrControl, "clear %d:%d (cpu %d)\n", int_num, index, cpu_id);
|
||||||
std::vector<ThreadContext *> &tcvec = sys->threadContexts;
|
std::vector<ThreadContext *> &tcvec = sys->threadContexts;
|
||||||
BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr();
|
BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr();
|
||||||
cpu->clearInterrupt(int_num, index);
|
cpu->clearInterrupt(tcvec[cpu_id]->threadId(), int_num, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrControl *
|
IntrControl *
|
||||||
|
|
|
@ -1142,9 +1142,9 @@ X86KvmCPU::deliverInterrupts()
|
||||||
// call across threads, we might still lose interrupts unless
|
// call across threads, we might still lose interrupts unless
|
||||||
// they are getInterrupt() and updateIntrInfo() are called
|
// they are getInterrupt() and updateIntrInfo() are called
|
||||||
// atomically.
|
// atomically.
|
||||||
EventQueue::ScopedMigration migrate(interrupts->eventQueue());
|
EventQueue::ScopedMigration migrate(interrupts[0]->eventQueue());
|
||||||
fault = interrupts->getInterrupt(tc);
|
fault = interrupts[0]->getInterrupt(tc);
|
||||||
interrupts->updateIntrInfo(tc);
|
interrupts[0]->updateIntrInfo(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
X86Interrupt *x86int(dynamic_cast<X86Interrupt *>(fault.get()));
|
X86Interrupt *x86int(dynamic_cast<X86Interrupt *>(fault.get()));
|
||||||
|
@ -1187,8 +1187,8 @@ X86KvmCPU::kvmRun(Tick ticks)
|
||||||
{
|
{
|
||||||
struct kvm_run &kvm_run(*getKvmRunState());
|
struct kvm_run &kvm_run(*getKvmRunState());
|
||||||
|
|
||||||
if (interrupts->checkInterruptsRaw()) {
|
if (interrupts[0]->checkInterruptsRaw()) {
|
||||||
if (interrupts->hasPendingUnmaskable()) {
|
if (interrupts[0]->hasPendingUnmaskable()) {
|
||||||
DPRINTF(KvmInt,
|
DPRINTF(KvmInt,
|
||||||
"Delivering unmaskable interrupt.\n");
|
"Delivering unmaskable interrupt.\n");
|
||||||
syncThreadContext();
|
syncThreadContext();
|
||||||
|
@ -1200,7 +1200,7 @@ X86KvmCPU::kvmRun(Tick ticks)
|
||||||
// the thread context and check if there are /really/
|
// the thread context and check if there are /really/
|
||||||
// interrupts that should be delivered now.
|
// interrupts that should be delivered now.
|
||||||
syncThreadContext();
|
syncThreadContext();
|
||||||
if (interrupts->checkInterrupts(tc)) {
|
if (interrupts[0]->checkInterrupts(tc)) {
|
||||||
DPRINTF(KvmInt,
|
DPRINTF(KvmInt,
|
||||||
"M5 has pending interrupts, delivering interrupt.\n");
|
"M5 has pending interrupts, delivering interrupt.\n");
|
||||||
|
|
||||||
|
|
|
@ -403,12 +403,12 @@ Execute::takeInterrupt(ThreadID thread_id, BranchData &branch)
|
||||||
DPRINTF(MinorInterrupt, "Considering interrupt status from PC: %s\n",
|
DPRINTF(MinorInterrupt, "Considering interrupt status from PC: %s\n",
|
||||||
cpu.getContext(thread_id)->pcState());
|
cpu.getContext(thread_id)->pcState());
|
||||||
|
|
||||||
Fault interrupt = cpu.getInterruptController()->getInterrupt
|
Fault interrupt = cpu.getInterruptController(thread_id)->getInterrupt
|
||||||
(cpu.getContext(thread_id));
|
(cpu.getContext(thread_id));
|
||||||
|
|
||||||
if (interrupt != NoFault) {
|
if (interrupt != NoFault) {
|
||||||
/* The interrupt *must* set pcState */
|
/* The interrupt *must* set pcState */
|
||||||
cpu.getInterruptController()->updateIntrInfo
|
cpu.getInterruptController(thread_id)->updateIntrInfo
|
||||||
(cpu.getContext(thread_id));
|
(cpu.getContext(thread_id));
|
||||||
interrupt->invoke(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? */
|
/* If there was an interrupt signalled, was it acted on now? */
|
||||||
bool took_interrupt = false;
|
bool took_interrupt = false;
|
||||||
|
|
||||||
if (cpu.getInterruptController()) {
|
if (cpu.getInterruptController(0)) {
|
||||||
/* This is here because it seems that after drainResume the
|
/* This is here because it seems that after drainResume the
|
||||||
* interrupt controller isn't always set */
|
* interrupt controller isn't always set */
|
||||||
interrupted = drainState == NotDraining && isInterrupted(0);
|
interrupted = drainState == NotDraining && isInterrupted(0);
|
||||||
|
|
|
@ -86,7 +86,6 @@ O3CheckerParams::create()
|
||||||
params->system = system;
|
params->system = system;
|
||||||
params->cpu_id = cpu_id;
|
params->cpu_id = cpu_id;
|
||||||
params->profile = profile;
|
params->profile = profile;
|
||||||
params->interrupts = NULL;
|
|
||||||
params->workload = workload;
|
params->workload = workload;
|
||||||
|
|
||||||
O3Checker *cpu = new O3Checker(params);
|
O3Checker *cpu = new O3Checker(params);
|
||||||
|
|
|
@ -392,7 +392,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FullO3CPU always requires an interrupt controller.
|
// 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"
|
fatal("FullO3CPU %s has no interrupt controller.\n"
|
||||||
"Ensure createInterruptController() is called.\n", name());
|
"Ensure createInterruptController() is called.\n", name());
|
||||||
}
|
}
|
||||||
|
@ -935,7 +935,7 @@ Fault
|
||||||
FullO3CPU<Impl>::getInterrupts()
|
FullO3CPU<Impl>::getInterrupts()
|
||||||
{
|
{
|
||||||
// Check if there are any outstanding interrupts
|
// 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>
|
template <class Impl>
|
||||||
|
@ -949,7 +949,7 @@ FullO3CPU<Impl>::processInterrupts(const Fault &interrupt)
|
||||||
// @todo: Allow other threads to handle interrupts.
|
// @todo: Allow other threads to handle interrupts.
|
||||||
|
|
||||||
assert(interrupt != NoFault);
|
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());
|
DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
|
||||||
this->trap(interrupt, 0, nullptr);
|
this->trap(interrupt, 0, nullptr);
|
||||||
|
|
|
@ -435,11 +435,11 @@ BaseSimpleCPU::checkForInterrupts()
|
||||||
ThreadContext* tc = thread->getTC();
|
ThreadContext* tc = thread->getTC();
|
||||||
|
|
||||||
if (checkInterrupts(tc)) {
|
if (checkInterrupts(tc)) {
|
||||||
Fault interrupt = interrupts->getInterrupt(tc);
|
Fault interrupt = interrupts[curThread]->getInterrupt(tc);
|
||||||
|
|
||||||
if (interrupt != NoFault) {
|
if (interrupt != NoFault) {
|
||||||
t_info.fetchOffset = 0;
|
t_info.fetchOffset = 0;
|
||||||
interrupts->updateIntrInfo(tc);
|
interrupts[curThread]->updateIntrInfo(tc);
|
||||||
interrupt->invoke(tc);
|
interrupt->invoke(tc);
|
||||||
thread->decoder.reset();
|
thread->decoder.reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,7 @@ X86ISA::I82094AA::signalInterrupt(int line)
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < numContexts; i++) {
|
for (int i = 0; i < numContexts; i++) {
|
||||||
Interrupts *localApic = sys->getThreadContext(i)->
|
Interrupts *localApic = sys->getThreadContext(i)->
|
||||||
getCpuPtr()->getInterruptController();
|
getCpuPtr()->getInterruptController(0);
|
||||||
if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
|
if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
|
||||||
message.destination) {
|
message.destination) {
|
||||||
apics.push_back(localApic->getInitialApicId());
|
apics.push_back(localApic->getInitialApicId());
|
||||||
|
|
|
@ -87,9 +87,9 @@ for (i, cpu) in enumerate(system.cpu):
|
||||||
cpu.itb.walker.port = system.ruby._cpu_ports[i].slave
|
cpu.itb.walker.port = system.ruby._cpu_ports[i].slave
|
||||||
cpu.dtb.walker.port = system.ruby._cpu_ports[i].slave
|
cpu.dtb.walker.port = system.ruby._cpu_ports[i].slave
|
||||||
|
|
||||||
cpu.interrupts.pio = system.ruby._cpu_ports[i].master
|
cpu.interrupts[0].pio = system.ruby._cpu_ports[i].master
|
||||||
cpu.interrupts.int_master = system.ruby._cpu_ports[i].slave
|
cpu.interrupts[0].int_master = system.ruby._cpu_ports[i].slave
|
||||||
cpu.interrupts.int_slave = system.ruby._cpu_ports[i].master
|
cpu.interrupts[0].int_slave = system.ruby._cpu_ports[i].master
|
||||||
|
|
||||||
root = Root(full_system = True, system = system)
|
root = Root(full_system = True, system = system)
|
||||||
m5.ticks.setGlobalFrequency('1THz')
|
m5.ticks.setGlobalFrequency('1THz')
|
||||||
|
|
19
util/cpt_upgraders/smt-interrupts.py
Normal file
19
util/cpt_upgraders/smt-interrupts.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Upgrade single-threaded checkpoints to be properly supported with SMT.
|
||||||
|
# SMT adds per-thread interrupts. Thus we must move the interrupt status
|
||||||
|
# from the CPU and into the execution context.
|
||||||
|
def upgrader(cpt):
|
||||||
|
for sec in cpt.sections():
|
||||||
|
import re
|
||||||
|
|
||||||
|
re_cpu_match = re.match('^(.*sys.*\.cpu[^._]*)$', sec)
|
||||||
|
if re_cpu_match != None:
|
||||||
|
interrupts = cpt.get(sec, 'interrupts')
|
||||||
|
intStatus = cpt.get(sec, 'intStatus')
|
||||||
|
|
||||||
|
cpu_name = re_cpu_match.group(1)
|
||||||
|
|
||||||
|
cpt.set(cpu_name + ".xc.0", 'interrupts', interrupts)
|
||||||
|
cpt.set(cpu_name + ".xc.0", 'intStatus', intStatus)
|
||||||
|
|
||||||
|
cpt.remove_option(sec, 'interrupts')
|
||||||
|
cpt.remove_option(sec, 'intStatus')
|
Loading…
Reference in a new issue