diff options
author | dgilbert <dgilbert@us.ibm.com> | 2012-11-27 11:41:04 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-12-19 16:02:43 -0600 |
commit | f5ae894024733fe3fb5ae26aaaa67cc8df0d0a3c (patch) | |
tree | 7bcc9aa241f64758736e88d4f1bc9c4bf72db252 /src/usr/intr | |
parent | 9458535739acca481800bbda1b59d4f1b213d2c2 (diff) | |
download | talos-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.C | 428 | ||||
-rw-r--r-- | src/usr/intr/intrrp.H | 203 | ||||
-rw-r--r-- | src/usr/intr/test/intrtest.H | 76 |
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, + ®, + 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, + ®, + 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() { |