diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2012-03-22 11:14:00 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-03-27 15:12:30 -0500 |
commit | 64a9a50f5582133148c7960adae83021e1c23d8c (patch) | |
tree | be09d0bab769ad00c6e1aab09e40dc1fbd86c7eb /src/usr/intr | |
parent | e365e2055da924ce134e2f8263d47a6afba23e98 (diff) | |
download | talos-hostboot-64a9a50f5582133148c7960adae83021e1c23d8c.tar.gz talos-hostboot-64a9a50f5582133148c7960adae83021e1c23d8c.zip |
Support P8 interrupt presenter.
Task 35765
RTC: 35561
Change-Id: I9fd382fa1005b593d5bef5a258810a70956129d7
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/788
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/intr')
-rw-r--r-- | src/usr/intr/intrrp.C | 153 | ||||
-rw-r--r-- | src/usr/intr/intrrp.H | 83 | ||||
-rw-r--r-- | src/usr/intr/test/intrtest.H | 68 |
3 files changed, 224 insertions, 80 deletions
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C index c18a307f3..c2531a3ea 100644 --- a/src/usr/intr/intrrp.C +++ b/src/usr/intr/intrrp.C @@ -66,11 +66,16 @@ void IntrRp::init( void * i_taskArgs ) // ICPBAR = INTP.ICP_BAR[0:25] in P7 = 0x3FBFF90 + (8*node) + procPos // P7 Scom address 0x02011C09 P8 = 0x020109c9 -// BaseAddress: +// BaseAddress P7: // BA[18:43] = ICPBAR (P8 says [14:43] (30 bits)) -// BA[47:49] = COREid (0-7) +// BA[47:49] = COREid (0-7) // BA[50:51] = cpu thread (0-3) // +// BaseAddress P8: +// BA[14:43] = ICPBAR (30 bits) +// BA[45:48] = coreID (1-6,9-14) (12 cores) +// BA[49:51] = thread (0-7) +// // BA+0 = XIRR (poll - Read/Write has no side effects)) // BA+4 = XIRR (Read locks HW, Write -> EOI to HW)) // BA+12 = MFRR (1 byte) @@ -81,7 +86,7 @@ errlHndl_t IntrRp::_init() { errlHndl_t err = NULL; - // TODO Temporaritly DISABLE in VBU until P8 support is added + // TODO Temporaritly DISABLE in VBU until P8 support is confirmed if( TARGETING::is_vpo() ) { iv_isVBU = true; @@ -90,9 +95,20 @@ errlHndl_t IntrRp::_init() // get the PIR // Which ever cpu core this is running on is the MASTER cpu // Make master thread 0 - iv_masterCpu.word = task_getcpuid(); + uint32_t cpuid = task_getcpuid(); + iv_masterCpu = cpuid; + // If P7 or P7+ core -- need to tweak fields in PIR + if(cpu_core_type() < CORE_POWER8_MURANO) + { + iv_masterCpu = P7PIR_t(cpuid); + } iv_masterCpu.threadId = 0; + TRACFCOMP(g_trac_intr,"node[%d], chip[%d], core[%d], thread[%d]", + iv_masterCpu.nodeId, iv_masterCpu.chipId, iv_masterCpu.coreId, + iv_masterCpu.threadId); + + uint64_t realAddr = 0; // TODO Does the BAR scom reg need to be read here or set here?? @@ -145,25 +161,13 @@ errlHndl_t IntrRp::_init() { // Set up the interrupt provider registers - // NOTE: Simics only supports 4 threads, and two cores per proc chip. - // - // NOTE: P7 register address format only supports 4 threads per core. - // This will change for P8 - // // NOTE: It's only possible to set up the master core at this point. // // Set up link registers to forward all intrpts to master cpu. // - // There is one register set per cpu thread or 1024 register sets max. + // There is one register set per cpu thread. size_t threads = cpu_thread_count(); - if(threads > 4) //TODO remove when true P8 support is added - { - TRACFCOMP(g_trac_intr, - "I>intrrp needs to be updated to handle > 4 threads"); - threads = 4; - } - PIR_t pir = iv_masterCpu; for(size_t thread = 0; thread < threads; ++thread) { @@ -186,7 +190,7 @@ errlHndl_t IntrRp::enableInterrupts() { errlHndl_t err = NULL; - // TODO Temporarily DISABLE in VBU until P8 support is added + // TODO Temporarily DISABLE in VBU until P8 support is confirmed if(iv_isVBU) return err; // Enable the interrupt on master processor core, thread 0 @@ -207,7 +211,7 @@ errlHndl_t IntrRp::disableInterrupts() errlHndl_t err = NULL; // Disable the interrupt on master processor core, thread 0 - // TODO Temporarily DISABLE in VBU until P8 support is added + // TODO Temporarily DISABLE in VBU until P8 support is confirmed if(iv_isVBU) return err; uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(iv_masterCpu); @@ -241,10 +245,6 @@ void IntrRp::msgHandler() { case MSG_INTR_EXTERN: { - // Acknowlege msg - msg->data[1] = 0; - msg_respond(iv_msgQ, msg); - ext_intr_t type = NO_INTERRUPT; // type = XISR = XIRR[8:31] @@ -260,6 +260,10 @@ void IntrRp::msgHandler() TRACDCOMP(g_trac_intr,"External Interrupt recieved, Type=%x",type); + // Acknowlege msg + msg->data[1] = 0; + msg_respond(iv_msgQ, msg); + Registry_t::iterator r = iv_registry.find(type); if(r != iv_registry.end()) { @@ -275,6 +279,7 @@ void IntrRp::msgHandler() " handler. Ignorming it. rc = %d", (uint32_t) type, rc); } + msg_free(rmsg); } else // no queue registered for this interrupt type { @@ -294,8 +299,8 @@ void IntrRp::msgHandler() case MSG_INTR_REGISTER_MSGQ: { - msg_q_t l_msgQ= reinterpret_cast<msg_q_t>(msg->data[0]); - ext_intr_t l_t= static_cast<ext_intr_t>(msg->data[1]); + msg_q_t l_msgQ = reinterpret_cast<msg_q_t>(msg->data[0]); + ext_intr_t l_t = static_cast<ext_intr_t>(msg->data[1]); errlHndl_t err = registerInterrupt(l_msgQ,l_t); msg->data[1] = reinterpret_cast<uint64_t>(err); @@ -303,6 +308,31 @@ void IntrRp::msgHandler() } break; + case MSG_INTR_UNREGISTER_MSGQ: + { + TRACDCOMP(g_trac_intr, + "UNREG: msg type = 0x%lx", + msg->data[0]); + + msg_q_t msgQ = NULL; + ext_intr_t type = static_cast<ext_intr_t>(msg->data[0]); + Registry_t::iterator r = iv_registry.find(type); + if(r != iv_registry.end()) + { + msgQ = r->second; + iv_registry.erase(r); + } + + msg->data[1] = reinterpret_cast<uint64_t>(msgQ); + + TRACDCOMP(g_trac_intr, + "UNREG: msgQ = 0x%lx", + msg->data[1]); + + msg_respond(iv_msgQ,msg); + } + break; + case MSG_INTR_ENABLE: { errlHndl_t err = enableInterrupts(); @@ -325,6 +355,16 @@ void IntrRp::msgHandler() case MSG_INTR_ADD_CPU: { PIR_t pir = msg->data[0]; + // If P7 or P7+ core -- need to tweak fields in PIR + if(cpu_core_type() < CORE_POWER8_MURANO) + { + pir = P7PIR_t(msg->data[0]); + } + + TRACFCOMP(g_trac_intr,"Add CPU node[%d], chip[%d]," + "core[%d], thread[%d]", + pir.nodeId, pir.chipId, pir.coreId, + pir.threadId); size_t threads = cpu_thread_count(); @@ -386,15 +426,9 @@ errlHndl_t IntrRp::registerInterrupt(msg_q_t i_msgQ, ext_intr_t i_type) void IntrRp::initInterruptPresenter(const PIR_t i_pir) const { - // TODO Temporaritly DISABLE in VBU until P8 support is added + // TODO Temporaritly DISABLE in VBU until P8 support is confirmed if(iv_isVBU) return; - //@fixme - this seems redundant... - if( TARGETING::is_vpo() ) - { - return; - } - uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(i_pir); uint8_t * cppr = reinterpret_cast<uint8_t*>(baseAddr + CPPR_OFFSET); @@ -425,9 +459,10 @@ void IntrRp::initInterruptPresenter(const PIR_t i_pir) const LinkReg_t linkReg; linkReg.word = 0; linkReg.loopTrip = 1; // needed? - linkReg.pchip= (iv_masterCpu.nodeId*8)+iv_masterCpu.chipId; - linkReg.pcore= iv_masterCpu.coreId; - linkReg.tspec= iv_masterCpu.threadId; + linkReg.node = iv_masterCpu.nodeId; + linkReg.pchip= iv_masterCpu.chipId; + linkReg.pcore= iv_masterCpu.coreId; + linkReg.tspec= iv_masterCpu.threadId; *(plinkReg) = linkReg.word; *(plinkReg + 1) = linkReg.word; @@ -480,8 +515,20 @@ errlHndl_t INTR::registerMsgQ(msg_q_t i_msgQ, ext_intr_t i_type) msg->data[0] = reinterpret_cast<uint64_t>(i_msgQ); msg->data[1] = static_cast<uint64_t>(i_type); - msg_sendrecv(intr_msgQ, msg); - err = reinterpret_cast<errlHndl_t>(msg->data[1]); + int rc = msg_sendrecv(intr_msgQ, msg); + if(!rc) + { + err = reinterpret_cast<errlHndl_t>(msg->data[1]); + } + else + { + TRACFCOMP(g_trac_intr,ERR_MRK + "INTR::registerMsgQ - msg_sendrecv failed. errno = %d", + rc); + } + + msg_free(msg); + } else { @@ -507,6 +554,36 @@ errlHndl_t INTR::registerMsgQ(msg_q_t i_msgQ, ext_intr_t i_type) return err; } +// Unregister message queue from interrupt handler +msg_q_t INTR::unRegisterMsgQ(ext_intr_t i_type) +{ + msg_q_t msgQ = NULL; + msg_q_t intr_msgQ = msg_q_resolve(INTR_MSGQ); + if(intr_msgQ) + { + msg_t * msg = msg_allocate(); + msg->type = MSG_INTR_UNREGISTER_MSGQ; + msg->data[0] = static_cast<uint64_t>(i_type); + + int rc = msg_sendrecv(intr_msgQ,msg); + + if(!rc) + { + msgQ = reinterpret_cast<msg_q_t>(msg->data[1]); + } + else + { + TRACFCOMP(g_trac_intr,ERR_MRK + "INTR::unRegisterMsgQ - msg_sendrecv failed. errno = %d", + rc); + } + + msg_free(msg); + } + return msgQ; +} + + /* * Enable hardware to report external interrupts */ @@ -522,6 +599,7 @@ errlHndl_t INTR::enableExternalInterrupts() msg_sendrecv(intr_msgQ, msg); err = reinterpret_cast<errlHndl_t>(msg->data[1]); + msg_free(msg); } else { @@ -563,6 +641,7 @@ errlHndl_t INTR::disableExternalInterrupts() msg_sendrecv(intr_msgQ, msg); err = reinterpret_cast<errlHndl_t>(msg->data[1]); + msg_free(msg); } else { diff --git a/src/usr/intr/intrrp.H b/src/usr/intr/intrrp.H index 43e7eaaa7..3e8c06659 100644 --- a/src/usr/intr/intrrp.H +++ b/src/usr/intr/intrrp.H @@ -81,6 +81,23 @@ namespace INTR // If the interrupt can't be handled by the current chip there are // three link registers used provide targets to forward the // interrupt to. + // P7: + // [0] last + // [1] LoopTrip + // [2:18] Reserved + // [19:24] PChip + // [25:27] PCore + // [28:29] TSpec + // [30:31] LSpec + // + // P8: + // [0] last + // [1] LoopTrip + // [2:18] Reserved + // [19:21] NodeId + // [22:24] ChipId + // [25:28] PCore + // [29:31] TSpec struct LinkReg_t { union @@ -88,21 +105,42 @@ namespace INTR uint32_t word; struct { - uint32_t last:1; //!< RO, 0 means last reg - uint32_t loopTrip:1; //!< Stop forwarding - uint32_t reserved:17;//!< Not implemented - uint32_t pchip:6; //!< Target chip - uint32_t pcore:3; //!< Target core - uint32_t tspec:2; //!< Target tread - uint32_t lspec:2; //!< Target link register + uint32_t last:1; //!< RO, 0 means last reg + uint32_t loopTrip:1; //!< Stop forwarding + uint32_t reserved:17; //!< Not implemented + uint32_t node:3; //!< Target node + uint32_t pchip:3; //!< Target chip + uint32_t pcore:4; //!< core(1-6,9-14) + uint32_t tspec:3; //!< Target Thread } PACKED; }; }; /** + * cpu P7PIR register + * @note P7 bits - thread 2, core 3, chip 2, node 3, + */ + struct P7PIR_t + { + union + { + uint32_t word; + struct + { + uint32_t reserved:22; //!< zeros + uint32_t nodeId:3; //!< node (8) + uint32_t chipId:2; //!< chip pos on node (4) + uint32_t coreId:3; //!< Core number (8) + uint32_t threadId:2; //!< thread number (4) + } PACKED; + }; + P7PIR_t(uint32_t i_word) : word(i_word) {} + }; + + + + /** * cpu PIR register - * @note TODO P7 bits - thread 2, core 3, chip 2, node 3, - * P8 will be different. Need P8 book IV */ struct PIR_t { @@ -111,14 +149,31 @@ namespace INTR uint32_t word; struct { - uint32_t reserved:22; //!< zeros - uint32_t nodeId:3; //!< node (4) - uint32_t chipId:2; //!< chip pos on node (8) - uint32_t coreId:3; //!< Core number (12) - uint32_t threadId:2; //!< thread number (8) + //P8: + uint32_t reserved:19; //!< zeros + uint32_t nodeId:3; //!< node (0-3) + uint32_t chipId:3; //!< chip pos on node (0-5) + uint32_t coreId:4; //!< Core number (1-6,9-14)? + uint32_t threadId:3; //!< Thread number (0-7) } PACKED; }; PIR_t(uint32_t i_word) : word(i_word) {} + + PIR_t operator = (uint32_t i_word) + { + word = i_word; + return word; + } + + PIR_t operator = (P7PIR_t i_p7pir) + { + nodeId = i_p7pir.nodeId; + chipId = i_p7pir.chipId; + coreId = i_p7pir.coreId; + threadId = i_p7pir.threadId; + + return word; + } }; diff --git a/src/usr/intr/test/intrtest.H b/src/usr/intr/test/intrtest.H index bd9e316ca..c0fab1492 100644 --- a/src/usr/intr/test/intrtest.H +++ b/src/usr/intr/test/intrtest.H @@ -44,28 +44,33 @@ class IntrTest: public CxxTest::TestSuite */ void test_verifyState( void ) { -#if defined(__INTR_TEST__) - // TODO Temporaritly DISABLE in VBU until P8 support is added + + // TODO Temporaritly DISABLE in VBU until P8 support is verfied if( TARGETING::is_vpo() ) { return; } - // Add support for second chip (dummy) - uint32_t fake_pir = 0x00000001 << 5; // P7 chip 1 TODO P8=? - msg_q_t intr_msgQ = msg_q_resolve(INTR_MSGQ); - msg_t * msg = msg_allocate(); - msg->type = INTR::MSG_INTR_ADD_CPU_USR; - msg->data[0] = fake_pir; + //// Add support for second chip (dummy) + ////uint32_t fake_pir = 0x00000001 << 5; // P7 + //uint32_t fake_pir = 0x00000001 << 7; // P8 + //msg_q_t intr_msgQ = msg_q_resolve(INTR_MSGQ); + //msg_t * msg = msg_allocate(); + //msg->type = INTR::MSG_INTR_ADD_CPU_USR; + //msg->data[0] = fake_pir; - msg_sendrecv(intr_msgQ, msg); + //msg_sendrecv(intr_msgQ, msg); + //msg_free(msg); // all the simics registers - for(uint64_t chip = 0; chip < 4; ++chip) + for(uint64_t chip = 0; chip < 1; ++chip) { - // simics P7 only supports 4 threads per core - // and 2 cores - let the thread field overflow - // into the core field -> 2 cores x 4 threads = 8 threads + // simics P8 appears to support 8 threads on 1 core. + // simics P7 appears to support 4 threads on 2 cores. + // for P7, pretending to have 8 threads works because the + // bit fields for cores and threads are contiguous so we can + // let the thread count overflow into the core field. so this + // works for p7 as well. for(uint64_t thread = 0; thread < 8; ++thread) { uint64_t offset = (chip << 20) | (thread << 12); @@ -78,17 +83,19 @@ class IntrTest: public CxxTest::TestSuite if(*addr != 0xFF000000) { TS_FAIL - ("INTR:Master cpu not initialized-XIRR=0x%08x", - *addr); + ("INTR:Master cpu not initialized-XIRR@%p=0x%08x", + addr,*addr); } } - if (chip < 2 && thread < 4) // TODO Change when all threads supported + // TODO remove restriction when/if simics supports + // more than 2 chips and 4 threads each + if (chip < 2 && thread < 4) { if(offset != 0 && *addr != 0) { - TS_FAIL("INTR:Chip %ld Thread %ld bad XIRR=0x%08x", - chip,thread,*addr); + TS_FAIL("INTR:Chip %ld Thread %ld bad XIRR@%p=0x%08x", + chip,thread,addr,*addr); } @@ -105,7 +112,6 @@ class IntrTest: public CxxTest::TestSuite } } } -#endif } /** @@ -113,8 +119,7 @@ class IntrTest: public CxxTest::TestSuite */ void test_enableDisable( void ) { -#if defined(__INTR_TEST__) - // TODO Temporaritly DISABLE in VBU until P8 support is added + // TODO Temporaritly DISABLE in VBU until P8 support is confirmed if( TARGETING::is_vpo() ) { return; @@ -133,7 +138,7 @@ class IntrTest: public CxxTest::TestSuite if((*addr & 0xFF000000) != 0) { - TS_FAIL("INTR not disabled"); + TS_FAIL("INTR not disabled. Addr %p",addr); } err = INTR::enableExternalInterrupts(); @@ -148,9 +153,8 @@ class IntrTest: public CxxTest::TestSuite if((*addr & 0xFF000000) != 0xFF000000) { - TS_FAIL("INTR not enabled"); + TS_FAIL("INTR not enabled. Addr %p", addr); } -#endif } /** @@ -159,10 +163,7 @@ class IntrTest: public CxxTest::TestSuite */ void test_intr( void ) { - // Injecting interproc interrupt seems to work sometimes and not others - // TODO need to investigate. -#ifdef __NOT_NOW__ - // TODO Temporaritly DISABLE in VBU until P8 support is added + // TODO Temporaritly DISABLE in VBU until P8 support is confirmed if( TARGETING::is_vpo() ) { return; @@ -193,7 +194,16 @@ class IntrTest: public CxxTest::TestSuite TS_FAIL("INTR::unexpected interrupt type %lx",msg->type); } msg_respond(msgQ,msg); -#endif + + msgQ = INTR::unRegisterMsgQ(INTR::INTERPROC); + if(msgQ) + { + msg_q_destroy(msgQ); + } + else + { + TS_FAIL("INTR::unRegisterMsgQ failed"); + } } |