diff options
author | Dean Sanner <dsanner@us.ibm.com> | 2013-07-16 14:58:43 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-08-21 15:38:53 -0500 |
commit | b814311a6dc122e761336881130eace63d3533e7 (patch) | |
tree | 1330190b59abbe6fc094de1b5afda87abacc100b | |
parent | a6f46d0a9461b96781bc85c9fd82c24d14b5ce42 (diff) | |
download | talos-hostboot-b814311a6dc122e761336881130eace63d3533e7.tar.gz talos-hostboot-b814311a6dc122e761336881130eace63d3533e7.zip |
Handle interrupts on MPIPL
Change-Id: I315d5c802819bf6f16cd6adbffe77530bd42699a
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5427
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | src/include/kernel/intmsghandler.H | 4 | ||||
-rw-r--r-- | src/include/usr/intr/interrupt.H | 3 | ||||
-rw-r--r-- | src/include/usr/runtime/runtime.H | 29 | ||||
-rw-r--r-- | src/include/usr/runtime/runtime_reasoncodes.H | 2 | ||||
-rw-r--r-- | src/kernel/intmsghandler.C | 14 | ||||
-rw-r--r-- | src/usr/dump/dumpCollect.C | 74 | ||||
-rw-r--r-- | src/usr/dump/dumpCollect.H | 4 | ||||
-rw-r--r-- | src/usr/dump/test/dumptest.H | 61 | ||||
-rw-r--r-- | src/usr/hwas/hostbootIstep.C | 2 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dram_initialization/dram_initialization.C | 20 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C | 452 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/start_payload/start_payload.C | 9 | ||||
-rw-r--r-- | src/usr/initservice/extinitsvc/extinitsvctasks.H | 25 | ||||
-rw-r--r-- | src/usr/intr/intrrp.C | 710 | ||||
-rw-r--r-- | src/usr/intr/intrrp.H | 92 | ||||
-rw-r--r-- | src/usr/runtime/hdatservice.C | 129 | ||||
-rw-r--r-- | src/usr/runtime/hdatservice.H | 48 |
17 files changed, 1216 insertions, 462 deletions
diff --git a/src/include/kernel/intmsghandler.H b/src/include/kernel/intmsghandler.H index 3f888f94b..220a7fa30 100644 --- a/src/include/kernel/intmsghandler.H +++ b/src/include/kernel/intmsghandler.H @@ -67,7 +67,9 @@ class InterruptMsgHdlr : public MessageHandler XIRR_ADDR_OFFSET = 4, MFRR_ADDR_OFFSET = 12, - INTP_BAR_VALUE = 0xFFFFE000, // upper 32 bits of IPCBAR + INTP_BAR_VALUE = 0xFFFFE000, // upper 32 bits of IPCBAR + + INTERPROC_XISR = 2, //IPI XISR is 2 }; /** diff --git a/src/include/usr/intr/interrupt.H b/src/include/usr/intr/interrupt.H index f41f8ccf6..473fa7cd3 100644 --- a/src/include/usr/intr/interrupt.H +++ b/src/include/usr/intr/interrupt.H @@ -90,7 +90,7 @@ namespace INTR enum ISNvalue_t { - ISN_FSP = 0, + ISN_PSI = 0, ISN_OCC = 1, ISN_FSI = 2, FSP_MAILBOX = 2, @@ -138,6 +138,7 @@ namespace INTR MSG_INTR_DISABLE, //!< Disable external interrupts MSG_INTR_SHUTDOWN, //!< Call to shutdown interrupt presenter MSG_INTR_ENABLE_PSI_INTR, //!< Enable PSI interrupts + MSG_INTR_MPIPL_CLEANUP, //!< Clean up interrupts on MPIPL }; /** diff --git a/src/include/usr/runtime/runtime.H b/src/include/usr/runtime/runtime.H index 59233c566..0536d2c63 100644 --- a/src/include/usr/runtime/runtime.H +++ b/src/include/usr/runtime/runtime.H @@ -96,6 +96,35 @@ errlHndl_t get_host_data_section( SectionId i_section, size_t& o_dataSize ); const size_t DATA_SIZE_UNKNOWN = 0xFFFFFFFFFFFFFFFF; +/** + * @brief Update the actual count of section. Only supported for + * memory dump results table + * + * @param[in] i_section Chunk of data to find + * @param[out] i_count Actual countPhysical memory address of data + * + * @return errlHndl_t NULL on success + */ +errlHndl_t update_host_data_section_actual( SectionId i_section, + uint16_t i_count ); + +/** + * @brief This function updates the actual count for the MDRT + * May be called at anytime, but the actual value is updated + * to the SPIRA during populate_attributes + * + */ +void update_MDRT_Count(uint16_t i_count); + +/** + * @brief This function writes the stored count for the MDRT + * out to the SPIRA + * + * @return errlHndl_t + */ +errlHndl_t write_MDRT_Count(void); + + } #endif diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H index cda640d85..3c888abf1 100644 --- a/src/include/usr/runtime/runtime_reasoncodes.H +++ b/src/include/usr/runtime/runtime_reasoncodes.H @@ -45,7 +45,7 @@ namespace RUNTIME MOD_TCE_INIT = 0x0D, /**< tce.C */ MOD_TCE_MAP = 0x0E, /**< tce.C */ MOD_HDATSERVICE_FINDSPIRA = 0x0F, /** hdatservice.C */ - + MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL = 0x10, /**< hdatservice.C */ }; enum RuntimeReasonCode diff --git a/src/kernel/intmsghandler.C b/src/kernel/intmsghandler.C index 4a9ae26e7..03b8996d3 100644 --- a/src/kernel/intmsghandler.C +++ b/src/kernel/intmsghandler.C @@ -139,6 +139,20 @@ void InterruptMsgHdlr::handleInterrupt() // by writing the xirr back with the value read. printk("XIRR @ %lx = %x\n",xirrAddress,xirr); + + //If this is an IPI -- clean it up + if((xirr & 0x00FFFFFF) == INTERPROC_XISR) + { + uint64_t mfrrAddress = + cv_ipc_base_address + mmio_offset(pir) + MFRR_ADDR_OFFSET; + + // Ignore HRMOR setting + mfrrAddress |= 0x8000000000000000ul; + uint8_t mfrr = 0xFF; + + asm volatile("stbcix %0,0,%1" :: "r" (mfrr) , "r" (mfrrAddress)); + asm volatile("stwcix %0,0,%1" :: "r" (xirr) , "r" (xirrAddress)); + } } } diff --git a/src/usr/dump/dumpCollect.C b/src/usr/dump/dumpCollect.C index 8f85f44a9..f0089311c 100644 --- a/src/usr/dump/dumpCollect.C +++ b/src/usr/dump/dumpCollect.C @@ -113,6 +113,9 @@ errlHndl_t doDumpCollect(void) int rc = 0; bool invalidSrcSize = false; bool invalidDestSize = false; + bool l_contiguous = false; + uint64_t l_prevSrcAddr = 0xFFFFFFFFFFFFFFFF; + uint32_t l_resultCount = 0x0; // local src table info uint64_t *vaSrcTableAddr = 0; @@ -190,14 +193,18 @@ errlHndl_t doDumpCollect(void) } vaMapSrcTableAddr = - (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curSrcTableAddr)), - THIRTYTWO_GB))); + (static_cast<uint64_t*>(mm_block_map( + reinterpret_cast<void*>(ALIGN_PAGE_DOWN + (curSrcTableAddr & RM_TOP_NIBBLE_MASK)), + THIRTYTWO_GB))); vaSrcTableAddr = vaMapSrcTableAddr; vaMapDestTableAddr = - (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curDestTableAddr)), - THIRTYTWO_GB))); + (static_cast<uint64_t*>(mm_block_map( + reinterpret_cast<void*>(ALIGN_PAGE_DOWN + (curDestTableAddr & RM_TOP_NIBBLE_MASK)), + THIRTYTWO_GB))); vaDestTableAddr = vaMapDestTableAddr; @@ -212,6 +219,7 @@ errlHndl_t doDumpCollect(void) // Current Destination physical and Va address TRACFCOMP(g_trac_dump, "HBDumpCopySrcToDest DestTableIndex = %d, DestTableAddr = %.16X, VA = %.16X", curDestIndex, curDestTableAddr, vaDestTableAddr); + resultsTableEntry->dataSize = 0x0; while(1) { @@ -219,7 +227,8 @@ errlHndl_t doDumpCollect(void) if (bytesLeftInSrc == 0) { // unmap the previous src entry - rc = mmio_dev_unmap(reinterpret_cast<void*>(vaMapSrcTableAddr)); + rc = mm_block_unmap( + reinterpret_cast<void*>(vaMapSrcTableAddr)); if (rc != 0) { @@ -275,8 +284,10 @@ errlHndl_t doDumpCollect(void) // map the MDST entry to a device such that we can read and write from that memory // address vaMapSrcTableAddr = - (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curSrcTableAddr)), - THIRTYTWO_GB))); + (static_cast<uint64_t*>(mm_block_map( + reinterpret_cast<void*>(ALIGN_PAGE_DOWN + (curSrcTableAddr & RM_TOP_NIBBLE_MASK)), + THIRTYTWO_GB))); vaSrcTableAddr = vaMapSrcTableAddr; @@ -291,8 +302,8 @@ errlHndl_t doDumpCollect(void) if (bytesLeftInDest == 0) { // unmap the previous dest entry - rc = mmio_dev_unmap(reinterpret_cast<void*>(vaMapDestTableAddr)); - + rc = mm_block_unmap( + reinterpret_cast<void*>(vaMapDestTableAddr)); if (rc != 0) { /*@ @@ -358,6 +369,20 @@ errlHndl_t doDumpCollect(void) curDestTableAddr = destTableEntry[curDestIndex].dataAddr; bytesLeftInDest = destTableEntry[curDestIndex].dataSize; + //check to see if this destination addr is contiguous + l_contiguous = false; + if(curDestIndex !=0) + { + if(((destTableEntry[curDestIndex-1].dataAddr + + destTableEntry[curDestIndex-1].dataSize) + == curDestTableAddr) + && (l_prevSrcAddr == curSrcTableAddr)) + { + l_contiguous = true; + + } + } + // If the current dest addr or the size to copy are zero. if ((curDestTableAddr == 0) || (bytesLeftInDest == 0)) { @@ -410,8 +435,10 @@ errlHndl_t doDumpCollect(void) // map the MDDT to a VA addresss vaMapDestTableAddr = - (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curDestTableAddr)), - THIRTYTWO_GB))); + (static_cast<uint64_t*>(mm_block_map( + reinterpret_cast<void*>(ALIGN_PAGE_DOWN + (curDestTableAddr & RM_TOP_NIBBLE_MASK)), + THIRTYTWO_GB))); vaDestTableAddr = vaMapDestTableAddr; @@ -434,11 +461,23 @@ errlHndl_t doDumpCollect(void) if (curResultIndex < maxResultEntries) { // Update the results table - resultsTableEntry->srcAddr = curSrcTableAddr; - resultsTableEntry->destAddr = curDestTableAddr; - resultsTableEntry->dataSize = sizeToCopy; - resultsTableEntry++; - curResultIndex++; + if(l_contiguous) + { + (resultsTableEntry-1)->dataSize +=sizeToCopy; + } + else + { + resultsTableEntry->srcAddr = curSrcTableAddr; + resultsTableEntry->destAddr = curDestTableAddr; + resultsTableEntry->dataSize = sizeToCopy; + resultsTableEntry++; + l_resultCount++; + curResultIndex++; + if (curResultIndex < maxResultEntries) + { + resultsTableEntry->dataSize = 0x0; + } + } } else { @@ -476,6 +515,7 @@ errlHndl_t doDumpCollect(void) curDestTableAddr += sizeToCopy; vaSrcTableAddr += addrOffset; vaDestTableAddr += addrOffset; + l_prevSrcAddr = curSrcTableAddr; //src address last used } // end of while loop @@ -525,6 +565,8 @@ errlHndl_t doDumpCollect(void) break; } + //Update actual count in RUNTIME + RUNTIME::update_MDRT_Count(l_resultCount); }while(0);// end of do-while loop // Got an errorlog back from get_host_data_sections diff --git a/src/usr/dump/dumpCollect.H b/src/usr/dump/dumpCollect.H index 09816848b..b7bf59c6f 100644 --- a/src/usr/dump/dumpCollect.H +++ b/src/usr/dump/dumpCollect.H @@ -32,6 +32,10 @@ namespace DUMP { + enum + { + RM_TOP_NIBBLE_MASK = 0x0FFFFFFFFFFFFFFFULL, + }; /** * @brief This routine retrieves first entry of the MDST, MDDT and diff --git a/src/usr/dump/test/dumptest.H b/src/usr/dump/test/dumptest.H index 022fecd64..fbd4523aa 100644 --- a/src/usr/dump/test/dumptest.H +++ b/src/usr/dump/test/dumptest.H @@ -122,14 +122,14 @@ class DumpTest: public CxxTest::TestSuite uint64_t src_data[8] = {DUMP_TEST_SRC_DATA_AREA, 64, // 450000 DUMP_TEST_SRC_DATA_AREA + 64, 64, - DUMP_TEST_SRC_DATA_AREA + 128, 64, - DUMP_TEST_SRC_DATA_AREA + 192, 64}; + DUMP_TEST_SRC_DATA_AREA + 192, 64, + DUMP_TEST_SRC_DATA_AREA + 256, 64}; uint64_t dst_data[8] = {DUMP_TEST_DST_DATA_AREA, 64, // 460000 DUMP_TEST_DST_DATA_AREA + 64, 64, - DUMP_TEST_DST_DATA_AREA + 128, 64, - DUMP_TEST_DST_DATA_AREA + 192, 64}; + DUMP_TEST_DST_DATA_AREA + 256, 64, + DUMP_TEST_DST_DATA_AREA + 512, 64}; // Put the src addresses defined above into the MDST @@ -166,18 +166,14 @@ class DumpTest: public CxxTest::TestSuite uint64_t result_data[] = { DUMP_TEST_SRC_DATA_AREA, DUMP_TEST_DST_DATA_AREA, - 64, 0, - - DUMP_TEST_SRC_DATA_AREA+64, - DUMP_TEST_DST_DATA_AREA+64, - 64, 0, + 64 *2, 0, - DUMP_TEST_SRC_DATA_AREA+128, - DUMP_TEST_DST_DATA_AREA+128, + DUMP_TEST_SRC_DATA_AREA+192, + DUMP_TEST_DST_DATA_AREA+256, 64, 0, - DUMP_TEST_SRC_DATA_AREA+192, - DUMP_TEST_DST_DATA_AREA+192, + DUMP_TEST_SRC_DATA_AREA+256, + DUMP_TEST_DST_DATA_AREA+512, 64, 0, }; @@ -268,7 +264,7 @@ class DumpTest: public CxxTest::TestSuite if (src_rc!=0) { TRACFCOMP(g_trac_dump, "DumpTest::DumpCollect:1 : Results Data mismatch rc = %d", src_rc); - TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected error data mismatch in results table" ); + TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected error DATA mismatch in results" ); } @@ -303,8 +299,10 @@ class DumpTest: public CxxTest::TestSuite if (result_rc!=0) { - TRACFCOMP(g_trac_dump, "DumpTest::DumpCollect:1 : Results Data mismatch rc = %d", result_rc); - TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected error data mismatch in results table" ); + TRACFCOMP(g_trac_dump, "DumpTest::DumpCollect:1 : Results Table mismatch rc = %d", result_rc); + TRACFBIN( g_trac_dump, "MDRT=", resultTablePtr, sizeof(result_data) ); + TRACFBIN( g_trac_dump, "expected=", result_data, sizeof(result_data) ); + TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected mismatch in results table" ); } } @@ -353,10 +351,10 @@ class DumpTest: public CxxTest::TestSuite DUMP_TEST_SRC_DATA_AREA+256 + 128,64, // 4500180 DUMP_TEST_SRC_DATA_AREA+256 + 192, 64}; // 45001C0 - uint64_t dst_data[8] = {DUMP_TEST_DST_DATA_AREA+1024, 64, // 4600400 - DUMP_TEST_DST_DATA_AREA+1024 + 64, 32, // 4600440 - DUMP_TEST_DST_DATA_AREA+1024 + 96, 32, // 4600480 - DUMP_TEST_DST_DATA_AREA+1024+ 128, 128}; // 46004C0 + uint64_t dst_data[8] = {DUMP_TEST_DST_DATA_AREA+1024, 64, //4600400 + DUMP_TEST_DST_DATA_AREA+1024 + 64, 32, //4600440 + DUMP_TEST_DST_DATA_AREA+1024 + 256, 32, //4600500 + DUMP_TEST_DST_DATA_AREA+1024 + 128, 128};//4600520 memcpy(srcTablePtr, src_data, sizeof(src_data)); memcpy(dstTablePtr, dst_data, sizeof(dst_data)); @@ -388,18 +386,15 @@ class DumpTest: public CxxTest::TestSuite // results output data expected uint64_t result_data[] = { DUMP_TEST_SRC_DATA_AREA+256, - DUMP_TEST_DST_DATA_AREA+1024, 64, 0, - - DUMP_TEST_SRC_DATA_AREA+256+64, - DUMP_TEST_DST_DATA_AREA+1024+64, 32, 0, + DUMP_TEST_DST_DATA_AREA+1024, 96, 0, DUMP_TEST_SRC_DATA_AREA+256+64+32, - DUMP_TEST_DST_DATA_AREA+1024+64+32, 32, 0, + DUMP_TEST_DST_DATA_AREA+1024+256, 32, 0, DUMP_TEST_SRC_DATA_AREA+256+128, DUMP_TEST_DST_DATA_AREA+1024+128, 64, 0, - DUMP_TEST_SRC_DATA_AREA+256+192, + DUMP_TEST_SRC_DATA_AREA+256+128+64, DUMP_TEST_DST_DATA_AREA+1024+128+64, 64, 0, }; @@ -509,7 +504,7 @@ class DumpTest: public CxxTest::TestSuite if (src_rc!=0) { TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenDest:1 : Results Data mismatch rc = %d for index = %d", src_rc, i); - TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error data mismatch in results table" ); + TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error data mismatch in results data" ); } @@ -618,8 +613,10 @@ class DumpTest: public CxxTest::TestSuite if (result_rc!=0) { - TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenDest : Results Data mismatch rc = %d", result_rc); - TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error data mismatch in results table" ); + TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenDest : Results Table mismatch rc = %d", result_rc); + TRACFBIN( g_trac_dump, "MDRT=", resultTablePtr, sizeof(result_data) ); + TRACFBIN( g_trac_dump, "expected=", result_data, sizeof(result_data) ); + TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error TABLE mismatch in results table" ); } } @@ -1128,8 +1125,10 @@ class DumpTest: public CxxTest::TestSuite if (result_rc!=0) { - TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenSRC:1 : Results Data mismatch rc = %d", result_rc); - TS_FAIL( "DumpTest::DumpCollectUnevenSrc ERROR : Unexpected error data mismatch in results table" ); + TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenSRC:1 : Results Table mismatch rc = %d", result_rc); + TRACFBIN( g_trac_dump, "MDRT=", resultTablePtr, sizeof(result_data) ); + TRACFBIN( g_trac_dump, "expected=", result_data, sizeof(result_data) ); + TS_FAIL( "DumpTest::DumpCollectUnevenSrc ERROR : Unexpected error TABLE mismatch in results table" ); } } diff --git a/src/usr/hwas/hostbootIstep.C b/src/usr/hwas/hostbootIstep.C index 20552389b..06a591547 100644 --- a/src/usr/hwas/hostbootIstep.C +++ b/src/usr/hwas/hostbootIstep.C @@ -40,6 +40,7 @@ #include <targeting/attrsync.H> #include <diag/prdf/prdfMain.H> +#include <intr/interrupt.H> namespace HWAS { @@ -115,6 +116,7 @@ void* host_discover_targets( void *io_pArgs ) // Sync attributes from Fsp errl = syncAllAttributesFromFsp(); + } else { diff --git a/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C b/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C index 9d17ceb34..09d3f6e53 100644 --- a/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C +++ b/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C @@ -853,7 +853,6 @@ void* call_host_mpipl_service( void *io_pArgs ) TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "SUCCESS : proc_mpipl_ex_cleanup" ); - // currently according to Adriana, the dump calls should only cause an // istep failure when the dump collect portion of this step fails.. We // will not fail the istep on any mbox message failures. instead we will @@ -861,8 +860,20 @@ void* call_host_mpipl_service( void *io_pArgs ) errlHndl_t l_errMsg = NULL; - // Need to load the dump module - l_err = VFS::module_load( "libdump.so" ); + // Dump relies upon the runtime module + // Not declaring in istep DEP list cause if we load it + // we want it to stay loaded + if ( !VFS::module_is_loaded( "libruntime.so" ) ) + { + l_err = VFS::module_load( "libruntime.so" ); + + if ( l_err ) + { + // load module returned with errl set + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Could not load runtime module" ); + } + } // If dump module successfull loaded then continue with DumpCollect and // messaging @@ -952,8 +963,7 @@ void* call_host_mpipl_service( void *io_pArgs ) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "ERROR : returned from VFS::module_load (libdump.so)" ); - } - + } } // If got an error in the procedure or collection of the dump kill the istep diff --git a/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C b/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C index d6593564f..17575d8ee 100644 --- a/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C +++ b/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C @@ -20,8 +20,8 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: proc_mpipl_ex_cleanup.C,v 1.4 2013/02/02 21:02:23 belldi Exp $ -// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_mpipl_ex_cleanup.C,v $ +// $Id: proc_mpipl_ex_cleanup.C,v 1.5 2013/07/18 13:38:04 stillgs Exp $ +// $Source: /afs/awd.austin.ibm.com/proj/p9/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_mpipl_ex_cleanup.C,v $ //------------------------------------------------------------------------------ // *| // *! (C) Copyright International Business Machines Corp. 2012 @@ -34,11 +34,11 @@ // *! OWNER NAME : Dion Bell Email: belldi@us.ibm.com // *! BACKUP NAME : Dion Bell Email: belldi@us.ibm.com // *! -// *! -// *! -// *! +// *! +// *! +// *! // *! Additional Note(s): -// *! +// *! // *! //------------------------------------------------------------------------------ @@ -46,6 +46,7 @@ // Includes //------------------------------------------------------------------------------ #include "proc_mpipl_ex_cleanup.H" +#include "p8_scom_addresses.H" extern "C" { @@ -53,301 +54,222 @@ extern "C" //------------------------------------------------------------------------------ // name: proc_mpipl_ex_cleanup //------------------------------------------------------------------------------ - // purpose: + // purpose: // Undo step that prepared fast-winkled cores for scanning and set up deep winkle mode // SCOM regs: - // 1) GP3 Register (NA in PERV CPLT) - // - // Murano (6 regs) - // 00000000140F0014 (PCB2) - // 00000000150F0014 (PCB2) - // 00000000160F0014 (PCB2) - // 000000001C0F0014 (PCB2) - // 000000001D0F0014 (PCB2) - // 000000001E0F0014 (PCB2) - // - // - // Venice (12 regs) - // 00000000110F0014 (PCB2) - // 00000000120F0014 (PCB2) - // 00000000130F0014 (PCB2) - // 00000000140F0014 (PCB2) - // 00000000150F0014 (PCB2) - // 00000000160F0014 (PCB2) - // 00000000190F0014 (PCB2) - // 000000001A0F0014 (PCB2) - // 000000001B0F0014 (PCB2) - // 000000001C0F0014 (PCB2) - // 000000001D0F0014 (PCB2) - // 000000001E0F0014 (PCB2) + // 1) GP3 Register (NA in PERV CPLT) // // bit 27 (TP_LVLTRANS_FENCE): Electrical winkel fence. Mainly used by power management. // // 2) PowerManagement GP0 reg // - // Murano (6 regs) - // 00000000140F0102(PCB2) - // 00000000150F0102(PCB2) - // 00000000160F0102(PCB2) - // 000000001C0F0102(PCB2) - // 000000001D0F0102(PCB2) - // 000000001E0F0102(PCB2) - // - // Venice (12 regs) - // 00000000110F0102(PCB2) - // 00000000120F0102(PCB2) - // 00000000130F0102(PCB2) - // 00000000140F0102(PCB2) - // 00000000150F0102(PCB2) - // 00000000160F0102(PCB2) - // 00000000190F0102(PCB2) - // 000000001A0F0102(PCB2) - // 000000001B0F0102(PCB2) - // 000000001C0F0102(PCB2) - // 000000001D0F0102(PCB2) - // 000000001E0F0102(PCB2) - // // bit 22 (TP_TC_PERVASIVE_ECO_FENCE): Pervasive ECO fence // // bit 39 (PM_SLV_WINKLE_FENCE): Fence off the powered off chiplet in winkle. - Logical fence/hold for pcb_slave and pcb_slave_pm. For electrical fence see bit 23. // - // 3) PowerManagement GP1 - // - // Murano (6 regs) - // 0x00000000140F0105 (PCB2) - // 0x00000000150F0105 (PCB2) - // 0x00000000160F0105 (PCB2) - // 0x000000001C0F0105 (PCB2) - // 0x000000001D0F0105 (PCB2) - // 0x000000001E0F0105 (PCB2) - // - // Venice (12 regs) - // 0x00000000110F0105 (PCB2) - // 0x00000000120F0105 (PCB2) - // 0x00000000130F0105 (PCB2) - // 0x00000000140F0105 (PCB2) - // 0x00000000150F0105 (PCB2) - // 0x00000000160F0105 (PCB2) - // 0x00000000190F0105 (PCB2) - // 0x000000001A0F0105 (PCB2) - // 0x000000001B0F0105 (PCB2) - // 0x000000001C0F0105 (PCB2) - // 0x000000001D0F0105 (PCB2) - // 0x000000001E0F0105 (PCB2) + // 3) PowerManagement GP1 // // Bit 5: WINKLE_POWER_OFF_SEL: Winkle Power Off Select: // Selects which voltage level to place the Core and ECO domain PFETs upon Winkle entry. 0 = Vret (Fast Winkle Mode), 1 = Voff (Deep Winkle Mode). Depending on the setting of pmicr_latency_en, this bit is controlled with a PCB-write (0) or by the PMICR in the core (1). // // Bit 15: PMICR_LATENCY_EN: Selects how the sleep/winkle latency (which is deep/fast) is controlled. If asserted the PMICR controls the winkle/sleep_power_off_sel in PMGP1, otherwise those bits are controlled via SCOM by OCC. - // parameters: + // parameters: // 'i_target' is chip target // - // returns: + // returns: // FAPI_RC_SUCCESS (success, EX chiplets entered fast winkle) - // + // // getscom/putscom/getattribute fapi errors // fapi error assigned from eCMD function failure // //------------------------------------------------------------------------------ fapi::ReturnCode proc_mpipl_ex_cleanup(const fapi::Target & i_target) { - const char *procedureName = "proc_mpipl_ex_cleanup"; - fapi::ReturnCode rc; //fapi return code - uint32_t rc_ecmd; //ecmd return code value - const uint32_t data_size = 64; //Size of data buffer - ecmdDataBufferBase fsi_data(data_size); //64-bit data buffer - uint8_t attr_chip_unit_pos; //EX chiplet's unit offset within chip with respect to similar EX units - const uint64_t EX_OFFSET_MULT = 0x01000000; //Multiplier used to calculate offset for respective EX chiplet - uint64_t EX_GP3_REG_0x1X0F0014; //Addr of GP3 reg PCB2 for respective EX chiplet - const uint64_t EX_GP3_REG_PCB2_ADDR = 0x00000000100F0014; //Addr of GP3 reg PCB2 (minus offset for EX chiplet) - const uint32_t EX_GP3_REG_PCB2_BIT_POS27 = 27; //Bit 27 of GP3 reg PCB2 - uint64_t EX_PMGP0_REG_0x1X0F0102; //Addr of PM GP0 reg PCB2 for respective EX chiplet - const uint64_t EX_PMGP0_REG_PCB2_ADDR = 0x00000000100F0102; //Addr of PM GP0 reg PCB2 (minus offset for EX chiplet) - const uint32_t EX_PMGP0_REG_PCB2_BIT_POS22 = 22; //Bit 22 of PM GP0 reg PCB2 - const uint32_t EX_PMGP0_REG_PCB2_BIT_POS39 = 39; //Bit 39 of PM GP0 reg PCB2 - uint64_t EX_PMGP1_REG_0x1X0F0103; //Variable address, PM GP1 reg PCB for respective EX chiplet - const uint64_t EX_PMGP1_REG_PCB_ADDR = 0x00000000100F0103; //PM GP1 reg PCB addr (minus offset for EX chiplet) - uint64_t EX_PMGP1_REG_0x1X0F0104; //Variable address, PM GP1 reg PCB1 for respective EX chiplet - const uint64_t EX_PMGP1_REG_PCB1_ADDR = 0x00000000100F0104; //PM GP1 reg PCB1 addr (minus offset for EX chiplet) - uint64_t EX_PMGP1_REG_0x1X0F0105; //Variable address, PM GP1 reg PCB2 for respective EX chiplet - const uint64_t EX_PMGP1_REG_PCB2_ADDR = 0x00000000100F0105; //PM GP1 reg PCB2 addr (minus offset for EX chiplet) - const uint32_t EX_PMGP1_REG_PCB2_BIT_POS5 = 5; //Bit 5 (WINKLE_POWER_OFF_SEL) of PM GP1 reg PCB2 - const uint32_t EX_PMGP1_REG_PCB2_BIT_POS15 = 15; //Bit 15 (PMICR_LATENCY_EN) of PM GP1 reg PCB2 + const char *procedureName = "proc_mpipl_ex_cleanup"; + fapi::ReturnCode rc; //fapi return code + uint32_t rc_ecmd = 0; //ecmd return code value + ecmdDataBufferBase fsi_data(64); //64-bit data buffer + uint8_t attr_chip_unit_pos; //EX chiplet's unit offset within chip with respect to similar EX units + const uint64_t EX_OFFSET_MULT = 0x01000000; //Multiplier used to calculate offset for respective EX chiplet - fapi::TargetType l_chiplet_type = fapi::TARGET_TYPE_EX_CHIPLET; //Type of chiplet is EX chiplet - fapi::TargetState l_chiplet_state = fapi::TARGET_STATE_FUNCTIONAL; //State of chiplet is functional - std::vector<fapi::Target> v_ex_chiplets; //Vector of EX chiplets - std::vector<fapi::Target>::iterator entry_pos; //Position of entry - std::vector<fapi::Target>::iterator end_pos; //End of vector - - rc = fapiGetChildChiplets(i_target, l_chiplet_type, v_ex_chiplets, l_chiplet_state); //Get vector of EX chiplets - entry_pos = v_ex_chiplets.begin(); //first element of vector - end_pos = v_ex_chiplets.end(); //end of vector - - //Parse thru EX chiplets and prepare fast-winkled cores for scanning - while(entry_pos != end_pos ) { - // Get EX chiplet number - rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*entry_pos), attr_chip_unit_pos); - if (rc) { - FAPI_ERR("%s: fapiGetAttribute error (ATTR_CHIP_UNIT_POS)", procedureName); - return rc; - } - FAPI_DBG("EX chiplet pos = 0x%02X", attr_chip_unit_pos); - - EX_GP3_REG_0x1X0F0014 = EX_GP3_REG_PCB2_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of GP3 reg (PCB2) for respective EX chiplet - FAPI_DBG("GP3 reg (PCB2), addr=0x%08llX", EX_GP3_REG_0x1X0F0014); - - EX_PMGP0_REG_0x1X0F0102 = EX_PMGP0_REG_PCB2_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP0 reg (PCB2) for respective EX chiplet - FAPI_DBG("PM GP0 reg (PCB2), addr=0x%08llX", EX_PMGP0_REG_0x1X0F0102 ); - - EX_PMGP1_REG_0x1X0F0103 = EX_PMGP1_REG_PCB_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP1 reg (PCB) for respective EX chiplet - FAPI_DBG("PM GP1 reg (PCB), addr=0x%08llX", EX_PMGP1_REG_0x1X0F0103); - - EX_PMGP1_REG_0x1X0F0104 = EX_PMGP1_REG_PCB1_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP1 reg (PCB1) for respective EX chiplet - FAPI_DBG("PM GP1 reg (PCB1), addr=0x%08llX", EX_PMGP1_REG_0x1X0F0104); - - EX_PMGP1_REG_0x1X0F0105 = EX_PMGP1_REG_PCB2_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP1 reg (PCB2) for respective EX chiplet - FAPI_DBG("PM GP1 reg (PCB2), addr=0x%08llX", EX_PMGP1_REG_0x1X0F0105); - + uint64_t address; // Varible for computed addresses + uint64_t offset; + char reg_name[32]; // Character array for register names - //Undo step that prepared fast-winkled cores for scanning - // - //1) Drop PB Electrical Fence (EX_GP3_OR_0x100F0014(27)=1) - rc_ecmd = fsi_data.flushTo0(); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd); - rc.setEcmdError(rc_ecmd); - return rc; - } - FAPI_DBG("Asserting bit 27 of ecmdDataBufferBase that stores value of GP3 reg (addr: 0x%08llX)", EX_GP3_REG_0x1X0F0014); - rc_ecmd = fsi_data.setBit(EX_GP3_REG_PCB2_BIT_POS27); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not assert bit 27 of ecmdDataBufferBase that stores value of GP3 reg (addr: 0x%08llX)", procedureName, rc_ecmd, EX_GP3_REG_0x1X0F0014); - rc.setEcmdError(rc_ecmd); - return rc; - } - - FAPI_DBG("ecmdDataBufferBase storing value of GP3 reg (addr: 0x%08llX), val=0x%016llX", EX_GP3_REG_0x1X0F0014, fsi_data.getDoubleWord((uint32_t) 0)); - rc = fapiPutScom( i_target, EX_GP3_REG_0x1X0F0014, fsi_data ); - if (rc) { - FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_GP3_REG_0x1X0F0014); - return rc; - } - - //2) Drop logical Pervasive/PCBS-PM fence (EX_PMGP0_OR_0x100F0102(39)=1) - rc_ecmd = fsi_data.flushTo0(); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd); - rc.setEcmdError(rc_ecmd); - return rc; - } + // Relevant PMGP0 bits +// const uint32_t PM_DISABLE = 0; + const uint32_t BLOCK_REG_WKUP_SOURCE = 53; - FAPI_DBG("Asserting bit 39 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", EX_PMGP0_REG_0x1X0F0102 ); - rc_ecmd = fsi_data.setBit(EX_PMGP0_REG_PCB2_BIT_POS39); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not assert bit 39 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", procedureName, rc_ecmd, EX_PMGP0_REG_0x1X0F0102); - rc.setEcmdError(rc_ecmd); - return rc; - } - - FAPI_DBG("ecmdDataBufferBase storing value of PM GP0 reg (addr: 0x%08llX), val=0x%016llX", EX_PMGP0_REG_0x1X0F0102, fsi_data.getDoubleWord((uint32_t) 0)); - rc = fapiPutScom( i_target, EX_PMGP0_REG_0x1X0F0102, fsi_data ); - if (rc) { - FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP0_REG_0x1X0F0102); - return rc; - } - - //3) Drop Pervasive Extended Cache Option (ECO) fence (EX_PMGP0_OR_0x100F0102(22)=1) - rc_ecmd = fsi_data.flushTo0(); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd); - rc.setEcmdError(rc_ecmd); - return rc; - } - - FAPI_DBG("Asserting bit 22 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", EX_PMGP0_REG_0x1X0F0102 ); - rc_ecmd = fsi_data.setBit(EX_PMGP0_REG_PCB2_BIT_POS22); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not assert bit 22 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", procedureName, rc_ecmd, EX_PMGP0_REG_0x1X0F0102); - rc.setEcmdError(rc_ecmd); - return rc; - } - - FAPI_DBG("ecmdDataBufferBase storing value of PM GP0 reg (addr: 0x%08llX), val=0x%016llX", EX_PMGP0_REG_0x1X0F0102, fsi_data.getDoubleWord((uint32_t) 0)); - rc = fapiPutScom( i_target, EX_PMGP0_REG_0x1X0F0102, fsi_data ); - if (rc) { - FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP0_REG_0x1X0F0102); - return rc; - } - + // Relevant PMGP1 bits + const uint32_t WINKLE_POWER_OFF_SEL = 5; - // Check bit 15 (PMICR_LATENCY_EN) of PM GP1 reg is 0, so bit 5 (WINKLE_POWER_OFF_SEL) of PM GP1 reg is controlled via SCOM write - // - FAPI_DBG("Checking bit 15 (PMICR_LATENCY_EN) of PM GP1 reg (addr: 0x%08llX) is 0", EX_PMGP1_REG_0x1X0F0103); - rc = fapiGetScom(i_target, EX_PMGP1_REG_0x1X0F0103, fsi_data); - if (rc) { - FAPI_ERR("%s: fapiGetScom error (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_0x1X0F0103); - return rc; - } - FAPI_DBG("PM GP1 reg (addr: 0x%08llX), val=0x%016llX", EX_PMGP1_REG_0x1X0F0103, fsi_data.getDoubleWord((uint32_t) 0)); - - //Check whether bit 15 (PMICR_LATENCY_EN) of PowerManagement GP1 reg is 1 - if( fsi_data.getBit(EX_PMGP1_REG_PCB2_BIT_POS15) ) { - FAPI_DBG("Bit pos %u (PMICR_LATENCY_EN) of PM GP1 reg (addr: 0x%08llX) is 1", EX_PMGP1_REG_PCB2_BIT_POS15, EX_PMGP1_REG_0x1X0F0103); - FAPI_DBG("Clearing bit pos %u (PMICR_LATENCY_EN) of PM GP1 reg (addr: 0x%08llX)", EX_PMGP1_REG_PCB2_BIT_POS15, EX_PMGP1_REG_0x1X0F0103); - - //Clear bit 15 (PMICR_LATENCY_EN) of PM GP1 reg - rc_ecmd = fsi_data.flushTo1(); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 1's", procedureName, rc_ecmd); - rc.setEcmdError(rc_ecmd); - return rc; - } - rc_ecmd = fsi_data.clearBit(EX_PMGP1_REG_PCB2_BIT_POS15); - if(rc_ecmd) { - FAPI_ERR("%s: Could not clear bit pos %u of PM GP1 reg (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_PCB2_BIT_POS15, EX_PMGP1_REG_0x1X0F0104); - rc.setEcmdError(rc_ecmd); - return rc; + std::vector<fapi::Target> v_ex_chiplets; //Vector of EX chiplets + + + do + { + //Entering fapi function + FAPI_INF("Entering %s", procedureName); + + //Get vector of EX chiplets + rc = fapiGetChildChiplets( i_target, + fapi::TARGET_TYPE_EX_CHIPLET, + v_ex_chiplets, + fapi::TARGET_STATE_FUNCTIONAL); + if (rc) + { + FAPI_ERR("%s: fapiGetChildChiplets error", procedureName); + break; } - //Write data to PM GP1 reg - rc = fapiPutScom(i_target, EX_PMGP1_REG_0x1X0F0104, fsi_data); - if (rc) { - FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_0x1X0F0104); - return rc; + FAPI_INF("Processing target %s", i_target.toEcmdString()); + + //Parse thru EX chiplets and prepare fast-winkled cores for deep operations + //Loop thru EX chiplets in vector + for (uint32_t counter = 0; counter < v_ex_chiplets.size(); counter++) + { + + // Get EX chiplet number + rc = FAPI_ATTR_GET( ATTR_CHIP_UNIT_POS, + &(v_ex_chiplets[counter]), + attr_chip_unit_pos); + if (rc) + { + FAPI_ERR("%s: fapiGetAttribute error (ATTR_CHIP_UNIT_POS)", procedureName); + break; + } + FAPI_INF("EX chiplet pos = 0x%02X", attr_chip_unit_pos); + + + // Calculate the address offset based on chiplet number + offset = EX_OFFSET_MULT * attr_chip_unit_pos; + + // ----------------------------------------------------------------- + FAPI_DBG("\tOriginal register contents"); + address = EX_GP3_0x100F0012 + offset; + strcpy(reg_name, "GP3"); + rc = fapiGetScom( i_target, address, fsi_data ); + if (rc) + { + FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); + break; + } + FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); + + address = EX_PMGP0_0x100F0100 + offset; + strcpy(reg_name, "PMGP0"); + rc = fapiGetScom( i_target, address, fsi_data ); + if (rc) + { + FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); + break; + } + FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); + + address = EX_PMGP1_0x100F0103 + offset; + strcpy(reg_name, "PMGP1"); + rc = fapiGetScom( i_target, address, fsi_data ); + if (rc) + { + FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); + break; + } + FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); + // ----------------------------------------------------------------- + + // Clean up configuration remnants of the fast-winkle configuration + // that was used to flush the chiplets after checkstop. EX chiplets + // will have been through SBE EX Init with certain step skippled due + // to MPIPL. + + FAPI_INF("Re-establish Deep Winkle mode default"); + address = EX_PMGP1_OR_0x100F0105 + offset; + strcpy(reg_name, "PMGP1 OR"); + + rc_ecmd |= fsi_data.flushTo0(); + rc_ecmd |= fsi_data.setBit(WINKLE_POWER_OFF_SEL); + if(rc_ecmd) + { + FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX) with rc %x", reg_name, address, rc_ecmd); + rc.setEcmdError(rc_ecmd); + break; + } + rc = fapiPutScom(i_target, address, fsi_data); + if (rc) + { + FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address); + break; + } + + FAPI_INF("Clear block wakeup sources to PM logic. PM is NOT re-enabled"); + // (eg clear Block Interrrupt Sources) + address = EX_PMGP0_AND_0x100F0101 + offset; + strcpy(reg_name, "PMGP0 AND"); + + rc_ecmd |= fsi_data.flushTo1(); +// rc_ecmd |= fsi_data.clearBit(PM_DISABLE); + rc_ecmd |= fsi_data.clearBit(BLOCK_REG_WKUP_SOURCE); + if(rc_ecmd) + { + FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX)", reg_name, address); + rc.setEcmdError(rc_ecmd); + break; + } + rc = fapiPutScom(i_target, address, fsi_data); + if (rc) + { + FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address); + break; + } + + // ----------------------------------------------------------------- + FAPI_DBG("\tUpdated register contents"); + address = EX_GP3_0x100F0012 + offset; + strcpy(reg_name, "GP3"); + rc = fapiGetScom( i_target, address, fsi_data ); + if (rc) + { + FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); + break; + } + FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); + + address = EX_PMGP0_0x100F0100 + offset; + strcpy(reg_name, "PMGP0"); + rc = fapiGetScom( i_target, address, fsi_data ); + if (rc) + { + FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); + break; + } + FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); + + address = EX_PMGP1_0x100F0103 + offset; + strcpy(reg_name, "PMGP1"); + rc = fapiGetScom( i_target, address, fsi_data ); + if (rc) + { + FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); + break; + } + FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); + // ----------------------------------------------------------------- + } // chiplet loop + + // Error exit from above loop + // Not really needed as outer while(0) is next but here for consistent structure + if (!rc.ok()) + { + break; } - } - - // Assert bit 5 (WINKLE_POWER_OFF_SEL) of PM GP1 reg - rc_ecmd = fsi_data.flushTo0(); - if(rc_ecmd) { - FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd); - rc.setEcmdError(rc_ecmd); - return rc; - } - rc_ecmd = fsi_data.setBit(EX_PMGP1_REG_PCB2_BIT_POS5); - if(rc_ecmd) { - FAPI_ERR("%s: Could not assert bit pos %u of PM GP1 reg (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_PCB2_BIT_POS5, EX_PMGP1_REG_0x1X0F0105); - rc.setEcmdError(rc_ecmd); - return rc; - } - rc = fapiPutScom(i_target, EX_PMGP1_REG_0x1X0F0105, fsi_data); - if (rc) { - FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_0x1X0F0105); - return rc; - } - - entry_pos++; //Point to next EX chiplet - } + } while (0); //Exiting fapi function - FAPI_DBG("Exiting fapi function: %s", procedureName); - + FAPI_INF("Exiting %s", procedureName); + return rc; } - - - + } // extern "C" diff --git a/src/usr/hwpf/hwp/start_payload/start_payload.C b/src/usr/hwpf/hwp/start_payload/start_payload.C index 36c076026..f7b132295 100644 --- a/src/usr/hwpf/hwp/start_payload/start_payload.C +++ b/src/usr/hwpf/hwp/start_payload/start_payload.C @@ -300,6 +300,15 @@ void* call_host_runtime_setup( void *io_pArgs ) } else { + //Update the MDRT value + l_err = RUNTIME::write_MDRT_Count(); + if(l_err != NULL) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "write_MDRT_Count failed" ); + break; + } + // Write the HostServices attributes into mainstore l_err = RUNTIME::populate_attributes(); if ( l_err ) diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H index 358701fb4..0a5b2dc19 100644 --- a/src/usr/initservice/extinitsvc/extinitsvctasks.H +++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H @@ -65,6 +65,19 @@ const TaskInfo g_exttaskinfolist[] = { }, /** + * @brief FSI Device Driver + */ + + { + "libfsi.so" , // taskname + NULL, // no pointer to fn + { + INIT_TASK, // task type + EXT_IMAGE, // Extended Module + } + }, + + /** * @brief External interrupt resource provider */ { @@ -103,18 +116,6 @@ const TaskInfo g_exttaskinfolist[] = { }, - /** - * @brief FSI Device Driver - */ - - { - "libfsi.so" , // taskname - NULL, // no pointer to fn - { - INIT_TASK, // task type - EXT_IMAGE, // Extended Module - } - }, /** * @brief FSI SCOM Device Driver diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C index 11339dbc6..a07fb980c 100644 --- a/src/usr/intr/intrrp.C +++ b/src/usr/intr/intrrp.C @@ -45,6 +45,7 @@ #include <sys/time.h> #include <sys/vfs.h> #include <hwas/common/hwasCallout.H> +#include <fsi/fsiif.H> #define INTR_TRACE_NAME INTR_COMP_NAME @@ -73,7 +74,7 @@ const uint32_t IntrRp::cv_PE_BAR_SCOM_LIST[] = }; trace_desc_t * g_trac_intr = NULL; -TRAC_INIT(&g_trac_intr, INTR_TRACE_NAME, KILOBYTE, TRACE::BUFFER_SLOW); +TRAC_INIT(&g_trac_intr, INTR_TRACE_NAME, 16*KILOBYTE, TRACE::BUFFER_SLOW); /** * setup _start and handle barrier @@ -609,6 +610,133 @@ errlHndl_t IntrRp::setBAR(TARGETING::Target * i_target, return err; } +errlHndl_t IntrRp::getPsiIRSN(TARGETING::Target * i_target, uint32_t& o_irsn) +{ + errlHndl_t err = NULL; + + // Setup PHBISR + // EN.TPC.PSIHB.PSIHB_ISRN_REG set to 0x00030003FFFF0000 + PSIHB_ISRN_REG_t reg; + size_t scom_len = sizeof(uint64_t); + + do{ + err = deviceRead + ( i_target, + ®, + scom_len, + DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG)); + + if(err) + { + break; + } + + o_irsn = reg.irsn & reg.mask; + }while(0); + + + TRACFCOMP(g_trac_intr,"PSIHB_ISRN: 0x%x",o_irsn); + + return err; +} + +errlHndl_t IntrRp::getNxIRSN(TARGETING::Target * i_target, uint32_t& o_irsn) +{ + errlHndl_t err = NULL; + + size_t scom_len = sizeof(uint64_t); + uint64_t reg = 0x0; + + do{ + err = deviceRead + ( i_target, + ®, + scom_len, + DEVICE_SCOM_ADDRESS(NX_BUID_SCOM_ADDR)); + + if(err) + { + break; + } + + o_irsn = ((static_cast<uint32_t>(reg >> NX_IRSN_COMP_SHIFT) + & NX_IRSN_COMP_MASK) & + ((static_cast<uint32_t>(reg >> NX_IRSN_MASK_SHIFT) + & NX_IRSN_MASK_MASK) || NX_IRSN_UPPER_MASK)); + }while(0); + + + TRACFCOMP(g_trac_intr,"NX_ISRN: 0x%x",o_irsn); + + return err; +} + + +errlHndl_t IntrRp::getPcieIRSNs(TARGETING::Target * i_target, + std::vector<uint32_t> &o_irsn) +{ + errlHndl_t err = NULL; + o_irsn.clear(); + + uint64_t reg = 0; + uint64_t mask = 0; + + size_t scom_len = sizeof(uint64_t); + + do{ + // PE + for(size_t i = 0; + i < sizeof(cv_PE_IRSN_COMP_SCOM_LIST) + /sizeof(cv_PE_IRSN_COMP_SCOM_LIST[0]); + ++i) + { + scom_len = sizeof(uint64_t); + err = deviceRead + ( + i_target, + ®, + scom_len, + DEVICE_SCOM_ADDRESS(cv_PE_IRSN_COMP_SCOM_LIST[i]) + ); + if(err) + { + break; + } + + + scom_len = sizeof(uint64_t); + err = deviceRead + ( + i_target, + &mask, + scom_len, + DEVICE_SCOM_ADDRESS(cv_PE_IRSN_MASK_SCOM_LIST[i]) + ); + if(err) + { + break; + } + + uint64_t l_irsn64 = reg & mask; + reg >>= PE_IRSN_SHIFT; + mask >>=PE_IRSN_SHIFT; + l_irsn64 >>=PE_IRSN_SHIFT; + uint32_t l_irsn = l_irsn64; + TRACFCOMP(g_trac_intr,"PE_ISRN[0x%08x] PE%d ", l_irsn, i); + if(l_irsn != 0x0) + { + o_irsn.push_back(l_irsn); + } + } + if(err) + { + break; + } + }while(0); + + return err; +} + errlHndl_t IntrRp::initIRSCReg(TARGETING::Target * i_target) { @@ -688,6 +816,11 @@ errlHndl_t IntrRp::initXIVR(enum ISNvalue_t i_isn, bool i_enable) switch(i_isn) { + case ISN_PSI: + xivr.priority = PsiHbXivr::PSI_PRIO; + scom_addr = PsiHbXivr::PSI_XIVR_ADRR; + break; + case ISN_OCC: xivr.priority = PsiHbXivr::OCC_PRIO; scom_addr = PsiHbXivr::OCC_XIVR_ADRR; @@ -792,6 +925,7 @@ errlHndl_t IntrRp::maskXIVR(TARGETING::Target *i_target) static const XIVR_INFO xivr_info[] = { + {ISN_PSI, PsiHbXivr::PSI_XIVR_ADRR}, {ISN_OCC, PsiHbXivr::OCC_XIVR_ADRR}, {ISN_FSI, PsiHbXivr::FSI_XIVR_ADRR}, {ISN_LPC, PsiHbXivr::LPC_XIVR_ADRR}, @@ -1186,12 +1320,12 @@ errlHndl_t IntrRp::hw_disableRouting(TARGETING::Target * i_proc, PSIHB_ISRN_REG_t reg; err = deviceRead - ( - i_proc, - ®, - scom_len, - DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG) - ); + ( + i_proc, + ®, + scom_len, + DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG) + ); if(err) { @@ -1200,23 +1334,23 @@ errlHndl_t IntrRp::hw_disableRouting(TARGETING::Target * i_proc, switch(i_rx_tx) { - case INTR_UPSTREAM: - reg.uie = 0; //upstream interrupt enable = 0 (disable) - break; + case INTR_UPSTREAM: + reg.uie = 0; //upstream interrupt enable = 0 (disable) + break; - case INTR_DOWNSTREAM: - reg.die = 0; //downstream interrupt enable = 0 (disable) - break; + case INTR_DOWNSTREAM: + reg.die = 0; //downstream interrupt enable = 0 (disable) + break; } scom_len = sizeof(uint64_t); err = deviceWrite - ( - i_proc, - ®, - scom_len, - DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG) - ); + ( + i_proc, + ®, + scom_len, + DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG) + ); if(err) { @@ -1245,13 +1379,13 @@ errlHndl_t IntrRp::hw_disableRouting(TARGETING::Target * i_proc, switch(i_rx_tx) { case INTR_UPSTREAM: - // reset bit PE_IRSN_RX - reg &= ~((1ull << (63-PE_IRSN_RX))); + // reset bit PE_IRSN_UPSTREAM + reg &= ~((1ull << (63-PE_IRSN_UPSTREAM))); break; case INTR_DOWNSTREAM: - // reset bit PE_IRSN_TX - reg &= ~((1ull << (63-PE_IRSN_TX))); + // reset bit PE_IRSN_DOWNSTREAM + reg &= ~((1ull << (63-PE_IRSN_DOWNSTREAM))); break; } @@ -1328,12 +1462,12 @@ errlHndl_t IntrRp::hw_resetIRSNregs(TARGETING::Target * i_proc) // all other fields = 0 err = deviceWrite - ( - i_proc, - ®1, - scom_len, - DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG) - ); + ( + i_proc, + ®1, + scom_len, + DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG) + ); if(err) { break; @@ -1397,158 +1531,476 @@ errlHndl_t IntrRp::hw_resetIRSNregs(TARGETING::Target * i_proc) return err; } +//---------------------------------------------------------------------------- + +errlHndl_t IntrRp::blindIssueEOIs(TARGETING::Target * i_proc) +{ + errlHndl_t err = NULL; + + TARGETING::TargetHandleList procCores; + getChildChiplets(procCores, i_proc, TYPE_CORE, false); //state can change + + do + { + //Issue eio to IPIs first + for(TARGETING::TargetHandleList::iterator + core = procCores.begin(); + core != procCores.end(); + ++core) + { + FABRIC_CHIP_ID_ATTR chip = i_proc->getAttr<ATTR_FABRIC_CHIP_ID>(); + FABRIC_NODE_ID_ATTR node = i_proc->getAttr<ATTR_FABRIC_NODE_ID>(); + CHIP_UNIT_ATTR coreId = + (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + + PIR_t pir(0); + pir.nodeId = node; + pir.chipId = chip; + pir.coreId = coreId; + + size_t threads = cpu_thread_count(); + for(size_t thread = 0; thread < threads; ++thread) + { + pir.threadId = thread; + uint64_t xirrAddr = iv_baseAddr + + cpuOffsetAddr(pir); + uint32_t * xirrPtr = + reinterpret_cast<uint32_t*>(xirrAddr + XIRR_OFFSET); + uint8_t * mfrrPtr = reinterpret_cast<uint8_t*>( + xirrAddr + MFRR_OFFSET); + + //need to set mfrr to 0xFF first + TRACDCOMP(g_trac_intr,"Clearing IPI to xirrPtr[%p]", xirrPtr); + *mfrrPtr = 0xFF; + *xirrPtr = 0xFF000002; + } + } + + PIR_t pir(iv_masterCpu); + pir.threadId = 0; + //Can just write all EOIs to master core thread 0 XIRR + uint64_t xirrAddr = iv_baseAddr + cpuOffsetAddr(pir); + volatile uint32_t * xirrPtr = + reinterpret_cast<uint32_t*>(xirrAddr +XIRR_OFFSET); + + + //Issue eio to PSI logic + uint32_t l_psiBaseIsn; + err = getPsiIRSN(i_proc, l_psiBaseIsn); + if(err) + { + break; + } + + //Only issue if ISN is non zero (ie set) + if(l_psiBaseIsn) + { + l_psiBaseIsn |= 0xFF000000; + uint32_t l_psiMaxIsn = l_psiBaseIsn + ISN_HOST; + + TRACFCOMP(g_trac_intr,"Issuing EOI to PSIHB range %x - %x", + l_psiBaseIsn, l_psiMaxIsn); + + for(uint32_t l_isn = l_psiBaseIsn; l_isn < l_psiMaxIsn; ++l_isn) + { + TRACDCOMP(g_trac_intr," xirrPtr[%p] xirr[%x]\n", xirrPtr, l_isn); + *xirrPtr = l_isn; + } + } + + + //Issue EIOs to PE (PCIE) ISN + std::vector<uint32_t> l_peIsn; + err = getPcieIRSNs(i_proc, l_peIsn); + if(err) + { + break; + } + + for(std::vector<uint32_t>::iterator peIsn = l_peIsn.begin(); + peIsn != l_peIsn.end(); + ++peIsn) + { + //now need to issue on all SN up to 2048 + uint32_t l_peBaseIsn = (*peIsn) | 0xFF000000; + uint32_t l_peMaxIsn = l_peBaseIsn + MAX_PE_IRSN_SN; + TRACFCOMP(g_trac_intr,"Issuing EOI to PCIE range %x - %x", + l_peBaseIsn, l_peMaxIsn); + + for(uint32_t l_isn = l_peBaseIsn; l_isn < l_peMaxIsn; ++l_isn) + { + *xirrPtr = l_isn; + } + } + + //Issue eio to NX logic + uint32_t l_nxBaseIsn; + err = getNxIRSN(i_proc, l_nxBaseIsn); + if(err) + { + break; + } + + //Only issue if ISN is non zero (ie set) + if(l_nxBaseIsn) + { + l_nxBaseIsn |= 0xFF000000; + uint32_t l_nxMaxIsn = l_nxBaseIsn + MAX_NX_IRSN_SN; + TRACFCOMP(g_trac_intr,"Issuing EOI to NX range % - %x", + l_nxBaseIsn, l_nxMaxIsn); + + for(uint32_t l_isn = l_nxBaseIsn; l_isn < l_nxMaxIsn; ++l_isn) + { + *xirrPtr = l_isn; + } + } + } while(0); + return err; +} + //---------------------------------------------------------------------------- -errlHndl_t IntrRp::hw_disableIntrMpIpl() +errlHndl_t IntrRp::findProcs_Cores(TARGETING::TargetHandleList & o_procs, + TARGETING::TargetHandleList& o_cores) { errlHndl_t err = NULL; + do { + //Build a list of "functional" processors. This needs to be + //done without targetting support (just blueprint) since + //on MPIPL the targeting information is obtained in + //discover_targets -- much later in the IPL. + + //Since this is MPIPL we will rely on two things: + // 1) FSI will be active to present chips + // 2) The MPIPL HW bit in CFAM 2839 will be set + + //force FSI to init so we can rely on slave data + err = FSI::initializeHardware(); + if(err) + { + break; + } + TARGETING::TargetHandleList procChips; - getAllChips(procChips, TYPE_PROC); + TARGETING::PredicateCTM predProc( TARGETING::CLASS_CHIP, + TARGETING::TYPE_PROC ); - TARGETING::TargetHandleList procCores; - getAllChiplets(procCores, TYPE_CORE); + TARGETING::TargetService& tS = TARGETING::targetService(); + TARGETING::Target * sysTarget = NULL; + tS.getTopLevelTarget( sysTarget ); + assert( sysTarget != NULL ); + + TARGETING::Target* masterProcTarget = NULL; + TARGETING::targetService().masterProcChipTargetHandle( + masterProcTarget ); + + tS.getAssociated( procChips, + sysTarget, + TARGETING::TargetService::CHILD, + TARGETING::TargetService::ALL, + &predProc ); - // Disable upstream intr routing on all processor chips for(TARGETING::TargetHandleList::iterator proc = procChips.begin(); proc != procChips.end(); ++proc) { - // disable upstream intr routing - err = hw_disableRouting(*proc,INTR_UPSTREAM); - if(err) + //if master proc -- just add it as we are running on it + if (*proc == masterProcTarget) { - break; + o_procs.push_back(*proc); + continue; + } + + //First see if present + if(FSI::isSlavePresent(*proc)) + { + TRACFCOMP(g_trac_intr,"Proc %x detected via FSI", TARGETING::get_huid(*proc)); + + //Second check to see if MPIPL bit is on cfam "2839" which + //Note 2839 is ecmd addressing, real address is 0x28E4 (byte) + uint64_t l_addr = 0x28E4; + uint32_t l_data = 0; + size_t l_size = sizeof(uint32_t); + err = deviceRead(*proc, + &l_data, + l_size, + DEVICE_FSI_ADDRESS(l_addr)); + if (err) + { + TRACFCOMP(g_trac_intr,"Failed to read CFAM 2838 on %x", + TARGETING::get_huid(*proc)); + break; + } + + TRACFCOMP(g_trac_intr,"Proc %x 2839 val [%x]", TARGETING::get_huid(*proc), + l_data); + + if(l_data & 0x80000000) + { + //Chip is present and functional -- add it to our list + o_procs.push_back(*proc); + + //Also need to force it to use Xscom + //Note that it has to support (ie it is part of the SMP) + ScomSwitches l_switches = + (*proc)->getAttr<ATTR_SCOM_SWITCHES>(); + + l_switches.useFsiScom = 0; + l_switches.useXscom = 1; + + (*proc)->setAttr<ATTR_SCOM_SWITCHES>(l_switches); + } } } - if(err) + if (err) { break; } - // Set interrupt presenter to allow all interrupts - for(TARGETING::TargetHandleList::iterator - core = procCores.begin(); - core != procCores.end(); + + //Build up a list of all possible cores (don't care if func/present, + //just that they exist in the blueprint + TARGETING::TargetHandleList l_cores; + for(TARGETING::TargetHandleList::iterator proc = o_procs.begin(); + proc != o_procs.end(); + ++proc) + { + l_cores.clear(); + getChildChiplets(l_cores, *proc, TYPE_CORE, false); + for(TARGETING::TargetHandleList::iterator core = l_cores.begin(); + core != l_cores.end(); + ++core) + { + o_cores.push_back(*core); + } + } + }while(0); + + return err; +} + +void IntrRp::allowAllInterrupts(TARGETING::Target* i_core) +{ + const TARGETING::Target * proc = getParentChip(i_core); + + FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>(); + FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>(); + CHIP_UNIT_ATTR coreId = i_core->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + + PIR_t pir(0); + pir.nodeId = node; + pir.chipId = chip; + pir.coreId = coreId; + + size_t threads = cpu_thread_count(); + for(size_t thread = 0; thread < threads; ++thread) + { + pir.threadId = thread; + uint64_t cpprAddr=cpuOffsetAddr(pir)+iv_baseAddr+CPPR_OFFSET; + uint8_t *cppr = reinterpret_cast<uint8_t*>(cpprAddr); + *cppr = 0xff; // allow all interrupts + } + +} + +void IntrRp::disableAllInterrupts(TARGETING::Target* i_core) +{ + const TARGETING::Target * proc = getParentChip(i_core); + + FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>(); + FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>(); + CHIP_UNIT_ATTR coreId = i_core->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + + PIR_t pir(0); + pir.nodeId = node; + pir.chipId = chip; + pir.coreId = coreId; + + size_t threads = cpu_thread_count(); + for(size_t thread = 0; thread < threads; ++thread) + { + pir.threadId = thread; + disableInterruptPresenter(pir); + } +} + +void IntrRp::drainMpIplInterrupts(TARGETING::TargetHandleList & i_cores) +{ + TRACFCOMP(g_trac_intr,"Drain pending interrupts"); + bool interrupt_found = false; + size_t retryCount = 10; + + do + { + interrupt_found = false; + nanosleep(0,1000000); // 1 ms + + for(TARGETING::TargetHandleList::iterator + core = i_cores.begin(); + core != i_cores.end(); ++core) { const TARGETING::Target * proc = getParentChip(*core); FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>(); FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>(); - CHIP_UNIT_ATTR coreId = - (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + CHIP_UNIT_ATTR coreId = + (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>(); PIR_t pir(0); pir.nodeId = node; pir.chipId = chip; pir.coreId = coreId; + TRACFCOMP(g_trac_intr," n%d p%d c%d", node, chip, coreId); size_t threads = cpu_thread_count(); for(size_t thread = 0; thread < threads; ++thread) { pir.threadId = thread; - uint64_t cpprAddr=cpuOffsetAddr(pir)+iv_baseAddr+CPPR_OFFSET; - uint8_t *cppr = reinterpret_cast<uint8_t*>(cpprAddr); - *cppr = 0xff; // allow all interrupts + uint64_t xirrAddr = iv_baseAddr + + cpuOffsetAddr(pir) + XIRR_RO_OFFSET; + uint32_t * xirrPtr = + reinterpret_cast<uint32_t*>(xirrAddr); + uint32_t xirr = *xirrPtr & 0x00FFFFFF; + TRACDCOMP(g_trac_intr," xirrPtr[%p] xirr[%x]\n", xirrPtr, xirr); + if(xirr) + { + // Found pending interrupt! + interrupt_found = true; + + TRACFCOMP(g_trac_intr, + ERR_MRK + "Pending interrupt found on MPIPL." + " CpuId:0x%x XIRR:0x%x", + pir.word, + xirr); + uint8_t * mfrrPtr = + reinterpret_cast<uint8_t*>(xirrAddr + MFRR_OFFSET); + // Signal EOI - read then write xirr value + ++xirrPtr; // move to RW XIRR reg + volatile uint32_t xirr_rw = *xirrPtr; + + //If IPI need to set mfrr to 0xFF + if(INTERPROC_XISR == xirr) + { + *mfrrPtr = 0xFF; + } + + *xirrPtr = xirr_rw; + --xirrPtr; // back to RO XIRR reg + } } } + } while(interrupt_found == true && --retryCount != 0); - // Now look for interrupts - bool interrupt_found = false; - size_t retryCount = 10; + if(interrupt_found && (retryCount == 0)) + { + // traces above should identify stuck interrupt + INITSERVICE::doShutdown(INTR::RC_PERSISTANT_INTERRUPTS); + } +} + + + +errlHndl_t IntrRp::hw_disableIntrMpIpl() +{ + errlHndl_t err = NULL; + TARGETING::TargetHandleList funcProc, procCores; + + //Need to clear out all pending interrupts. This includes + //ones that PHYP already accepted and ones "hot" in the XIRR + //register. Must be done for all processors prior to opening + //up traffic for mailbox (since we switch the IRSN). PHYP + //can route PSI interrupts to any chip in the system so all + //must be cleaned up prior to switching - do + do + { + //Get the procs/cores + err = findProcs_Cores(funcProc, procCores); + if(err) { - interrupt_found = false; - nanosleep(0,1000000); // 1 ms + break; + } - for(TARGETING::TargetHandleList::iterator - core = procCores.begin(); - core != procCores.end(); - ++core) - { - const TARGETING::Target * proc = getParentChip(*core); - - FABRIC_CHIP_ID_ATTR chip = - proc->getAttr<ATTR_FABRIC_CHIP_ID>(); - FABRIC_NODE_ID_ATTR node = - proc->getAttr<ATTR_FABRIC_NODE_ID>(); - CHIP_UNIT_ATTR coreId = - (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>(); - - PIR_t pir(0); - pir.nodeId = node; - pir.chipId = chip; - pir.coreId = coreId; - - size_t threads = cpu_thread_count(); - for(size_t thread = 0; thread < threads; ++thread) - { - pir.threadId = thread; - uint64_t xirrAddr = iv_baseAddr + - cpuOffsetAddr(pir) + XIRR_RO_OFFSET; - uint32_t * xirrPtr = - reinterpret_cast<uint32_t*>(xirrAddr); - uint32_t xirr = *xirrPtr & 0x00FFFFFF; - if(xirr) // pending interrupt - { - // Found pending interrupt! - interrupt_found = true; - - TRACFCOMP(g_trac_intr, - ERR_MRK - "Pending interrupt found on MPIPL." - " CpuId:0x%x XIRR:0x%x", - pir.word, - xirr); - // Signal EOI - read then write xirr value - ++xirrPtr; // move to RW XIRR reg - volatile uint32_t xirr_rw = *xirrPtr; - *xirrPtr = xirr_rw; - --xirrPtr; // back to RO XIRR reg - } - } - } - } while(interrupt_found == true && --retryCount != 0); + //since HB will need to use PSI interrupt block, we need to + //perform the extra step of disabling FSP PSI interrupts at + //source(theoretically upstream disable should have handled, + //but it seesms to slip through somehow and doesn't get fully + //cleaned up cause we clear the XIVR + for(TARGETING::TargetHandleList::iterator proc = funcProc.begin(); + (proc != funcProc.end()) && !err; + ++proc) + { + uint64_t reg = PSI_FSP_INT_ENABLE; + size_t scom_len = sizeof(uint64_t); + err = deviceWrite + ( + (*proc), + ®, + scom_len, + DEVICE_SCOM_ADDRESS(PSI_HBCR_AND_SCOM_ADDR) + ); + } + if(err) + { + break; + } - if(interrupt_found && (retryCount == 0)) + // Disable upstream intr routing on all processor chips + TRACFCOMP(g_trac_intr,"Disable upstream interrupt"); + for(TARGETING::TargetHandleList::iterator proc = funcProc.begin(); + (proc != funcProc.end()) && !err; + ++proc) + { + // disable upstream intr routing + err = hw_disableRouting(*proc,INTR_UPSTREAM); + } + if(err) { - // traces above should identify stuck interrupt - INITSERVICE::doShutdown(INTR::RC_PERSISTANT_INTERRUPTS); + break; } - // Disable all interrupt presenters + // Set interrupt presenter to allow all interrupts + TRACFCOMP(g_trac_intr,"Allow interrupts"); for(TARGETING::TargetHandleList::iterator core = procCores.begin(); core != procCores.end(); ++core) { - const TARGETING::Target * proc = getParentChip(*core); + allowAllInterrupts(*core); + } - FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>(); - FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>(); - CHIP_UNIT_ATTR coreId = - (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>(); + // Now look for interrupts + drainMpIplInterrupts(procCores); - PIR_t pir(0); - pir.nodeId = node; - pir.chipId = chip; - pir.coreId = coreId; + // Issue blind EOIs to all threads IPIs and to clean up stale XIRR + TRACFCOMP(g_trac_intr,"Issue blind EOIs to all ISRN and IPIs"); + for(TARGETING::TargetHandleList::iterator proc = funcProc.begin(); + (proc != funcProc.end()) && !err; + ++proc) + { + err = blindIssueEOIs(*proc); + } + if(err) + { + break; + } - size_t threads = cpu_thread_count(); - for(size_t thread = 0; thread < threads; ++thread) - { - pir.threadId = thread; - disableInterruptPresenter(pir); - } + // Disable all interrupt presenters + for(TARGETING::TargetHandleList::iterator core = procCores.begin(); + core != procCores.end(); + ++core) + { + disableAllInterrupts(*core); } // disable downstream routing and clean up IRSN regs - for(TARGETING::TargetHandleList::iterator proc = procChips.begin(); - proc != procChips.end(); + for(TARGETING::TargetHandleList::iterator proc = funcProc.begin(); + proc != funcProc.end(); ++proc) { // disable downstream routing @@ -1564,6 +2016,15 @@ errlHndl_t IntrRp::hw_disableIntrMpIpl() { break; } + + //Now mask off all XIVRs under the PSI unit + //This prevents hot PSI mbox interrupts from flowing up to HB + //and allows PHYP to deal with them + err = maskXIVR(*proc); + if(err) + { + break; + } } if(err) { @@ -1573,6 +2034,7 @@ errlHndl_t IntrRp::hw_disableIntrMpIpl() return err; } + void IntrRp::cleanCheck() { TARGETING::TargetHandleList procCores; @@ -1847,5 +2309,3 @@ uint64_t INTR::getIntpAddr(const TARGETING::Target * i_ex, uint8_t i_thread) pir.word & (InterruptMsgHdlr::P8_PIR_THREADID_MSK | InterruptMsgHdlr::P8_PIR_COREID_MSK))); } - - diff --git a/src/usr/intr/intrrp.H b/src/usr/intr/intrrp.H index a05bff542..488f27706 100644 --- a/src/usr/intr/intrrp.H +++ b/src/usr/intr/intrrp.H @@ -123,6 +123,14 @@ namespace INTR // Used to enable/disable and control interrupt routing NX_BUID_SCOM_ADDR = 0x0201308E, //INTR CTRL for NX NX_BUID_ENABLE = 0, //INTR Enable bit for NX + NX_IRSN_COMP_MASK = 0x7FFFF, + NX_IRSN_MASK_MASK = 0x1FFF, + NX_IRSN_UPPER_MASK = 0x7E000, + NX_IRSN_COMP_SHIFT = 44, + NX_IRSN_MASK_SHIFT = 31, + MAX_NX_IRSN_SN = 32, + + PE0_IRSN_COMP_SCOM_ADDR = 0x0201201A, //INTR IRSN compare PE0_IRSN_MASK_SCOM_ADDR = 0x0201201B, //INTR IRSN mask @@ -137,8 +145,14 @@ namespace INTR PE2_BAREN_SCOM_ADDR = 0x02012845, //INTR enable/disable // Bit pos in PEx_BAREN_SCOM register - PE_IRSN_RX = 3, // upstream enable - PE_IRSN_TX = 4, // downstream enable + PE_IRSN_DOWNSTREAM = 3, // downstream (PE RX enable) + PE_IRSN_UPSTREAM = 4, // upstream (PE TX enable) + PE_IRSN_SHIFT = 45, + MAX_PE_IRSN_SN = 2048, + + + PSI_FSP_INT_ENABLE = 0x1000000000000000ULL, + PSI_HBCR_AND_SCOM_ADDR = 0x02010913, }; enum INTR_ROUTING_t @@ -228,7 +242,9 @@ namespace INTR LPC_PRIO = 0x40, LCL_ERR_PRIO = 0x10, HOST_PRIO = 0x50, + PSI_PRIO = 0x60, + PSI_XIVR_ADRR = 0x02010910, OCC_XIVR_ADRR = 0x02010916, FSI_XIVR_ADRR = 0x02010917, LPC_XIVR_ADRR = 0x02010918, @@ -282,7 +298,6 @@ namespace INTR typedef std::vector<TARGETING::Target *> ChipList_t; typedef std::vector<ISNvalue_t> ISNList_t; - msg_q_t iv_msgQ; //!< Kernel Interrupt message queue Registry_t iv_registry; //!< registered interrupt type uint64_t iv_baseAddr; //!< Base address of hw INTR regs @@ -419,6 +434,14 @@ namespace INTR errlHndl_t hw_disableRouting(TARGETING::Target * i_proc, INTR_ROUTING_t i_rx_tx); + /* + * During MPIPL issue EOIs (blind) to all ISNs + * @param i_proc The processor chip target to issue EOIs for + * @return an error handle on error + */ + errlHndl_t blindIssueEOIs(TARGETING::Target * i_proc); + + /** * Reset ISRN value in hardware regs * @param i_proc The target processor @@ -427,11 +450,74 @@ namespace INTR errlHndl_t hw_resetIRSNregs(TARGETING::Target * i_proc); /** + * Build a list of "functional" processors. This needs to be + * done without targetting support (just blueprint) since + * on MPIPL the targeting information is obtained in + * discover_targets -- much later in the IPL. + * + + * @param o_proc List of "functional" processors on SMP + * @param o_cores List of cores under functional processors + * @return an error handle on error + */ + errlHndl_t findProcs_Cores(TARGETING::TargetHandleList & o_procs, + TARGETING::TargetHandleList& o_cores); + + /** * disableHwMpIpl */ errlHndl_t hw_disableIntrMpIpl(); /** + * Read the Psi interrupt source number out of the HW + * + * @param i_target Processor target to read value from + * @param o_irsn IRSN of the PSI unit for the processor + * @return an error handle on error + */ + errlHndl_t getPsiIRSN(TARGETING::Target * i_target, + uint32_t& o_irsn); + + /** + * Read the PCIE interrupt source numbers out of the HW + * + * @param i_target Processor target to read value from + * @param o_irsn List of IRSN for the PCIE units + * @return an error handle on error + */ + errlHndl_t getPcieIRSNs(TARGETING::Target * i_target, + std::vector<uint32_t> &o_irsn); + + /** + * Read the NX interrupt source number out of the HW + * + * @param i_target Processor target to read value from + * @param o_irsn IRSN of the NX unit for the processor + * @return an error handle on error + */ + errlHndl_t getNxIRSN(TARGETING::Target * i_target, + uint32_t& o_irsn); + + + /** + * Drain all outstanding interrupts during MPIPL + * @param i_cores List of all existing cores on functional procs + */ + void drainMpIplInterrupts(TARGETING::TargetHandleList & i_cores); + + /** + * Disable all interrupts on passed in core + * @param i_core Core to disable interrupts on + */ + void disableAllInterrupts(TARGETING::Target* i_core); + + /** + * Allow all interrupts on passed in core + * @param i_core Core to enable interrupts on + */ + void allowAllInterrupts(TARGETING::Target* i_core); + + /** * cleanCheck - verify there are no active interrupts */ void cleanCheck(); diff --git a/src/usr/runtime/hdatservice.C b/src/usr/runtime/hdatservice.C index 4de60449b..f6d70d19b 100644 --- a/src/usr/runtime/hdatservice.C +++ b/src/usr/runtime/hdatservice.C @@ -299,6 +299,7 @@ hdatService::hdatService(void) :iv_spiraL(NULL) ,iv_spiraH(NULL) ,iv_spiraS(NULL) +,iv_mdrtCnt(0) { } @@ -600,7 +601,6 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, errhdl = findSpira(); if( errhdl ) { break; } - // NACA if( RUNTIME::NACA == i_section ) { @@ -929,7 +929,7 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, //Note - there is no header for the MDRT //return the total allocated size since it is empty at first - o_dataSize = tuple->hdatAllocSize * tuple->hdatAllocSize; + o_dataSize = tuple->hdatAllocSize * tuple->hdatAllocCnt; errhdl = getSpiraTupleVA(tuple, o_dataAddr); if( errhdl ) { break; } @@ -1157,6 +1157,115 @@ errlHndl_t hdatService::findSpira( void ) return errhdl; } +errlHndl_t hdatService::updateHostDataSectionActual( SectionId i_section, + uint16_t i_count ) +{ + errlHndl_t errhdl = NULL; + TRACFCOMP( g_trac_runtime, "RUNTIME::updateHostDataSectionActual( i_section=%d )", i_section); + + do + { + //Always force a load (mapping) + errhdl = loadHostData(); + if(errhdl) + { + break; + } + + TARGETING::Target * sys = NULL; + TARGETING::targetService().getTopLevelTarget( sys ); + assert(sys != NULL); + + // Figure out what kind of payload we have + TARGETING::ATTR_PAYLOAD_KIND_type payload_kind + = sys->getAttr<TARGETING::ATTR_PAYLOAD_KIND>(); + + if( TARGETING::PAYLOAD_KIND_NONE == payload_kind ) + { + // we're all done -- don't need to do anything + break; + } + //If payload is not (PHYP or Sapphire w/fsp) + else if( !((TARGETING::PAYLOAD_KIND_PHYP == payload_kind ) || + ((TARGETING::PAYLOAD_KIND_SAPPHIRE == payload_kind ) && + !INITSERVICE::spLess()))) + { + TRACFCOMP( g_trac_runtime, "get_host_data_section> There is no host data for PAYLOAD_KIND=%d", payload_kind ); + /*@ + * @errortype + * @moduleid RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL + * @reasoncode RUNTIME::RC_INVALID_PAYLOAD_KIND + * @userdata1 ATTR_PAYLOAD_KIND + * @userdata2 Requested Section + * @devdesc There is no host data for specified kind of payload + */ + errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL, + RUNTIME::RC_INVALID_PAYLOAD_KIND, + payload_kind, + i_section); + errhdl->collectTrace("RUNTIME",1024); + break; + } + + // Setup the SPIRA pointers + errhdl = findSpira(); + if( errhdl ) { break; } + + + // MS DUMP Results Table - MDRT + if( RUNTIME::MS_DUMP_RESULTS_TBL == i_section ) + { + //For security we can't trust the FSP's payload attribute + // on MPIPLs for the dump tables. + //@todo: RTC:59171 + + // Find the right tuple and verify it makes sense + hdat5Tuple_t* tuple = NULL; + if( iv_spiraS ) + { + tuple = &(iv_spiraS->hdatDataArea[SPIRAH_MS_DUMP_RSLT_TBL]); + } + else if( unlikely(iv_spiraL != NULL) ) + { + tuple = &(iv_spiraL->hdatDataArea[SPIRAL_MS_DUMP_RSLT_TBL]); + } + TRACFCOMP( g_trac_runtime, "MS_DUMP_RESULTS_TBL tuple=%p, count=%x", tuple, i_count); + errhdl = check_tuple( i_section, + tuple ); + if( errhdl ) { break; } + + tuple->hdatActualCnt = i_count; + } + // Not sure how we could get here... + else + { + TRACFCOMP( g_trac_runtime, "get_host_data_section> Unknown section %d", i_section ); + /*@ + * @errortype + * @moduleid RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL + * @reasoncode RUNTIME::RC_INVALID_SECTION + * @userdata1 Section Id + * @userdata2 <unused> + * @devdesc Unknown section requested + */ + errhdl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL, + RUNTIME::RC_INVALID_SECTION, + i_section, + 0); + errhdl->collectTrace("RUNTIME",1024); + break; + } + + if( errhdl ) { break; } + + } while(0); + + return errhdl; +} + /******************** Public Methods ********************/ @@ -1183,6 +1292,22 @@ errlHndl_t get_host_data_section( SectionId i_section, getHostDataSection(i_section,i_instance, o_dataAddr, o_dataSize); } +errlHndl_t update_host_data_section_actual( SectionId i_section, + uint16_t i_count ) +{ + return Singleton<hdatService>::instance(). + updateHostDataSectionActual(i_section,i_count); +} + +void update_MDRT_Count(uint16_t i_count ) +{ + Singleton<hdatService>::instance().updateMdrtCount(i_count); +} + +errlHndl_t write_MDRT_Count( void ) +{ + return Singleton<hdatService>::instance().writeMdrtCount(); +} }; /******************** diff --git a/src/usr/runtime/hdatservice.H b/src/usr/runtime/hdatservice.H index 542c7be32..0b670273a 100644 --- a/src/usr/runtime/hdatservice.H +++ b/src/usr/runtime/hdatservice.H @@ -95,6 +95,17 @@ namespace RUNTIME uint64_t& o_dataAddr, size_t& o_dataSize ); + /** + * @brief Update the actual count of section. Only supported for + * memory dump results table + * + * @param[in] i_section Chunk of data to find + * @param[in] i_count Actual count + * + * @return errlHndl_t NULL on success + */ + errlHndl_t updateHostDataSectionActual( SectionId i_section, + uint16_t i_count ); protected: /** @@ -219,6 +230,43 @@ namespace RUNTIME * SPIRA-S */ hdatSpira_t* iv_spiraS; + + /** + * Count of number of MDRT entries present + * on MPIPL/Dump. A value of 0 implies it + * doesn't need to be written + */ + uint16_t iv_mdrtCnt; + + public: + /** + * @brief Update the actual count of MDRT. Called by dump + * and needs to be saved away till populate_attributes. Can't + * be directly written by dump since FSP will load new value over + + * @param[in] i_count Actual count for MDRT entries + * + */ + void updateMdrtCount( uint16_t i_count ) + { + iv_mdrtCnt = i_count; + } + + /** + * @brief Write the MDRT stored value to SPIRA + * + * @return errlHndl_t NULL on success + */ + errlHndl_t writeMdrtCount( void ) + { + errlHndl_t l_err = NULL; + if(iv_mdrtCnt) + { + l_err = updateHostDataSectionActual( + MS_DUMP_RESULTS_TBL,iv_mdrtCnt); + } + return l_err; + } }; }; |