/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/import/chips/p9/procedures/hwp/ffdc/exp_collect_explorer_log.C $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2016,2019 */ /* [+] 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 */ //------------------------------------------------------------------------------ /// @file exp_collect_explorer_log.C /// /// @brief Collects and adds Explorer logs to rc //------------------------------------------------------------------------------ // *HWP HW Owner : Matt Derksen // *HWP HW Backup Owner : <> // *HWP FW Owner : <> // *HWP Level : 2 // *HWP Consumed by : SE:HB //------------------------------------------------------------------------------ #include #include "exp_collect_explorer_log.H" #include struct explog_section_header_t { uint16_t packet_num; // ordering byte (0 = first packet) uint32_t offset_exp_log; // offset where data portion started in full explorer log uint16_t error_data_size; // size of data portion following header explog_section_header_t() : packet_num(0), offset_exp_log(0), error_data_size(0) {} } __attribute__((__packed__)); // 1st entry is most relevant traces so make it a small size so // it won't be truncated from HWP error log const size_t FIRST_PACKET_SIZE = 0x100; // Use a larger packet size for the rest of the remaining error data // These aren't as important since they are older trace logs const size_t FOLLOWING_PACKET_SIZE = 0x200; /** * @brief Explorer Log type? * * The firmware maintains the log in a circular buffer in RAM (ACTIVE_LOG) and * in the event of a processor exception, firmware assert, or other critical * condition the firmware saves the data in RAM to SPI flash (SAVED_LOG). * Having the log stored in non-volatile memory allows post-analysis * of the log even if it requires a power-cycle to recover the system. */ enum exp_log_type : uint8_t { ACTIVE_LOG = 1, // RAM error section SAVED_LOG = 2 // SPI flash error section }; /** * @brief Main procedure to grab log traces from Explorer chip * and append the trace data to HWP error (o_rc) * * @param[in] i_ocmb_chip - OCMB chip target * @param[in] i_size - allowable total size (add entries upto this size) * @param[in] i_log_type - what kind of explorer log to grab * @param[out] o_rc - return code to add FFDC data to. * * @return FAPI2_RC_SUCCESS iff ok */ fapi2::ReturnCode exp_collect_explorer_logs(const fapi2::ffdc_t& i_ocmb_chip, const fapi2::ffdc_t& i_size, const exp_log_type i_log_type, fapi2::ReturnCode& o_rc) { fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; // This variable is reused multiple times to build up a unique section // identifier to split the log data read from the OCMB before we add // each section to the HWP error explog_section_header_t l_header_meta; // target from which to grab the error log data fapi2::Target l_target_ocmb = *(reinterpret_cast *> (i_ocmb_chip.ptr())); // How much explorer log data are we allowed to add to the HWP error? uint32_t l_allowable_size = *(reinterpret_cast(i_size.ptr())); std::vectorl_explorer_log_data; // full Explorer log data fapi2::ffdc_t UNIT_FFDC_EXP_ERROR; // filled in for RC_EXPLORER_ERROR_LOG FAPI_INF( "exp_collect_explorer_logs: Entering ... " "(log type: %s, max data size: 0x%04X)", i_log_type == ACTIVE_LOG ? "Active" : "Saved", l_allowable_size ); if ( ACTIVE_LOG == i_log_type ) { FAPI_EXEC_HWP(l_rc, exp_active_log, l_target_ocmb, l_explorer_log_data); } else { FAPI_EXEC_HWP(l_rc, exp_saved_log, l_target_ocmb, l_explorer_log_data); } if (l_rc != fapi2::FAPI2_RC_SUCCESS) { FAPI_ERR("exp_collect_explorer_logs: error 0x%04X from exp_%s_log", (uint32_t)l_rc, i_log_type == ACTIVE_LOG ? "active" : "saved"); } else { // Variable to store how much Explorer data we have remaining uint32_t l_explorer_bytes_left = l_explorer_log_data.size(); // Add this much explorer log data (as maximum amount, could be less) l_header_meta.error_data_size = FIRST_PACKET_SIZE; // We read from the end since the most recent logs are the last // entries returned in the full Explorer log data auto l_end_ptr = l_explorer_log_data.end(); // This is where we start iterating through the Explorer log data // and break it into sections that are added to the HWP error while ( l_explorer_bytes_left ) { // ---------------------------------------------------------------- // Calculate how much explorer data to add for this section entry // ---------------------------------------------------------------- // Verify there is enough space left in the allowable HWP error // so we can add another full data section if ( l_allowable_size > l_header_meta.error_data_size) { // We can add at least a packet of data, if we have that // much to add if (l_explorer_bytes_left < l_header_meta.error_data_size) { FAPI_INF("exp_collect_explorer_logs: %d) reduce packet size to include the last explorer log bytes" "(l_explorer_bytes_left %d, Initial packet size %d)", l_header_meta.packet_num, l_explorer_bytes_left, l_header_meta.error_data_size); // reduce the packet size to include the last explorer log bytes l_header_meta.error_data_size = l_explorer_bytes_left; } // else, have enough data and space, so add full data size } else if ( l_allowable_size ) // Any space left? { // Note: if here, we cannot add a full section size of data // Is allowable size remaining less than the explorer bytes available? if ( l_allowable_size < l_explorer_bytes_left ) { // use up the rest of the allowable space available FAPI_INF("exp_collect_explorer_logs: %d) use up rest of space available" "(l_explorer_bytes_left %d, l_allowable_size %d)", l_header_meta.packet_num, l_explorer_bytes_left, l_allowable_size); l_header_meta.error_data_size = l_allowable_size; } else { // reduce the packet size to include the last explorer log bytes l_header_meta.error_data_size = l_explorer_bytes_left; } } else { // reached allowable size break; } // ---------------------------------------------------------------- // offset where the data is starting from out of the whole Explorer log data l_header_meta.offset_exp_log = l_explorer_bytes_left - l_header_meta.error_data_size; FAPI_INF("exp_collect_explorer_logs: %d) starting offset 0x%08X " "(data size: %d)", l_header_meta.packet_num, l_header_meta.offset_exp_log, l_header_meta.error_data_size); // Adding header with meta data auto const ptr = reinterpret_cast(&l_header_meta); std::vectorl_error_log_entry ( ptr, ptr + sizeof(l_header_meta)); // Now append the explorer error section to the section entry // Note: working backwards from the end of the Explorer log data l_error_log_entry.insert( l_error_log_entry.end(), l_end_ptr - l_header_meta.error_data_size, l_end_ptr ); // Add the section entry to the HWP error log UNIT_FFDC_EXP_ERROR.ptr() = l_error_log_entry.data(); UNIT_FFDC_EXP_ERROR.size() = l_error_log_entry.size(); if (ACTIVE_LOG == i_log_type) { FAPI_ADD_INFO_TO_HWP_ERROR(o_rc, RC_EXPLORER_ACTIVE_ERROR_LOG); } else { FAPI_ADD_INFO_TO_HWP_ERROR(o_rc, RC_EXPLORER_SAVED_ERROR_LOG); } // Update to next packet of Explorer error log data l_header_meta.packet_num++; l_explorer_bytes_left -= l_header_meta.error_data_size; l_end_ptr -= l_header_meta.error_data_size; // point to beginning of last data inserted l_allowable_size -= l_header_meta.error_data_size; l_header_meta.error_data_size = FOLLOWING_PACKET_SIZE; } } FAPI_INF("exp_collect_explorer_logs: Exiting ..."); return l_rc; } /// See header fapi2::ReturnCode exp_collect_explorer_active_log( const fapi2::ffdc_t& i_ocmb_chip, const fapi2::ffdc_t& i_size, fapi2::ReturnCode& o_rc ) { return exp_collect_explorer_logs(i_ocmb_chip, i_size, ACTIVE_LOG, o_rc); } /// See header fapi2::ReturnCode exp_collect_explorer_saved_log( const fapi2::ffdc_t& i_ocmb_chip, const fapi2::ffdc_t& i_size, fapi2::ReturnCode& o_rc ) { return exp_collect_explorer_logs(i_ocmb_chip, i_size, SAVED_LOG, o_rc); }