summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2012-03-22 11:14:00 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-03-27 15:12:30 -0500
commit64a9a50f5582133148c7960adae83021e1c23d8c (patch)
treebe09d0bab769ad00c6e1aab09e40dc1fbd86c7eb /src/usr
parente365e2055da924ce134e2f8263d47a6afba23e98 (diff)
downloadblackbird-hostboot-64a9a50f5582133148c7960adae83021e1c23d8c.tar.gz
blackbird-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')
-rw-r--r--src/usr/intr/intrrp.C153
-rw-r--r--src/usr/intr/intrrp.H83
-rw-r--r--src/usr/intr/test/intrtest.H68
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");
+ }
}
OpenPOWER on IntegriCloud