diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/errl/errlreasoncodes.H | 1 | ||||
-rw-r--r-- | src/usr/errl/plugins/errludparserfactoryerrl.H | 2 | ||||
-rw-r--r-- | src/usr/errl/plugins/errludwofdata.H | 206 | ||||
-rw-r--r-- | src/usr/fapi2/plat_wof_access.C | 102 |
4 files changed, 294 insertions, 17 deletions
diff --git a/src/include/usr/errl/errlreasoncodes.H b/src/include/usr/errl/errlreasoncodes.H index dfe0eb8fc..c77e1de2a 100644 --- a/src/include/usr/errl/errlreasoncodes.H +++ b/src/include/usr/errl/errlreasoncodes.H @@ -77,6 +77,7 @@ namespace ERRORLOG ERRL_UDT_STRING_SET = 0x09, ERRL_UDT_BUILD = 0x0A, ERRL_UDT_SYSSTATE = 0x0B, + ERRL_UDT_WOFDATA = 0x0C, }; // Identifiers for ERRL user data subsection versions diff --git a/src/usr/errl/plugins/errludparserfactoryerrl.H b/src/usr/errl/plugins/errludparserfactoryerrl.H index 923632852..fbefe231f 100644 --- a/src/usr/errl/plugins/errludparserfactoryerrl.H +++ b/src/usr/errl/plugins/errludparserfactoryerrl.H @@ -40,6 +40,7 @@ #include "errludsensor.H" #include "errludbuild.H" #include "errludstate.H" +#include "errludwofdata.H" namespace ERRORLOG { @@ -69,6 +70,7 @@ public: registerParser<ErrlUserDetailsParserSensor>(ERRL_UDT_SENSOR); registerParser<ErrlUserDetailsParserBuild>(ERRL_UDT_BUILD); registerParser<ErrlUserDetailsParserSysState>(ERRL_UDT_SYSSTATE); + registerParser<ErrlUserDetailsParserWofData>(ERRL_UDT_WOFDATA); } private: diff --git a/src/usr/errl/plugins/errludwofdata.H b/src/usr/errl/plugins/errludwofdata.H new file mode 100644 index 000000000..f757c91d2 --- /dev/null +++ b/src/usr/errl/plugins/errludwofdata.H @@ -0,0 +1,206 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/errl/plugins/errludwofdata.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017,2018 */ +/* [+] 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 */ +#ifndef ERRL_UDWOFDATA_H +#define ERRL_UDWOFDATA_H + +/** + * @file errludwofdata.H + * + * Defines the ErrlUserDetailsWofData class that parses the + * WOF data user detail section of an error log + */ + +#include "errluserdetails.H" +#include <targeting/common/target.H> + +namespace ERRORLOG +{ + +/** + * @class ErrlUserDetailsParserWofData + * + * Parses WOF data user detail in an error log + */ +class ErrlUserDetailsParserWofData :public ErrlUserDetailsParser +{ +public: + /** + * @brief Constructor + */ + ErrlUserDetailsParserWofData() {} + + /** + * @brief Destructor + */ + virtual ~ErrlUserDetailsParserWofData() {} + + /** + * @brief Parses WOF detail data from an error log + * + * @param i_version Version of the data + * @param i_parser ErrlUsrParser object for outputting information + * @param i_pBuffer Pointer to buffer containing WOF detail data + * @param i_buflen Length of the buffer + */ + virtual void parse(errlver_t i_version, + ErrlUsrParser & i_parser, + void * i_pBuffer, + const uint32_t i_buflen) const + { + // From src/usr/fapi2/plat_wof_access.C + typedef struct + { + uint8_t core_count; + uint8_t mode; + uint16_t socket_power_w; + uint16_t sort_power_freq_mhz; + } wofTableCompareData_t; + + // From src/import/chips/p9/procedures/hwp/lib/p9_pstates_common.h + typedef enum + { + WOF_MODE_UNKNOWN = 0, + WOF_MODE_NOMINAL = 1, + WOF_MODE_TURBO = 2 + } WOF_MODE; + + uint16_t tableEntries = 0; + + // Format of WofData error buffer: + // uint16_t - # of table entries (including search for table) + // wofTableCompareData_t - Searched for this table + // wofTableCompareData_t - last table rejected for possible match + // ... + // wofTableCompareData_t - 1st table rejected for possible match + // NOTE: format must match + // addWofCompareDataToErrl() in plat_wof_access.C + if ((NULL != i_pBuffer) && (i_buflen >= sizeof(tableEntries))) + { + tableEntries = ntohs(*(reinterpret_cast<uint16_t*>(i_pBuffer))); + } + + // How many entries are really present in this buffer? + uint16_t actualTableCount = (i_buflen - sizeof(tableEntries)) / + sizeof(wofTableCompareData_t); + + // sanity check to verify we are getting all the table data + if (tableEntries != actualTableCount) + { + i_parser.PrintString("**************************************",""); + i_parser.PrintNumber("Total entries calculated", "%d", + actualTableCount); + i_parser.PrintNumber("Total entries expected", "%d", + tableEntries); + i_parser.PrintString("**************************************",""); + + tableEntries = actualTableCount; // don't go over buffer length + } + + // Check that the remaining data breaks down into parsable + // wofTableCompareData_t entries + if ( (i_buflen - sizeof(tableEntries)) + % sizeof(wofTableCompareData_t) == 0 ) + { + i_parser.PrintString("---------------------------------------", + "---------------------------------------"); + i_parser.PrintNumber("Total WOF Tables compared", "%d", + tableEntries-1); + + // point to start of table compare data + void * i_pTableData = (uint8_t*)i_pBuffer + sizeof(tableEntries); + wofTableCompareData_t* outputDataPtr = + static_cast<wofTableCompareData_t*>(i_pTableData); + for ( uint32_t tableEntry = 0; tableEntry < tableEntries; + ++tableEntry ) + { + if (tableEntry == 0) + { + i_parser.PrintString("---------------------------------------", + "---------------------------------------"); + i_parser.PrintString("Searched for this table", + "Tried to match this:"); + } + else + { + i_parser.PrintString("---------------------------------------", + "---------------------------"); + i_parser.PrintNumber("WOF Table", "#%d", tableEntry); + } + + i_parser.PrintNumber( "Core Count", "%d", + outputDataPtr->core_count ); + + switch(outputDataPtr->mode) + { + case WOF_MODE_UNKNOWN: + { + i_parser.PrintString( "Mode", "Any" ); + break; + } + case WOF_MODE_NOMINAL: + { + i_parser.PrintString( "Mode", "Nominal" ); + break; + } + case WOF_MODE_TURBO: + { + i_parser.PrintString( "Mode", "Turbo" ); + break; + } + default: + { + i_parser.PrintNumber( "Mode", "UNKNOWN: 0x%X", + outputDataPtr->mode ); + break; + } + } + i_parser.PrintNumber("Socket Power (Watts)", "%d", + ntohs(outputDataPtr->socket_power_w)); + i_parser.PrintNumber("Sort Power Freq (MHz)", "%d", + ntohs(outputDataPtr->sort_power_freq_mhz)); + outputDataPtr++; // go to next table entry + } + } + else + { + i_parser.PrintNumber("WOF Buffer length", "0x%X", i_buflen); + i_parser.PrintString("Expected buffer format:", + "uint16_t count, match this entry, unmatched entries"); + i_parser.PrintNumber("Each entry size", "%d", + sizeof(wofTableCompareData_t)); + i_parser.PrintHexDump(i_pBuffer, i_buflen); + } + } + +private: + // Disabled + ErrlUserDetailsParserWofData(const ErrlUserDetailsParserWofData &); + ErrlUserDetailsParserWofData & operator=( + const ErrlUserDetailsParserWofData &); +}; + +} + +#endif diff --git a/src/usr/fapi2/plat_wof_access.C b/src/usr/fapi2/plat_wof_access.C index fc8ce7cc9..24c17b8aa 100644 --- a/src/usr/fapi2/plat_wof_access.C +++ b/src/usr/fapi2/plat_wof_access.C @@ -108,6 +108,72 @@ typedef struct __attribute__((__packed__)) wofSectionTableEntry } wofSectionTableEntry_t; +// Compared fields in each WOF table header entry +// NOTE: struct must match errl/plugins/errludwofdata.H +typedef struct __attribute__((__packed__)) wofTableCompareData +{ + uint8_t core_count; + uint8_t mode; + uint16_t socket_power_w; + uint16_t sort_power_freq_mhz; +} wofTableCompareData_t; + +/** + * @brief Adds WOF detail data to an error log + * + * Format of WofData error buffer: + * uint16_t - # of table entries (including search for table) + * wofTableCompareData_t - Searched for this table + * wofTableCompareData_t - last table rejected for possible match + * ... + * wofTableCompareData_t - 1st table rejected for possible match + * NOTE: format must match errl plugin parser (errludwofdata.H) + * + * @param io_err Error log to add data into + * @param i_match_data Searched for table data + * @param i_headers Table headers searched that did not match + */ +void addWofCompareDataToErrl( errlHndl_t &io_err, + wofTableCompareData_t * i_match_data, + std::vector<WofTablesHeader_t*> i_headers ) +{ + uint16_t l_WOFentries = i_headers.size() + 1; // add searched entry too + + // Allocate WofData error buffer + uint32_t l_data_len = sizeof(l_WOFentries) + + l_WOFentries * sizeof(WofTablesHeader_t); + uint8_t * l_data = new uint8_t[l_data_len]; + + wofTableCompareData_t * l_tableDataPtr = + reinterpret_cast<wofTableCompareData_t*>(l_data + sizeof(l_WOFentries)); + + // first table entry is the data we tried to match + l_tableDataPtr[0] = *i_match_data; + l_tableDataPtr++; + + // add all the non-matched WOF data header sections + while(i_headers.size()) + { + WofTablesHeader_t * tmpHeader = i_headers.back(); + l_tableDataPtr->core_count = tmpHeader->core_count; + l_tableDataPtr->mode = tmpHeader->mode; + l_tableDataPtr->socket_power_w = tmpHeader->socket_power_w; + l_tableDataPtr->sort_power_freq_mhz = tmpHeader->sort_power_freq_mhz; + l_tableDataPtr++; + i_headers.pop_back(); + } + + io_err->addFFDC( + ERRL_COMP_ID, + l_data, + l_data_len, + 0, // version + ERRORLOG::ERRL_UDT_WOFDATA, // WOF DATA parser + false ); // merge + + delete [] l_data; +} + fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData) { FAPI_DBG("Entering platParseWOFTables ...."); @@ -450,6 +516,8 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData) { // Found a match FAPI_INF("Found a WOF table match"); + FAPI_INF("core_count: %d, socket power w: %d, sort power freq MHz: %d, ver: %d, mode: %d", + l_numCores, l_socketPower, l_sortFreq, l_ver, l_mode); // Copy the WOF table to the output pointer memcpy(o_wofData, @@ -511,10 +579,10 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData) * @moduleid fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES * @reasoncode fapi2::RC_WOF_TABLE_NOT_FOUND * @userdata1[00:15] Number of cores - * @userdata1[16:31] WOF Power Mode (0=Nominal,1=Turbo) + * @userdata1[16:31] WOF Power Mode (1=Nominal, 2=Turbo) * @userdata1[32:63] Socket power - * @userdata2[00:31] Nest frequency - * @userdata2[32:63] Sort frequency + * @userdata2[00:31] Sort frequency + * @userdata2[32:63] Number of WOF tables checked * @devdesc No WOF table match found * @custdesc Firmware Error */ @@ -524,11 +592,11 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData) fapi2::RC_WOF_TABLE_NOT_FOUND, TWO_UINT16_ONE_UINT32_TO_UINT64( l_numCores, - l_wofPowerLimit, + l_mode, l_socketPower), TWO_UINT32_TO_UINT64( - l_nestFreq, - l_sortFreq), + l_sortFreq, + l_headers.size()), true); //software callout l_errl->collectTrace(FAPI_TRACE_NAME); @@ -537,17 +605,17 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData) l_sys, TARGETING::ATTR_WOF_TABLE_LID_NUMBER) .addToLog(l_errl); - while(l_headers.size()) - { - l_errl->addFFDC( - HWPF_COMP_ID, - l_headers.back(), - sizeof(WofTablesHeader_t), - 0, // version - ERRORLOG::ERRL_UDT_NOFORMAT, // parser ignores data - false ); // merge - l_headers.pop_back(); - } + + // Add table data to error log as own section + // Add just the compare fields into the error log + // for each WofTable that did not match + wofTableCompareData_t l_match_data_fields; + l_match_data_fields.core_count = l_numCores; + l_match_data_fields.socket_power_w = l_socketPower; + l_match_data_fields.sort_power_freq_mhz = l_sortFreq; + l_match_data_fields.mode = l_mode; + + addWofCompareDataToErrl(l_errl, &l_match_data_fields, l_headers); l_rc.setPlatDataPtr(reinterpret_cast<void *>(l_errl)); break; |