Skip to content

Commit

Permalink
Add WOF compare data section for RC_WOF_TABLE_NOT_FOUND errors
Browse files Browse the repository at this point in the history
Only show data that was compared to find a matching WOF table.
Show each non-matching table in the WOF compare section along with
what we were trying to match

Change-Id: Ia3b44fac54a212e3584536c376598de5dfcf9a8d
CQ:SW426770
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/62529
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
  • Loading branch information
mderkse1 authored and dcrowell77 committed Jul 24, 2018
1 parent c9d74db commit 0a0a63d
Show file tree
Hide file tree
Showing 4 changed files with 294 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/include/usr/errl/errlreasoncodes.H
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/usr/errl/plugins/errludparserfactoryerrl.H
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "errludsensor.H"
#include "errludbuild.H"
#include "errludstate.H"
#include "errludwofdata.H"

namespace ERRORLOG
{
Expand Down Expand Up @@ -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:
Expand Down
206 changes: 206 additions & 0 deletions src/usr/errl/plugins/errludwofdata.H
Original file line number Diff line number Diff line change
@@ -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
102 changes: 85 additions & 17 deletions src/usr/fapi2/plat_wof_access.C
Original file line number Diff line number Diff line change
Expand Up @@ -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 ....");
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
*/
Expand All @@ -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);

Expand All @@ -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;
Expand Down

0 comments on commit 0a0a63d

Please sign in to comment.