diff options
-rw-r--r-- | src/sbefw/sbeHostMsg.H | 33 | ||||
-rw-r--r-- | src/sbefw/sbeHostUtils.C | 1 | ||||
-rw-r--r-- | src/sbefw/sbeMemAccessInterface.H | 2 | ||||
-rw-r--r-- | src/sbefw/sbe_host_intf.H | 1 | ||||
-rw-r--r-- | src/sbefw/sbe_sp_intf.H | 1 | ||||
-rw-r--r-- | src/sbefw/sbecmdgeneric.C | 83 | ||||
-rw-r--r-- | src/sbefw/sbecmdgeneric.H | 8 | ||||
-rw-r--r-- | src/sbefw/sbecmdparser.C | 5 | ||||
-rwxr-xr-x | src/test/testcases/testGeneric.xml | 4 | ||||
-rw-r--r-- | src/test/testcases/testPSUReadSbeMem.py | 158 |
10 files changed, 294 insertions, 2 deletions
diff --git a/src/sbefw/sbeHostMsg.H b/src/sbefw/sbeHostMsg.H index 34d555e6..1b4b7ad3 100644 --- a/src/sbefw/sbeHostMsg.H +++ b/src/sbefw/sbeHostMsg.H @@ -36,6 +36,7 @@ #include <stdint.h> #include "sbe_host_intf.H" #include "sbe_sp_intf.H" +#include "sbe_link.H" /*****************************************************************/ /* SBE->PSU request structures */ @@ -99,6 +100,38 @@ typedef struct } } sbeSetFFDCAddrReq_t; +/* @brief Read SBE MEM structure + */ +typedef struct +{ + uint64_t offset:32; + uint64_t size:32; + uint64_t responseAddr; + + // validate request parameters + bool validateReq() + { + // On ppe reading 8 bytes is optimal. So offset + // should be multiple of 8. + uint32_t const OFFSET_ALLIGNMENT = 8; + // As we use PBA operation, size should be multiple + // of 128bytes. + uint32_t const SIZE_ALLIGNMENT = 128; + // There are 4 seeprom devices each of 64KB, + // aso there is 1 ecc byte per 8 bytes of data + uint32_t const MAX_SEEPROM_SIZE = ((65536 - (65536 % 9)) / 9) * 8 * 4; + + return ( !(( offset % OFFSET_ALLIGNMENT != 0) || + ( size % SIZE_ALLIGNMENT != 0 ) || + ( ( offset + size ) > MAX_SEEPROM_SIZE )) ); + } + // Return effective seeprom address + uint64_t * getEffectiveAddr() + { + return ( uint64_t *)( SBE_SEEPROM_BASE_ORIGIN + offset ); + } +} sbeReadMemReq_t; + /*****************************************************************/ /* SBE->PSU response structures */ /*****************************************************************/ diff --git a/src/sbefw/sbeHostUtils.C b/src/sbefw/sbeHostUtils.C index 7cf14f9b..4b1e8a33 100644 --- a/src/sbefw/sbeHostUtils.C +++ b/src/sbefw/sbeHostUtils.C @@ -218,6 +218,7 @@ void sbePSUSendResponse(sbeSbe2PsuRespHdr_t &i_sbe2PsuRespHdr, fapi2::plat_getTargetHandleByChipletNumber<fapi2::TARGET_TYPE_EX>( sbeMemAccessInterface::PBA_DEFAULT_EX_CHIPLET_ID)); p9_PBA_oper_flag l_myPbaFlag; + l_myPbaFlag.setOperationType(p9_PBA_oper_flag::INJ); sbeMemAccessInterface l_PBAInterface( SBE_MEM_ACCESS_PBA, diff --git a/src/sbefw/sbeMemAccessInterface.H b/src/sbefw/sbeMemAccessInterface.H index 6e268b01..fb01ff5d 100644 --- a/src/sbefw/sbeMemAccessInterface.H +++ b/src/sbefw/sbeMemAccessInterface.H @@ -86,7 +86,7 @@ class sbeMemAccessInterface // Granule size based on interface - PBA/ADU uint32_t iv_granuleSize; // Buffer size is bigger of the two granules - char iv_buffer[MEM_INTERFACE_SIZE_BYTES]; + char iv_buffer[MEM_INTERFACE_SIZE_BYTES] __attribute__ ((aligned (8))); // Interface cleaned up - indicates if the underlying // HWP cleanup is done for the interface. // A new object assumes interface is in cleaned up diff --git a/src/sbefw/sbe_host_intf.H b/src/sbefw/sbe_host_intf.H index 378acae0..ed119bc9 100644 --- a/src/sbefw/sbe_host_intf.H +++ b/src/sbefw/sbe_host_intf.H @@ -96,6 +96,7 @@ enum sbePsuUpdateMemoryRegionMessages */ enum sbePsuGenericMessages { + SBE_PSU_GENERIC_MSG_READ_SBE_MEM = 0x03, SBE_PSU_GENERIC_MSG_SET_FFDC_ADDR = 0x04, SBE_PSU_GENERIC_MSG_QUIESCE = 0x05, SBE_PSU_GENERIC_MSG_SYSTEM_FABRIC_MAP = 0x06, diff --git a/src/sbefw/sbe_sp_intf.H b/src/sbefw/sbe_sp_intf.H index c1cf688d..8d76772a 100644 --- a/src/sbefw/sbe_sp_intf.H +++ b/src/sbefw/sbe_sp_intf.H @@ -217,6 +217,7 @@ enum sbeSecondaryResponse SBE_SEC_MAXIMUM_MEM_REGION_EXCEEDED = 0x16, SBE_SEC_MEM_REGION_AMEND_ATTEMPTED = 0x17, SBE_SEC_INPUT_BUFFER_OVERFLOW = 0x18, + SBE_SEC_INVALID_PARAMS = 0x19, }; /** diff --git a/src/sbefw/sbecmdgeneric.C b/src/sbefw/sbecmdgeneric.C index 5c7320b4..1e0655aa 100644 --- a/src/sbefw/sbecmdgeneric.C +++ b/src/sbefw/sbecmdgeneric.C @@ -204,7 +204,7 @@ uint32_t sbeGetFfdc (uint8_t *i_pArg) // @TODO via RTC : 149074 // primary and secondary status should be picked // from the globals. - // Check for Primary and Secondary Status from Globals and then send + // Check for Primary and Secondary Status from Globals and then send // internal FFDC. rc = sbeFfdcPack.sendOverFIFO(respHdr, SBE_FFDC_ALL_DUMP, @@ -442,5 +442,86 @@ uint32_t sbePsuQuiesce( uint8_t *i_pArg ) return rc; #undef SBE_FUNC } + +//---------------------------------------------------------------------------- +uint32_t sbeReadMem( uint8_t *i_pArg ) +{ + #define SBE_FUNC "sbeReadMem" + SBE_ENTER(SBE_FUNC); + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t fapiRc = FAPI2_RC_SUCCESS; + sbeReadMemReq_t req = {}; + + do + { + // Extract the request + // and send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1 + rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(req)/sizeof(uint64_t)), + (uint64_t*)&req, + true); + if(SBE_SEC_OPERATION_SUCCESSFUL != rc) + { + SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and " + "SBE_HOST_PSU_MBOX_REG2"); + break; + } + + if(!( req.validateReq()) ) + { + SBE_ERROR(SBE_FUNC"Invalid data. offset:0x%08X size:0x%08X", + req.offset, req.size ); + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_USER_ERROR, + SBE_SEC_INVALID_PARAMS); + break; + } + + // Default EX Target Init. As its not LCO mode, ex does not matter. + fapi2::Target<fapi2::TARGET_TYPE_EX> l_ex( + fapi2::plat_getTargetHandleByChipletNumber<fapi2::TARGET_TYPE_EX>( + sbeMemAccessInterface::PBA_DEFAULT_EX_CHIPLET_ID)); + p9_PBA_oper_flag l_myPbaFlag; + l_myPbaFlag.setOperationType(p9_PBA_oper_flag::INJ); + + sbeMemAccessInterface pbaInterface( + SBE_MEM_ACCESS_PBA, + req.responseAddr, + &l_myPbaFlag, + SBE_MEM_ACCESS_WRITE, + sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES, + l_ex); + uint32_t len = req.size; + uint64_t *seepromAddr = req.getEffectiveAddr(); + while( len > 0) + { + uint64_t *dataBuffer = static_cast<uint64_t*> + (pbaInterface.getBuffer()); + for(size_t idx=0; + idx < (sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES/ + sizeof(uint64_t)); + idx++) + { + *dataBuffer = *seepromAddr; + dataBuffer++; + seepromAddr++; + } + + fapi2::ReturnCode fapiRc = pbaInterface.accessGranule( + len == sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS) + { + break; + } + len = len - sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES; + } + } while(false); + + // Send the response + sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, fapiRc, rc); + + SBE_EXIT(SBE_FUNC); + return rc; + #undef SBE_FUNC +} #endif //not __SBEFW_SEEPROM__ diff --git a/src/sbefw/sbecmdgeneric.H b/src/sbefw/sbecmdgeneric.H index 934d34a6..af14541f 100644 --- a/src/sbefw/sbecmdgeneric.H +++ b/src/sbefw/sbecmdgeneric.H @@ -156,4 +156,12 @@ uint32_t sbeSetSystemFabricMap(uint8_t *i_pArg); */ uint32_t sbeStashKeyAddrPair(uint8_t *i_pArg); +/** + * @brief Read the data from SBE memory (0xD703) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the Psu access utility + */ +uint32_t sbeReadMem(uint8_t *i_pArg); #endif // __SBEFW_SBECMDGENERIC_H diff --git a/src/sbefw/sbecmdparser.C b/src/sbefw/sbecmdparser.C index af7b51bb..67c5e166 100644 --- a/src/sbefw/sbecmdparser.C +++ b/src/sbefw/sbecmdparser.C @@ -295,6 +295,11 @@ static sbeCmdStruct_t g_sbePsuMemRegionCmdArray[] = ////////////////////////////////////////////////////////////// static sbeCmdStruct_t g_sbePsuGenericCmdArray[] = { + {sbeReadMem, + SBE_PSU_GENERIC_MSG_READ_SBE_MEM, + (uint16_t)(~SBE_FENCE_AT_RUNTIME), + }, + {sbeSetFFDCAddr, SBE_PSU_GENERIC_MSG_SET_FFDC_ADDR, SBE_NO_FENCE, diff --git a/src/test/testcases/testGeneric.xml b/src/test/testcases/testGeneric.xml index dad7a81b..13e6eae6 100755 --- a/src/test/testcases/testGeneric.xml +++ b/src/test/testcases/testGeneric.xml @@ -37,3 +37,7 @@ <simcmd>run-python-file targets/p9_nimbus/sbeTest/testHostFFDC.py</simcmd> <exitonerror>yes</exitonerror> </testcase> + <testcase> + <simcmd>run-python-file targets/p9_nimbus/sbeTest/testPSUReadSbeMem.py</simcmd> + <exitonerror>yes</exitonerror> + </testcase> diff --git a/src/test/testcases/testPSUReadSbeMem.py b/src/test/testcases/testPSUReadSbeMem.py new file mode 100644 index 00000000..a91fbc48 --- /dev/null +++ b/src/test/testcases/testPSUReadSbeMem.py @@ -0,0 +1,158 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/test/testcases/testPSUReadSbeMem.py $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +import sys +sys.path.append("targets/p9_nimbus/sbeTest" ) +import testPSUUtil +import testRegistry as reg +import testUtil +import testMemUtil + +#------------------------------- +# This is a Test Expected Data +#------------------------------- +def getdoubleword(dataInInt): + hex_string = '0'*(16-len(str(hex(dataInInt))[:18][2:])) + str(hex(dataInInt))[:18][2:] + return hex_string + +def readSeeprom(offset, size, destAddr, primStatus, secStatus): + ''' + #------------------------------------------------------------------------------------------------------------------------------ + # SBE side test data - + #------------------------------------------------------------------------------------------------------------------------------ + ''' + sbe_test_data = ( + #----------------------------------------------------------------------------------------------------- + # OP Reg ValueToWrite size Test Expected Data Description + #----------------------------------------------------------------------------------------------------- + # FFDC Size, Pass CMD Size + ["write", reg.REG_MBOX0, "0000010000F0D703", 8, "None", "Writing to MBOX0 address"], + # seeprom offset, Size + ["write", reg.REG_MBOX1, getdoubleword((offset<<32)+size), 8, "None", "Writing to MBOX1 address"], + # response Addr + ["write", reg.REG_MBOX2, getdoubleword(destAddr), 8, "None", "Writing to MBOX2 address"], + ["write", reg.PSU_SBE_DOORBELL_REG_WO_OR, "8000000000000000", 8, "None", "Update SBE Doorbell register to interrupt SBE"], + ) + ''' + #--------------------- + # Host side test data - SUCCESS + #--------------------- + ''' + host_test_data_success = ( + #---------------------------------------------------------------------------------------------------------------- + # OP Reg ValueToWrite size Test Expected Data Description + #---------------------------------------------------------------------------------------------------------------- + ["read", reg.REG_MBOX4, "0", 8, getdoubleword((primStatus<<48)+(secStatus<<32)+0xF0D703), "Reading Host MBOX4 data to Validate"], + ) + + ''' + #----------------------------------------------------------------------- + # Do not modify - Used to simulate interrupt on Ringing Doorbell on Host + #----------------------------------------------------------------------- + ''' + host_polling_data = ( + #---------------------------------------------------------------------------------------------------------------- + # OP Reg ValueToWrite size Test Expected Data Description + #---------------------------------------------------------------------------------------------------------------- + ["read", reg.PSU_HOST_DOORBELL_REG_WO_OR, "0", 8, "8000000000000000", "Reading Host Doorbell for Interrupt Bit0"], + ) + # Run Simics initially + testUtil.runCycles( 10000000 ); + + # Intialize the class obj instances + regObj = testPSUUtil.registry() # Registry obj def for operation + + # HOST->SBE data set execution + regObj.ExecuteTestOp( testPSUUtil.simSbeObj, sbe_test_data ) + + print "\n Poll on Host side for INTR ...\n" + #Poll on HOST DoorBell Register for interrupt + regObj.pollingOn( testPSUUtil.simSbeObj, host_polling_data, 5 ) + + #SBE->HOST data set execution + regObj.ExecuteTestOp( testPSUUtil.simSbeObj, host_test_data_success ) + +#------------------------- +# Main Function +#------------------------- +def main(): + # Run Simics initially + testUtil.runCycles( 10000000 ); + + print "\n Execute SBE Test - Read SBE Mem\n" + + ''' + Test Case 1 + ''' + readSeeprom(0, 128, 0x08000000, 0, 0) + print "SUCCESS: read seeprom valid" + + # Read data from cache and verify its contents + # seeprom header + seepprmHdr = 'XIP SEPM' + #read from cache + readData = testMemUtil.getmem(0x08000000, 0x80, 0x02) + + for byte in range(len(seepprmHdr)): + if( ord(seepprmHdr[byte]) != readData[byte ]): + print "Data mismtach at: ", byte ; + print " expected: ", ord(seepprmHdr[byte]); + print " Actual: ", readData[byte]; + raise Exception('data mistmach'); + + ''' + Test Case 2 + ''' + readSeeprom(0x38CA0, 0x180, 0x8973780, 0, 0) + print "SUCCESS: read seeprom HB testcase" + + ''' + Test Case 3 + ''' + readSeeprom(0x0, 0x40, 0x08000000, 0x03, 0x19) + print "SUCCESS: read seeprom size not aligned" + + ''' + Test Case 4 + ''' + readSeeprom(0x3fe80, 0x180, 0x08000000, 0x03, 0x19) + print "SUCCESS: read seeprom size exceeded" + + ''' + Test Case 5 + ''' + readSeeprom(0x7, 0x40, 0x08000000, 0x03, 0x19) + print "SUCCESS: read seeprom offset not aligned" + +if __name__ == "__main__": + main() + if err: + print ( "\nTest Suite completed with error(s)" ) + #sys.exit(1) + else: + print ( "\nTest Suite completed with no errors" ) + #sys.exit(0); + + |