summaryrefslogtreecommitdiffstats
path: root/src/usr/intr
diff options
context:
space:
mode:
authordgilbert <dgilbert@us.ibm.com>2012-11-27 11:41:04 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-12-19 16:02:43 -0600
commitf5ae894024733fe3fb5ae26aaaa67cc8df0d0a3c (patch)
tree7bcc9aa241f64758736e88d4f1bc9c4bf72db252 /src/usr/intr
parent9458535739acca481800bbda1b59d4f1b213d2c2 (diff)
downloadtalos-hostboot-f5ae894024733fe3fb5ae26aaaa67cc8df0d0a3c.tar.gz
talos-hostboot-f5ae894024733fe3fb5ae26aaaa67cc8df0d0a3c.zip
Initialize the PIB hardware layer for interrupts
RTC: 47105 Change-Id: Iba893e65ee468b56e9e929a26d2888a67a4788af Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/2433 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.C428
-rw-r--r--src/usr/intr/intrrp.H203
-rw-r--r--src/usr/intr/test/intrtest.H76
3 files changed, 612 insertions, 95 deletions
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C
index 989f47979..f667220f3 100644
--- a/src/usr/intr/intrrp.C
+++ b/src/usr/intr/intrrp.C
@@ -36,16 +36,19 @@
#include <sys/misc.h>
#include <kernel/console.H>
#include <sys/task.h>
-#include <targeting/common/targetservice.H>
#include <vmmconst.h>
+#include <targeting/common/targetservice.H>
#include <targeting/common/attributes.H>
+#include <targeting/common/utilFilter.H>
#include <devicefw/userif.H>
#include <sys/time.h>
#include <sys/vfs.h>
+#include <hwas/common/hwasCallout.H>
#define INTR_TRACE_NAME INTR_COMP_NAME
using namespace INTR;
+using namespace TARGETING;
trace_desc_t * g_trac_intr = NULL;
TRAC_INIT(&g_trac_intr, INTR_TRACE_NAME, KILOBYTE, TRACE::BUFFER_SLOW);
@@ -161,6 +164,12 @@ errlHndl_t IntrRp::_init()
INITSERVICE::INTR_PRIORITY);
}
+ if(!err)
+ {
+ // Enable PSI to present interrupts
+ err = initIRSCReg(procTarget);
+ }
+
return err;
}
@@ -263,7 +272,7 @@ void IntrRp::msgHandler()
}
msg_free(rmsg);
}
- else if (type == INTERPROC)
+ else if (type == INTERPROC_XISR)
{
// Ignore "spurious" IPIs (handled below).
@@ -278,13 +287,13 @@ void IntrRp::msgHandler()
TRACFCOMP(g_trac_intr,ERR_MRK
"External Interrupt recieved type = %d, but "
"nothing registered to handle it. "
- "Ignoreing it.",
+ "Ignoring it.",
(uint32_t)type);
}
// Handle IPIs special since they're used for waking up
// cores and have special clearing requirements.
- if (type == INTERPROC)
+ if (type == INTERPROC_XISR)
{
// Clear IPI request.
volatile uint8_t * mfrr =
@@ -331,8 +340,15 @@ void IntrRp::msgHandler()
{
msg_q_t l_msgQ = reinterpret_cast<msg_q_t>(msg->data[0]);
uint64_t l_type = msg->data[1];
- ext_intr_t l_intr_type = static_cast<ext_intr_t>(l_type & 0xFFFF);
- errlHndl_t err = registerInterrupt(l_msgQ,l_type >> 32,l_intr_type);
+ ISNvalue_t l_intr_type = static_cast<ISNvalue_t>
+ (l_type & 0xFFFF);
+
+ errlHndl_t err = registerInterruptISN(l_msgQ,l_type >> 32,
+ l_intr_type);
+ if(!err)
+ {
+ err = initXIVR(l_intr_type, true);
+ }
msg->data[1] = reinterpret_cast<uint64_t>(err);
msg_respond(iv_msgQ,msg);
@@ -344,14 +360,18 @@ void IntrRp::msgHandler()
TRACFCOMP(g_trac_intr,
"INTR remove registration of interrupt type = 0x%lx",
msg->data[0]);
+ ISNvalue_t l_type = static_cast<ISNvalue_t>(msg->data[0]);
+ msg_q_t msgQ = unregisterInterruptISN(l_type);
- 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())
+ if(msgQ)
{
- msgQ = r->second.msgQ;
- iv_registry.erase(r);
+ //shouldn't get an error since we found a queue
+ //Just commit it
+ errlHndl_t err = initXIVR(l_type, false);
+ if(err)
+ {
+ errlCommit(err,INTR_COMP_ID);
+ }
}
msg->data[1] = reinterpret_cast<uint64_t>(msgQ);
@@ -405,6 +425,16 @@ void IntrRp::msgHandler()
}
break;
+ case MSG_INTR_ENABLE_PSI_INTR:
+ {
+ TARGETING::Target * target =
+ reinterpret_cast<TARGETING::Target *>(msg->data[0]);
+ errlHndl_t err = initIRSCReg(target);
+ msg->data[1] = reinterpret_cast<uint64_t>(err);
+ msg_respond(iv_msgQ,msg);
+ }
+ break;
+
case MSG_INTR_SHUTDOWN:
{
TRACFCOMP(g_trac_intr,"Shutdown event received");
@@ -454,47 +484,293 @@ errlHndl_t IntrRp::setBAR(TARGETING::Target * i_target,
}
+errlHndl_t IntrRp::initIRSCReg(TARGETING::Target * i_target)
+{
+ errlHndl_t err = NULL;
+
+ // Only do once for each proc chip
+ if(std::find(iv_chipList.begin(),iv_chipList.end(),i_target) ==
+ iv_chipList.end())
+ {
+ uint8_t chip = 0;
+ uint8_t node = 0;
+
+ i_target->tryGetAttr<ATTR_FABRIC_NODE_ID>(node);
+ i_target->tryGetAttr<ATTR_FABRIC_CHIP_ID>(chip);
+
+ size_t scom_len = sizeof(uint64_t);
+
+ // Setup PHBISR
+ // EN.TPC.PSIHB.PSIHB_ISRN_REG set to 0x00030003FFFF0000
+ PSIHB_ISRN_REG_t reg;
+
+ PIR_t pir(0);
+ pir.nodeId = node;
+ pir.chipId = chip;
+ // IRSN must be unique for each processor chip
+ reg.irsn = makeXISR(pir,0);
+ reg.die = PSIHB_ISRN_REG_t::ENABLE;
+ reg.uie = PSIHB_ISRN_REG_t::ENABLE;
+ reg.mask = PSIHB_ISRN_REG_t::IRSN_MASK;
+
+ TRACFCOMP(g_trac_intr,"PSIHB_ISRN_REG: 0x%016lx",reg.d64);
+
+ err = deviceWrite
+ ( i_target,
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG));
+
+ if(err)
+ {
+ // add callout
+ err->addHwCallout(i_target,
+ HWAS::SRCI_PRIORITY_HIGH,
+ HWAS::DECONFIG,
+ HWAS::GARD_NULL);
+ }
+ else
+ {
+ iv_chipList.push_back(i_target);
+ }
+ }
+
+ return err;
+}
-errlHndl_t IntrRp::registerInterrupt(msg_q_t i_msgQ,
+errlHndl_t IntrRp::initXIVR(enum ISNvalue_t i_isn, bool i_enable)
+{
+ errlHndl_t err = NULL;
+ size_t scom_len = sizeof(uint64_t);
+ uint64_t scom_addr = 0;
+
+ //Don't do any of this for ISN_INTERPROC
+ if(ISN_INTERPROC != i_isn)
+ {
+ //Setup the XIVR register
+ PsiHbXivr xivr;
+ PIR_t pir = intrDestCpuId();
+ xivr.pir = pir.word;
+ xivr.source = i_isn;
+
+ switch(i_isn)
+ {
+ case ISN_OCC:
+ xivr.priority = PsiHbXivr::OCC_PRIO;
+ scom_addr = PsiHbXivr::OCC_XIVR_ADRR;
+ break;
+
+ case ISN_FSI: //FSP_MAILBOX
+ xivr.priority = PsiHbXivr::FSI_PRIO;
+ scom_addr = PsiHbXivr::FSI_XIVR_ADRR;
+ break;
+
+ case ISN_LPC:
+ xivr.priority = PsiHbXivr::LPC_PRIO;
+ scom_addr = PsiHbXivr::LPC_XIVR_ADRR;
+ break;
+
+ case ISN_LCL_ERR:
+ xivr.priority = PsiHbXivr::LCL_ERR_PRIO;
+ scom_addr = PsiHbXivr::LCL_ERR_XIVR_ADDR;
+ break;
+
+ case ISN_HOST:
+ xivr.priority = PsiHbXivr::HOST_PRIO;
+ scom_addr = PsiHbXivr::HOST_XIVR_ADRR;
+ break;
+
+ default: //Unsupported ISN
+ TRACFCOMP(g_trac_intr,"Unsupported ISN: 0x%02x",i_isn);
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid INTR::MOD_INTR_INIT_XIVR
+ * @reasoncode INTR::RC_BAD_ISN
+ * @userdata1 Interrupt type to register
+ * @userdata2 0
+ *
+ * @defdesc Unsupported ISN Requested
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL, // severity
+ INTR::MOD_INTR_INIT_XIVR, // moduleid
+ INTR::RC_BAD_ISN, // reason code
+ static_cast<uint64_t>(i_isn),
+ 0
+ );
+ }
+
+ // Init the XIVR on all chips we have setup
+ // Note that this doesn't handle chips getting added midstream,
+ // But the current use case only has FSIMbox (1 chip) and
+ // ATTN (all chips) at stable points in the IPL
+ if(!err)
+ {
+ if(i_enable)
+ {
+ iv_isnList.push_back(i_isn);
+ }
+ else
+ {
+ xivr.priority = PsiHbXivr::PRIO_DISABLED;
+
+ //Remove from isn list
+ ISNList_t::iterator itr = std::find(iv_isnList.begin(),
+ iv_isnList.end(),
+ i_isn);
+ if(itr != iv_isnList.end())
+ {
+ iv_isnList.erase(itr);
+ }
+ }
+
+ for(ChipList_t::iterator target_itr = iv_chipList.begin();
+ target_itr != iv_chipList.end(); ++target_itr)
+ {
+ err = deviceWrite
+ (*target_itr,
+ &xivr,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(scom_addr));
+
+ if(err)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return err;
+}
+
+
+
+errlHndl_t IntrRp::registerInterruptISN(msg_q_t i_msgQ,
uint32_t i_msg_type,
ext_intr_t i_intr_type)
{
errlHndl_t err = NULL;
- Registry_t::iterator r = iv_registry.find(i_intr_type);
+ //INTERPROC is special -- same for all procs
+ if(i_intr_type == ISN_INTERPROC)
+ {
+ err = registerInterruptXISR(i_msgQ, i_msg_type,
+ INTERPROC_XISR);
+ }
+ else
+ {
+ //Register interrupt type on all present procs
+ for(ChipList_t::iterator target_itr = iv_chipList.begin();
+ target_itr != iv_chipList.end(); ++target_itr)
+ {
+ uint8_t chip = 0;
+ uint8_t node = 0;
+ (*target_itr)->tryGetAttr<ATTR_FABRIC_NODE_ID>(node);
+ (*target_itr)->tryGetAttr<ATTR_FABRIC_CHIP_ID>(chip);
+
+ PIR_t pir(0);
+ pir.nodeId = node;
+ pir.chipId = chip;
+ uint32_t l_irsn = makeXISR(pir, i_intr_type);
+
+ err = registerInterruptXISR(i_msgQ, i_msg_type, l_irsn);
+ if(err)
+ {
+ break;
+ }
+ }
+ }
+ return err;
+}
+
+errlHndl_t IntrRp::registerInterruptXISR(msg_q_t i_msgQ,
+ uint32_t i_msg_type,
+ ext_intr_t i_xisr)
+{
+ errlHndl_t err = NULL;
+
+ Registry_t::iterator r = iv_registry.find(i_xisr);
if(r == iv_registry.end())
{
- TRACFCOMP(g_trac_intr,"INTR::register intr type 0x%x", i_intr_type);
- iv_registry[i_intr_type] = intr_response_t(i_msgQ,i_msg_type);
+ TRACFCOMP(g_trac_intr,"INTR::register intr type 0x%x", i_xisr);
+ iv_registry[i_xisr] = intr_response_t(i_msgQ,i_msg_type);
}
else
{
if(r->second.msgQ != i_msgQ)
{
- /*@ errorlog tag
- * @errortype ERRL_SEV_INFORMATIONAL
- * @moduleid INTR::MOD_INTRRP_REGISTERINTERRUPT
- * @reasoncode INTR::RC_ALREADY_REGISTERED
- * @userdata1 Interrupt type
- * @userdata2 0
- *
- * @defdesc Interrupt type already registered
- *
- */
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid INTR::MOD_INTRRP_REGISTERINTERRUPT
+ * @reasoncode INTR::RC_ALREADY_REGISTERED
+ * @userdata1 XISR
+ * @userdata2 0
+ *
+ * @defdesc Interrupt type already registered
+ *
+ */
err = new ERRORLOG::ErrlEntry
- (
- ERRORLOG::ERRL_SEV_INFORMATIONAL, // severity
- INTR::MOD_INTRRP_REGISTERINTERRUPT, // moduleid
- INTR::RC_ALREADY_REGISTERED, // reason code
- i_intr_type,
- 0
- );
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL, // severity
+ INTR::MOD_INTRRP_REGISTERINTERRUPT, // moduleid
+ INTR::RC_ALREADY_REGISTERED, // reason code
+ i_xisr,
+ 0
+ );
}
-
}
return err;
}
+msg_q_t IntrRp::unregisterInterruptISN(ISNvalue_t i_intr_type)
+{
+ msg_q_t msgQ = NULL;
+
+ //INTERPROC is special -- same for all procs
+ if(i_intr_type == ISN_INTERPROC)
+ {
+ msgQ = unregisterInterruptXISR(INTERPROC_XISR);
+ }
+ else
+ {
+ //Unregister interrupt type on all present procs
+ for(ChipList_t::iterator target_itr = iv_chipList.begin();
+ target_itr != iv_chipList.end(); ++target_itr)
+ {
+ uint8_t chip = 0;
+ uint8_t node = 0;
+ (*target_itr)->tryGetAttr<ATTR_FABRIC_NODE_ID>(node);
+ (*target_itr)->tryGetAttr<ATTR_FABRIC_CHIP_ID>(chip);
+
+ PIR_t pir(0);
+ pir.nodeId = node;
+ pir.chipId = chip;
+ uint32_t l_irsn = makeXISR(pir, i_intr_type);
+
+ msgQ = unregisterInterruptXISR(l_irsn);
+ }
+ }
+
+ return msgQ;
+}
+
+msg_q_t IntrRp::unregisterInterruptXISR(ext_intr_t i_xisr)
+{
+ msg_q_t msgQ = NULL;
+
+ Registry_t::iterator r = iv_registry.find(i_xisr);
+ if(r != iv_registry.end())
+ {
+ msgQ = r->second.msgQ;
+ iv_registry.erase(r);
+ }
+
+ return msgQ;
+}
+
void IntrRp::initInterruptPresenter(const PIR_t i_pir) const
{
uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(i_pir);
@@ -621,6 +897,7 @@ errlHndl_t IntrRp::checkAddress(uint64_t i_addr)
void IntrRp::shutDown()
{
+ errlHndl_t err = NULL;
msg_t * rmsg = msg_allocate();
// Call everyone and say shutting down!
@@ -647,7 +924,49 @@ void IntrRp::shutDown()
msg_free(rmsg);
- // Reset the hardware regiseters
+ // Reset the PSI regs
+ // NOTE: there is nothing in the IRSN Proposal.odt document that
+ // specifies a procedure or order for disabling interrupts.
+ // @see RTC story 47105 discussion for Firmware & Hardware requirements
+ //
+
+ //Going to clear the XIVRs first
+ ISNList_t l_isnList = iv_isnList;
+ for(ISNList_t::iterator isnItr = l_isnList.begin();
+ isnItr != l_isnList.end();++isnItr)
+ {
+ //shouldn't get an error since we found a queue
+ //so just commit it
+ err = initXIVR((*isnItr), false);
+ if(err)
+ {
+ errlCommit(err,INTR_COMP_ID);
+ err = NULL;
+ }
+ }
+
+ // TODO secure boot - how do we know a processor chip has been added?
+ PSIHB_ISRN_REG_t reg; //zeros self
+ size_t scom_len = sizeof(reg);
+
+ for(ChipList_t::iterator target_itr = iv_chipList.begin();
+ target_itr != iv_chipList.end(); ++target_itr)
+ {
+ err = deviceWrite
+ (*target_itr,
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG));
+
+ if(err)
+ {
+ errlCommit(err,INTR_COMP_ID);
+ err = NULL;
+ }
+ }
+
+
+ // Reset the IP hardware regiseters
iv_cpuList.push_back(iv_masterCpu);
@@ -839,8 +1158,43 @@ errlHndl_t INTR::disableExternalInterrupts()
return err;
}
-uint32_t INTR::intrDestCpuId(uint32_t i_xisr)
+errlHndl_t INTR::enablePsiIntr(TARGETING::Target * i_target)
{
- return Singleton<IntrRp>::instance().intrDestCpuId(i_xisr);
+ errlHndl_t err = NULL;
+ msg_q_t intr_msgQ = msg_q_resolve(VFS_ROOT_MSG_INTR);
+ if(intr_msgQ)
+ {
+ msg_t * msg = msg_allocate();
+ msg->type = MSG_INTR_ENABLE_PSI_INTR;
+ msg->data[0] = reinterpret_cast<uint64_t>(i_target);
+
+ msg_sendrecv(intr_msgQ, msg);
+
+ err = reinterpret_cast<errlHndl_t>(msg->data[1]);
+ msg_free(msg);
+ }
+ else
+ {
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid INTR::MOD_INTR_ENABLE_PSI_INTR
+ * @reasoncode INTR::RC_RP_NOT_INITIALIZED
+ * @userdata1 MSG_INTR_ENABLE_PSI_INTR
+ * @userdata2 0
+ *
+ * @defdesc Interrupt resource provider not initialized yet.
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL, // severity
+ INTR::MOD_INTR_ENABLE_PSI_INTR, // moduleid
+ INTR::RC_RP_NOT_INITIALIZED, // reason code
+ static_cast<uint64_t>(MSG_INTR_ENABLE_PSI_INTR),
+ 0
+ );
+ }
+ return err;
}
+
diff --git a/src/usr/intr/intrrp.H b/src/usr/intr/intrrp.H
index d8c01208b..ad13c1679 100644
--- a/src/usr/intr/intrrp.H
+++ b/src/usr/intr/intrrp.H
@@ -31,6 +31,7 @@
#include <sys/misc.h>
#include <intr/interrupt.H>
#include <map>
+#include <algorithm>
struct msg_t;
@@ -41,6 +42,57 @@ namespace TARGETING
namespace INTR
{
+ /**
+ * cpu PIR register
+ */
+ struct PIR_t
+ {
+ union
+ {
+ uint32_t word;
+ struct
+ {
+ //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;
+ }
+
+ bool operator< (const PIR_t& r) const
+ {
+ return word < r.word;
+ }
+ };
+
+ /**
+ * Make an XISR value
+ * @param[in] i_node The PIR node id (0-7)
+ * @param[in] i_chip The PIR chip id (0-7)
+ * @param[in] i_isn The Interrupt Source Number (0-7)
+ * @return the XISR value
+ */
+ inline
+ uint32_t makeXISR(PIR_t i_pir, uint32_t i_isn)
+ {
+ XISR_t r;
+ r.u32 = 0;
+ r.isn = i_isn;
+ r.chip = i_pir.chipId;
+ r.node = i_pir.nodeId;
+ r.intrproc = 1; // not interproc intr
+ return r.u32;
+ }
+
class IntrRp
{
public:
@@ -53,9 +105,10 @@ namespace INTR
/**
* Get the CPU id of the master cpu.
+ * @return cpu id of the master cpu
*/
ALWAYS_INLINE
- uint32_t intrDestCpuId(uint32_t i_xisr) const { return iv_masterCpu.word; }
+ PIR_t intrDestCpuId() const { return iv_masterCpu; }
protected:
@@ -81,21 +134,21 @@ namespace INTR
enum
{
- XIRR_RO_OFFSET = 0, //!< offset to XIRR (poll)
- CPPR_OFFSET = 4, //!< offset to CPPR (1 byte)
- XIRR_OFFSET = 4, //!< offset to XIRR (4 bytes)
- MFRR_OFFSET = 12, //!< offset to MFRR (12 bytes)
- LINKA_OFFSET = 16, //!< offset to LINKA register
- LINKB_OFFSET = 20, //!< offset to LINKB register
- LINKC_OFFSET = 24, //!< offset to LINKC register
- XISR_MASK = 0x00FFFFFF, //!< XISR MASK in XIRR register
+ XIRR_RO_OFFSET = 0, //!< offset to XIRR (poll)
+ CPPR_OFFSET = 4, //!< offset to CPPR (1 byte)
+ XIRR_OFFSET = 4, //!< offset to XIRR (4 bytes)
+ MFRR_OFFSET = 12, //!< offset to MFRR (12 bytes)
+ LINKA_OFFSET = 16, //!< offset to LINKA register
+ LINKB_OFFSET = 20, //!< offset to LINKB register
+ LINKC_OFFSET = 24, //!< offset to LINKC register
+ XISR_MASK = 0x00FFFFFF, //!< XISR MASK in XIRR register
ICPBAR_EN = 30, //!< BAR enable bit pos
ICPBAR_SCOM_ADDR = 0x020109ca, //!< ICP BAR scom address
// MASK base ICP address
ICPBAR_BASE_ADDRESS_MASK = 0xFFFFFFFFFC000000ULL,
- };
+ };
// If the interrupt can't be handled by the current chip there are
// three link registers used provide targets to forward the
@@ -136,37 +189,85 @@ namespace INTR
};
/**
- * cpu PIR register
+ * This is the Interrupt Requestoer Source Compare Register.
+ * See Book IV, PSI chapter.
*/
- struct PIR_t
+ struct PSIHB_ISRN_REG_t
{
+ enum
+ {
+ //PSIHB_ISRN_REG_t values. See book IV & P8 scom reg defn.
+ DISABLE = 0,
+ ENABLE = 1,
+ IRSN_MASK = 0x7FFF8, //!< IRSN bits
+ PSIHB_ISRN_REG = 0x0201091b, //!< ISRN SCOM Address
+ };
+
union
{
- uint32_t word;
+ uint64_t d64;
+
struct
{
- //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)
+ uint64_t irsn:19; //!< IRSN compare reg
+ uint64_t res1:10; //!< zeros
+ uint64_t reset:1; //!< ICS Reset
+ uint64_t die:1; //!< Downstream Interrupt Enable
+ uint64_t uie:1; //!< Upstream Interrupt Enable
+ uint64_t mask:19; //!< IRSN Compare Mask
+ uint64_t res2:13; //!< zeros
} PACKED;
};
- PIR_t(uint32_t i_word) : word(i_word) {}
- PIR_t operator= (uint32_t i_word)
+ /**
+ * Default Contructor
+ */
+ PSIHB_ISRN_REG_t() : d64(0) {}
+ };
+
+ /**
+ * @brief PsiHbXivr Layout for XIVR registers.
+ */
+ struct PsiHbXivr
+ {
+ enum
{
- word = i_word;
- return word;
- }
+ PRIO_DISABLED = 0xff,
+
+ OCC_PRIO = 0x30,
+ FSI_PRIO = 0x20,
+ LPC_PRIO = 0x40,
+ LCL_ERR_PRIO = 0x10,
+ HOST_PRIO = 0x50,
+
+ OCC_XIVR_ADRR = 0x02010916,
+ FSI_XIVR_ADRR = 0x02010917,
+ LPC_XIVR_ADRR = 0x02010918,
+ LCL_ERR_XIVR_ADDR = 0x02010919,
+ HOST_XIVR_ADRR = 0x0201091A,
+ };
- bool operator< (const PIR_t& r) const
+
+ union
{
- return word < r.word;
- }
+ uint64_t u64;
+
+ struct
+ {
+ uint64_t res1:8; // zeros
+ uint64_t pir:14; // interrupt destination (server)
+ uint64_t linkptr:2; // which link reg in intr presenter
+ uint64_t priority:8; // intr priority level
+ uint64_t source:3; // source number
+ uint64_t res2:4; // zeros
+ uint64_t intr_pend:25; // interrupt is pending
+ } PACKED;
+ };
+
+ PsiHbXivr() : u64(0) {}
};
+
struct intr_response_t
{
msg_q_t msgQ;
@@ -187,9 +288,10 @@ namespace INTR
};
-
typedef std::map<ext_intr_t,intr_response_t> Registry_t;
typedef std::vector<PIR_t> CpuList_t;
+ typedef std::vector<TARGETING::Target *> ChipList_t;
+ typedef std::vector<ISNvalue_t> ISNList_t;
msg_q_t iv_msgQ; //!< Kernel Interrupt message queue
@@ -197,6 +299,8 @@ namespace INTR
uint64_t iv_baseAddr; //!< Base address of hw INTR regs
PIR_t iv_masterCpu; //!< Master cpu PIR
CpuList_t iv_cpuList; //!< Other CPU chips
+ ChipList_t iv_chipList; //!< Proc chips with PSI intr enabled
+ ISNList_t iv_isnList; //!< List of ISN's to clear on shutdown
typedef std::pair<uint8_t, msg_t*> IPI_Info_t;
typedef std::map<PIR_t, IPI_Info_t> IPI_Pending_t;
@@ -220,8 +324,8 @@ namespace INTR
* i_intr_type occurrs.
* @param[in] i_intr_type, The interrupt type to register.
*
- * @note the interrupt type is currently the XISR value in the XIRR
- * register and consists of the chipid, buid, and level
+ * @note the interrupt type is currently the ISN value in the XIVR
+ * register. and consists of the chipid, buid, and level
* @see src/include/usr/intr/interrupt.H i_intr_type for
* enumerations.
*
@@ -230,9 +334,28 @@ namespace INTR
* i_msgQ with i_intr_type in message data word 0 and then waits
* for a response.
*/
- errlHndl_t registerInterrupt(msg_q_t i_msgQ,
+ errlHndl_t registerInterruptISN(msg_q_t i_msgQ,
uint32_t i_msg_type,
ext_intr_t i_intr_type);
+ /* Same as above, but operates directly on XISR*/
+ errlHndl_t registerInterruptXISR(msg_q_t i_msgQ,
+ uint32_t i_msg_type,
+ ext_intr_t i_xisr);
+
+ /**
+ * Unregister for a given interrupt type
+ * @param[in] i_isn_type The type of interrupt to unregister
+ *
+ * @note the interrupt type is currently the ISN value in the PSIHB
+ * XIVR register
+ * @see i_intr_type for enumerations.
+ *
+ * @return The message queue that was unregistered with i_type
+ * | NULL if no queue was not found for i_type
+ */
+ msg_q_t unregisterInterruptISN(ISNvalue_t i_intr_type);
+ /*Same as above, but operates on XISR*/
+ msg_q_t unregisterInterruptXISR(ext_intr_t i_xisr);
/**
* Enable hardware to reporting external interrupts
@@ -271,6 +394,22 @@ namespace INTR
const PIR_t i_pir);
/**
+ * Initialize the IRSCReg to enable PSI to present interrupts
+ * @param[in] i_target The target processor
+ * @return error log handle on error
+ */
+ errlHndl_t initIRSCReg(TARGETING::Target * i_target);
+
+ /**
+ * Initialize the PSIHB XIVR Reg to generate interrupts
+ * on all processors for given ISN
+ * @param[in] i_isn XIVR to enable/disable
+ * @param[in] i_enable enable (true), disable(false)
+ * @return error log handle on error
+ */
+ errlHndl_t initXIVR(enum ISNvalue_t i_isn, bool i_enable);
+
+ /**
* Shutdown procedure
*/
void shutDown();
@@ -280,7 +419,7 @@ namespace INTR
* @param[in] i_pir PIR value for the presenter
* @return the offset
*/
- ALWAYS_INLINE
+ ALWAYS_INLINE
uint64_t cpuOffsetAddr(const PIR_t i_pir) const
{
// TODO when P7 support is removed then change this
diff --git a/src/usr/intr/test/intrtest.H b/src/usr/intr/test/intrtest.H
index 93c2d235a..c12835d77 100644
--- a/src/usr/intr/test/intrtest.H
+++ b/src/usr/intr/test/intrtest.H
@@ -1,25 +1,25 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/usr/intr/test/intrtest.H $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/intr/test/intrtest.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2011,2012 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
#ifndef __INTRTEST_H
#define __INTRTEST_H
@@ -139,7 +139,7 @@ class IntrTest: public CxxTest::TestSuite
// Need to register a msgq
msg_q_t msgQ = msg_q_create();
- err = INTR::registerMsgQ(msgQ,0,INTR::INTERPROC);
+ err = INTR::registerMsgQ(msgQ,0,INTR::ISN_INTERPROC);
if(err)
{
TS_FAIL("Errl from INTR::registerMsgQ()");
@@ -151,16 +151,17 @@ class IntrTest: public CxxTest::TestSuite
volatile uint8_t * mfrr =
reinterpret_cast<uint8_t *>(iv_masterAddr+12);
*(mfrr) = 0x55;
-
+
+ TRACFCOMP(g_trac_intr,"Waiting for IPI interrupt");
msg_t* msg = msg_wait(msgQ); // wait for interrupt msg
TRACFCOMP(g_trac_intr,"Interrupt handled! Type=%lx",msg->data[0]);
- if(msg->data[0] != INTR::INTERPROC)
+ if(msg->data[0] != INTR::INTERPROC_XISR)
{
TS_FAIL("INTR::unexpected interrupt type %lx",msg->data[0]);
}
msg_respond(msgQ,msg);
- msgQ = INTR::unRegisterMsgQ(INTR::INTERPROC);
+ msgQ = INTR::unRegisterMsgQ(INTR::ISN_INTERPROC);
if(msgQ)
{
msg_q_destroy(msgQ);
@@ -171,6 +172,29 @@ class IntrTest: public CxxTest::TestSuite
}
}
+ // This checks the enablePsiIntr. Even though the master proc
+ // is already configured it does not use this interface
+ // and there are no other processor currently configured in simics
+ // to test with.
+ void test_enablePsi( void )
+ {
+ errlHndl_t err = NULL;
+ if( TARGETING::is_vpo() )
+ {
+ return;
+ }
+
+ TARGETING::Target* target = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle( target );
+
+ err = INTR::enablePsiIntr(target);
+ if(err)
+ {
+ TS_FAIL("Errl from INTER::enablePsiIntr");
+ errlCommit(err,INTR_COMP_ID);
+ }
+ }
+
IntrTest() : CxxTest::TestSuite()
{
OpenPOWER on IntegriCloud