diff options
author | Donald Washburn <dwashbur@us.ibm.com> | 2017-08-17 10:28:05 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-11-01 17:06:39 -0400 |
commit | 5e731ccc76d458e752e465471e27a40dd6011e5b (patch) | |
tree | 33792894597adf1c3073d3ed522bc6ab253ea4d1 /src/usr/scom/test | |
parent | 89c19d7e3a5b6f2781636ca5373672f38d8f0a13 (diff) | |
download | talos-hostboot-5e731ccc76d458e752e465471e27a40dd6011e5b.tar.gz talos-hostboot-5e731ccc76d458e752e465471e27a40dd6011e5b.zip |
Work around for SCOM DMI bug on Cumulus.
Work-around for HW415185. On a cumulus system reads from
the first 6 DMI SCOM registers need to be read twice to
obtain correct values. It is desired to implement a
workaround in the SCOM driver that will force a retry
for any reads from these registers until a hardware
fix is in place.
*Implemented a framework for executing post operation
actions following a scom device operation. Currently
the only post operation action defined is the retry
request operation. The purpose of the framework is
to remove workaround logic from the device operation
code and place it in easily removable individual source
files as work-arounds are expected to be temporary in
nature.
*Move existing retry request for IBSCOM retries to
a new class IbScomRetry.
*Created the PostOpRetryCheck base class for the
workaround framework.
*Created a top-level composite pattern class used for
invoking request logic - PostOpChecks.
*Created a workaround class - DmiSomWorkaround
for querying DMI retry requests.
*Modified the doScomOp method to invoke the framework
to test for retries. Removed retry recursion.
*Created Unit Tests.
*Created integration test.
RTC: 177025
Change-Id: If4a1ecc57dd5978e5d1717a42c63cdc1698f4563
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/45104
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>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Prachi Gupta <pragupta@us.ibm.com>
Reviewed-by: Corey V. Swenson <cswenson@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/scom/test')
-rw-r--r-- | src/usr/scom/test/DmiScomWorkaround_for_test.H | 133 | ||||
-rw-r--r-- | src/usr/scom/test/DmiScomWorkaround_test.H | 632 | ||||
-rw-r--r-- | src/usr/scom/test/ibscom_retry_test.H | 281 | ||||
-rw-r--r-- | src/usr/scom/test/makefile | 13 | ||||
-rw-r--r-- | src/usr/scom/test/postopchecks_test.H | 670 | ||||
-rw-r--r-- | src/usr/scom/test/retryWorkaroundTestData.C | 188 | ||||
-rw-r--r-- | src/usr/scom/test/retryWorkaroundTestData.H | 35 |
7 files changed, 1951 insertions, 1 deletions
diff --git a/src/usr/scom/test/DmiScomWorkaround_for_test.H b/src/usr/scom/test/DmiScomWorkaround_for_test.H new file mode 100644 index 000000000..f7f81b68f --- /dev/null +++ b/src/usr/scom/test/DmiScomWorkaround_for_test.H @@ -0,0 +1,133 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/test/DmiScomWorkaround_for_test.H $ */ +/* */ +/* OpenPOWER HostBoot 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 */ +#ifndef __SCOM_DMI_SCOM_WORKAROUND_FOR_TEST_H +#define __SCOM_DMI_SCOM_WORKAROUND_FOR_TEST_H + +#include "../DmiScomWorkaround.H" + +using namespace SCOM; +using namespace ERRORLOG; + +// Derived class to implement mocked target dependency injection for +// Unit Testing of the DmiScomWorkaround class. +class DmiScomWorkaround_for_test : public DmiScomWorkaround +{ +public: + + //--------------------------------------------------------------------- + DmiScomWorkaround_for_test()=default; + + //----------------------------------------------------------------------- + // getTargetType implemented using mocked target. + bool getTargetType(TARGETING::Target* i_target, + TARGETING::TYPE& o_type) const + override + { + //Encodings for mock targets + // 0x4000000000000000 DMI Target + // 0x8000000000000000 PROC Target + // 0x0200000000000000 NIMBUS + // 0x0100000000000000 CUMULUS + // 0x00000000000000XX EC Level + + constexpr uint64_t typeMask{0xC000000000000000}; + constexpr uint64_t procType{0x8000000000000000}; + constexpr uint64_t dmiType{0x4000000000000000}; + + bool l_retval{false}; + uint64_t l_targetAddr = reinterpret_cast<uint64_t>(i_target); + + const uint64_t typeAddr = l_targetAddr & typeMask; + if(procType == typeAddr) + { + o_type = TARGETING::TYPE_PROC; + l_retval = true; + } + else if(dmiType == typeAddr) + { + o_type = TARGETING::TYPE_DMI; + l_retval = true; + } + + return l_retval; + } + + //------------------------------------------------------------------------ + // getTargetModel implemented using mocked target. + bool getTargetModel(TARGETING::Target* i_target, + TARGETING::MODEL& o_model) const + override + { + //Encodings for mock targets + // 0x4000000000000000 DMI Target + // 0x8000000000000000 PROC Target + // 0x0200000000000000 NIMBUS + // 0x0100000000000000 CUMULUS + // 0x00000000000000XX EC Level + + constexpr uint64_t modelMask{0x0300000000000000}; + constexpr uint64_t cumulusModel{0x0100000000000000}; + constexpr uint64_t nimbusModel{0x0200000000000000}; + + bool l_retval{false}; + uint64_t l_targetAddr = reinterpret_cast<uint64_t>(i_target); + + const uint64_t modelAddr = l_targetAddr & modelMask; + if(cumulusModel == modelAddr) + { + o_model = TARGETING::MODEL_CUMULUS; + l_retval = true; + } + else if(nimbusModel == modelAddr) + { + o_model = TARGETING::MODEL_NIMBUS; + l_retval = true; + } + + return l_retval; + } + + //----------------------------------------------------------------------- + bool getTargetECLevel(TARGETING::Target* i_target, + uint8_t& o_ecLevel) const + { + constexpr uint64_t ECLevelMask{0x00000000000000FF}; + + uint64_t l_targetAddr = reinterpret_cast<uint64_t>(i_target); + + const uint64_t l_ecLevel = l_targetAddr & ECLevelMask; + o_ecLevel = static_cast<uint8_t>(l_ecLevel); + + return true; + } + + //------------------------------------------------------------------------ + // We don't want to cache the processor model for unit tests + // in order to allow mocking targets with different models. + bool useCachedProcModel() const override {return false;} + +}; + +#endif diff --git a/src/usr/scom/test/DmiScomWorkaround_test.H b/src/usr/scom/test/DmiScomWorkaround_test.H new file mode 100644 index 000000000..50b5d4cf4 --- /dev/null +++ b/src/usr/scom/test/DmiScomWorkaround_test.H @@ -0,0 +1,632 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/test/DmiScomWorkaround_test.H $ */ +/* */ +/* OpenPOWER HostBoot 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 */ +#ifndef __SCOM_DMI_SCOM_WORKAROUND_TEST_H +#define __SCOM_DMI_SCOM_WORKAROUND_TEST_H + +#include "DmiScomWorkaround_for_test.H" +#include "retryWorkaroundTestData.H" + +#include <cxxtest/TestSuite.H> +#include <errl/errlreasoncodes.H> +#include <targeting/common/target.H> +#include <trace/interface.H> + +#include <vector> + +// Tracing is disabled by default. +// To turn on tracing, build the tests as shown below: +// TRACE_SCOM_UNIT_TEST=1 make -j32 +#ifdef TRACE_SCOM_UNIT_TEST +extern trace_desc_t* g_trac_scom; +#define SCOM_DMI_WORKAROUND_TRACF(printf_string,args...) \ + TRACFCOMP(g_trac_scom,"DMI_WRKAROUND_TEST::" printf_string,##args) +#else +#define SCOM_DMI_WORKAROUND_TRACF(printf_string,args...) +#endif + +//Package the TS_FAIL macro with TRACFCOMP error reporting. +//The TS_FAIL macro output seems to be separated from +//TRACFCOMP output. This can be confusing when adding +//trace statements to the tests while debugging. The failure +//message from the SCOM_DMI_WORKAROUND_TRACF macro will +//appear inline and in the proper context to other trace +//statements which may be added during debugging. +#define FAIL_DMIWKRD_TEST(printf_string,args...) \ + SCOM_DMI_WORKAROUND_TRACF(printf_string, ##args); \ + TS_FAIL("DMI_WRKAROUND_TEST::" printf_string, ##args) + +using namespace SCOM; +using namespace ERRORLOG; + +class DMI_WRKAROUND_TEST: public CxxTest::TestSuite +{ +public: + + //------------------------------------------------------------------- + // The DmiScomWorkaround will request a + // retry based upon the following conditions + // + // requestRetry parameters retry Conditions + // 1) errlHndl_t - Not used. + // 2) uint32_t i_retryCount - Must be 0. + // 3) DeviceFW::OperationType - Must be a read operation. + // 4) TARGETING::Target* i_target - Must be a PROC or DMI target + // 5) void* i_buffer - Not Used + // 6) size_t i_buflen - Not Used + // 7) int64_t i_accessType - Not Used + // 8) uint64_t i_addr - Address must be in a list of addresses + // defined in DmiScomWorkaround. There is + // a list for each DMI 0-7, and a list for + // DMI SCOM addresses accessed by a PROC + // target. + + + //----------------------------------------------------------------------- + // Test Cumulus Proc Target with addresses that do not require retries. + // All requestRetry calls should return false. + void test_cumulus_proc_with_no_retry_addr() + { + bool l_result{true}; + populateMockTargets(); + + do + { + std::shared_ptr<const PostOpRetryCheck> + l_workaround(new DmiScomWorkaround_for_test); + + + if(not l_workaround) + { + FAIL_DMIWKRD_TEST("test_cumulus_proc_with_no_retry_addr: " + "Unable to create a " + "DmiScomWorkaround_for_test " + "object." + ); + + l_result = false; + break; + } + + //iterate through the list of addresses that do not + //require retries. + for(uint64_t addr: g_always_no_retry_addrs) + { + bool l_rc{false}; + + l_rc = l_workaround->requestRetry(nullptr, + 0, + DeviceFW::READ, + iv_cumulus_proc_target, + nullptr, + 0, + 0, + addr + ); + if(l_rc) + { + FAIL_DMIWKRD_TEST("test_cumulus_proc_with_no_retry_addr: " + "requestRetry unexpectedly " + "returned true for a cumulus proc " + "target and address 0x%016X", addr + ); + + l_result = false; + break; + } + } + } + while(0); + + if(l_result) + { + SCOM_DMI_WORKAROUND_TRACF("test_cumulus_proc_with_no_retry_addr: " + "Test Passed!"); + } + else + { + SCOM_DMI_WORKAROUND_TRACF("test_cumulus_proc_with_no_retry_addr: " + "Test Failed!"); + } + } + + //----------------------------------------------------------------------- + // Test Nimbus Proc Target with addresses that do not require retries. + // All requestRetry calls should return false as the workaround is not + // required on Nimbus systems. + void test_nimbus_proc_with_no_retry_addr() + { + bool l_result{true}; + populateMockTargets(); + + do + { + std::shared_ptr<const PostOpRetryCheck> + l_workaround(new DmiScomWorkaround_for_test); + + if(not l_workaround) + { + FAIL_DMIWKRD_TEST("test_nimbus_proc_with_no_retry_addr: " + "Unable to create a " + "DmiScomWorkaround_for_test " + "object." + ); + + l_result = false; + break; + } + + //iterate through the list of addresses that do not + //require retries. + for(uint64_t addr: g_always_no_retry_addrs) + { + bool l_rc{false}; + + l_rc = l_workaround->requestRetry(nullptr, + 0, + DeviceFW::READ, + iv_nimbus_proc_target, + nullptr, + 0, + 0, + addr + ); + if(l_rc) + { + FAIL_DMIWKRD_TEST("test_nimbus_proc_with_no_retry_addr: " + "requestRetry unexpectedly " + "returned true for a nimbus " + "proc target and address " + "0x%016X", + addr + ); + + l_result = false; + break; + } + } + } + while(0); + + if(l_result) + { + SCOM_DMI_WORKAROUND_TRACF("test_nimbus_proc_with_no_retry_addr: " + "Test Passed!"); + } + else + { + SCOM_DMI_WORKAROUND_TRACF("test_nimbus_proc_with_no_retry_addr: " + "Test Failed!"); + } + } + + //--------------------------------------------------------------------- + // Test Cumulus Proc Target with addresses that require retries. + // All requestRetry calls should return true. + void test_cumulus_proc_with_retry_addr() + { + bool l_result{true}; + populateMockTargets(); + + uint8_t l_ecLevel{}; + TARGETING::Target* l_target{}; + + do + { + std::shared_ptr<const PostOpRetryCheck> + l_workaround(new DmiScomWorkaround_for_test); + + + if(not l_workaround) + { + FAIL_DMIWKRD_TEST("test_cumulus_proc_with_retry_addr: " + "Unable to create a " + "DmiScomWorkaround_for_test " + "object" + ); + + l_result = false; + break; + } + + //Do Tests with default EC Level = 0x10 + getTargetECLevel(iv_cumulus_proc_target, l_ecLevel); + + l_result = do_proc_test(l_workaround, + iv_cumulus_proc_target, + "cumulus", + true, //expected result of retryRequest + l_ecLevel + ); + + //Do Tests with EC Level = 0x00 + l_target = setTargetEcLevel(iv_cumulus_proc_target, + 0x00 + ); + + l_result = do_proc_test(l_workaround, + l_target, + "cumulus", + true, //expected result of retryRequest + 0x00 + ); + + //Do Tests with EC Level = 0x11 + l_target = setTargetEcLevel(iv_cumulus_proc_target, + 0x11 + ); + + l_result = do_proc_test(l_workaround, + l_target, + "cumulus", + false, //expected result of retryRequest + 0x11 + ); + + } + while(0); + + if(l_result) + { + SCOM_DMI_WORKAROUND_TRACF("test_cumulus_proc_with_retry_addr: " + "Test Passed!"); + } + else + { + SCOM_DMI_WORKAROUND_TRACF("test_cumulus_proc_with_retry_addr: " + "Test Failed!"); + } + } + + //--------------------------------------------------------------------- + // Test NIMBUS Proc Target with addresses that require retries. + // All requestRetry calls should return false since the workaround + // is not required on NIMBUS systems. + void test_nimbus_proc_with_retry_addr() + { + bool l_result{true}; + populateMockTargets(); + uint8_t l_ecLevel{}; + + do + { + std::shared_ptr<const PostOpRetryCheck> + l_workaround(new DmiScomWorkaround_for_test); + + + if(not l_workaround) + { + FAIL_DMIWKRD_TEST("test_nimbus_proc_with_retry_addr: " + "Unable to create a " + "DmiScomWorkaround_for_test " + "object." + ); + + l_result = false; + break; + } + + getTargetECLevel(iv_cumulus_proc_target, l_ecLevel); + l_result = do_proc_test(l_workaround, + iv_nimbus_proc_target, + "nimbus", + false, //expected result of retryRequest + l_ecLevel + ); + } + while(0); + + if(l_result) + { + SCOM_DMI_WORKAROUND_TRACF("test_nimbus_proc_with_retry_addr: " + "Test Passed!"); + } + else + { + SCOM_DMI_WORKAROUND_TRACF("test_nimbus_proc_with_retry_addr: " + "Test Failed!"); + } + } + + //-------------------------------------------------------------------- + // The above tests were based upon addresses and targets. This test + // uses the other relevant parameters to the requestRetry method. + void test_other_args_for_false() + { + bool l_result{true}; + bool l_rc{false}; + + do + { + std::shared_ptr<const PostOpRetryCheck> + l_workaround(new DmiScomWorkaround_for_test); + + + if(not l_workaround) + { + FAIL_DMIWKRD_TEST("test_other_args_for_false: " + "Unable to create a " + "DmiScomWorkaround_for_test " + "object." + ); + + l_result = false; + break; + } + + std::shared_ptr<ErrlEntry> l_errl; + l_errl.reset(new ErrlEntry(ERRL_SEV_INFORMATIONAL, + ERRL_TEST_MOD_ID, + ERRL_TEST_REASON_CODE, + 0, + 0, + false + ) + ); + + if(not l_errl) + { + FAIL_DMIWKRD_TEST("test_other_args_for_false: " + "Unable to create ErrlEntry object." + ); + + l_result=false; + break; + } + + //TEST 1 + // + //CUMULUS Proc Target. + //ErrorEntry Valid. + //Address requires retry for CUMULUS dmi/proc targets. + // + //Expected Result: TRUE + // + //Ensures that the result is not effected by a valid + //errHndl_t parameter. + + // requestRetry parameters retry Conditions + // 1) errlHndl_t - Not NULL. + // 2) uint32_t i_retryCount - 0. + // 3) DeviceFW::OperationType - READ + // 4) TARGETING::Target* i_target - PROC + // 8) uint64_t i_addr - In Retry List. + l_rc = l_workaround->requestRetry(l_errl.get(), + 0, + DeviceFW::READ, + iv_cumulus_proc_target, + nullptr, + 0, + 0, + g_always_retry_addrs.front() + ); + + if(not l_rc) + { + FAIL_DMIWKRD_TEST("test_other_args_for_false: " + "requestRetry unexpectedly returned " + "false when called with a non-null " + "ErrlEntry pointer" + ); + + l_result=false; + break; + } + + //TEST 2 + // + //CUMULUS Proc Target + //Address requires retry for CUMULUS dmi/proc targets. + //Retry Count non-zero indicating a multiple + //retry request. + // + //Expected Result: FALSE + // + //Ensures that the result is false for a multiple retry request. + + // requestRetry parameters retry Conditions + // 1) errlHndl_t - NULL. + // 2) uint32_t i_retryCount - 1. <---- causes false return. + // 3) DeviceFW::OperationType - READ + // 4) TARGETING::Target* i_target - PROC + // 8) uint64_t i_addr - In Retry List. + l_rc = l_workaround->requestRetry(nullptr, + 1, + DeviceFW::READ, + iv_cumulus_proc_target, + nullptr, + 0, + 0, + g_always_retry_addrs.front() + ); + + if(l_rc) + { + FAIL_DMIWKRD_TEST("test_other_args_for_false: " + "requestRetry unexpectedly returned " + "true when called with a retry count " + "of 1." + ); + + l_result=false; + break; + } + + //TEST 3 + //Address requires retry for CUMULUS dmi/proc targets. + //CUMULUS Proc Target + // + //Operation was a WRITE. Workaround only enabled for READ. + // + //Expected Result: FALSE + // + //Ensures that the result is false for a write operation. + // + // requestRetry parameters retry Conditions + // 1) errlHndl_t - NULL. + // 2) uint32_t i_retryCount - 0. + // 3) DeviceFW::OperationType - WRITE <---- causes false return. + // 4) TARGETING::Target* i_target - PROC + // 8) uint64_t i_addr - In Retry List. + // + l_rc = l_workaround->requestRetry(nullptr, + 0, + DeviceFW::WRITE, + iv_cumulus_proc_target, + nullptr, + 0, + 0, + g_always_retry_addrs.front() + ); + + if(l_rc) + { + FAIL_DMIWKRD_TEST("test_other_args_for_false: " + "requestRetry unexpectedly returned " + "true when called with a " + "Write command. " + ); + + l_result=false; + break; + } + } + while(0); + + if(l_result) + { + SCOM_DMI_WORKAROUND_TRACF("test_other_args_for_false: " + "Test Passed!"); + } + else + { + SCOM_DMI_WORKAROUND_TRACF("test_other_args_for_false: " + "Test Failed!"); + } + } + +private: + + TARGETING::Target* iv_nimbus_proc_target{}; + TARGETING::Target* iv_cumulus_proc_target{}; + TARGETING::Target* iv_proc_target{}; + + void populateMockTargets() + { + //Encodings for mock targets + // 0x4000000000000000 DMI Target + // 0x8000000000000000 PROC Target + // 0x0200000000000000 NIMBUS + // 0x0100000000000000 CUMULUS + // 0x00000000000000XX Chip Unit + + uint64_t addr = 0x8200000000000010; + iv_nimbus_proc_target = reinterpret_cast<TARGETING::Target*>(addr); + + addr = 0x8100000000000010; + iv_cumulus_proc_target = reinterpret_cast<TARGETING::Target*>(addr); + + addr = 0x8000000000000010; + iv_proc_target = reinterpret_cast<TARGETING::Target*>(addr); + } + + //------------------------------------------------------------------------ + bool do_proc_test(std::shared_ptr<const PostOpRetryCheck>& i_workaround, + TARGETING::Target* i_target, + const char* i_model, + const bool i_expected, + const uint8_t i_eclevel + ) + { + bool l_result{true}; + bool l_rc{false}; + const char* l_oppositeExpString = i_expected?"false":"true"; + + do + { + //iterate through the complete list of retry addresses + for(uint64_t addr: g_always_retry_addrs) + { + + l_rc = i_workaround->requestRetry(nullptr, + 0, + DeviceFW::READ, + i_target, + nullptr, + 0, + 0, + addr + ); + if(i_expected != l_rc) + { + FAIL_DMIWKRD_TEST("test_%s_proc_with_retry_addr: " + "requestRetry unexpectedly " + "returned %s for a %s proc " + "target with EC Level 0x%0X " + "and address 0x%016llX", + i_model, + l_oppositeExpString, + i_model, + i_eclevel, + addr + ); + + l_result = false; + break; + } + } + } + while(0); + + return l_result; + } + + //---------------------------------------------------------------------- + TARGETING::Target* setTargetEcLevel(TARGETING::Target* i_target, + uint8_t i_ecLevel + ) + { + constexpr uint64_t ECLevelMask{0x00000000000000FF}; + + uint64_t l_targetAddr = reinterpret_cast<uint64_t>(i_target); + l_targetAddr &= ~ECLevelMask; + l_targetAddr |= (ECLevelMask & i_ecLevel); + + return reinterpret_cast<TARGETING::Target*>(l_targetAddr); + } + + //----------------------------------------------------------------------- + void getTargetECLevel(TARGETING::Target* i_target, + uint8_t& o_ecLevel) const + { + constexpr uint64_t ECLevelMask{0x00000000000000FF}; + + uint64_t l_targetAddr = reinterpret_cast<uint64_t>(i_target); + + const uint64_t l_ecLevel = l_targetAddr & ECLevelMask; + o_ecLevel = static_cast<uint8_t>(l_ecLevel); + } +}; + +#endif diff --git a/src/usr/scom/test/ibscom_retry_test.H b/src/usr/scom/test/ibscom_retry_test.H new file mode 100644 index 000000000..e265c305f --- /dev/null +++ b/src/usr/scom/test/ibscom_retry_test.H @@ -0,0 +1,281 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/test/ibscom_retry_test.H $ */ +/* */ +/* OpenPOWER HostBoot 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 */ +#ifndef __SCOM_IBSCOM_RETRY_TEST +#define __SCOM_IBSCOM_RETRY_TEST + +#include "../ibscom_retry.H" +#include <ibscom/ibscomreasoncodes.H> +#include <errl/errlreasoncodes.H> + +#include <cxxtest/TestSuite.H> +#include <trace/interface.H> + +// Tracing is disabled by default. +// To turn on tracing, build the tests as shown below: +// TRACE_SCOM_UNIT_TEST=1 make -j32 +#ifdef TRACE_SCOM_UNIT_TEST +extern trace_desc_t* g_trac_scom; +#define SCOM_IBSCOM_TRACF(printf_string,args...) \ + TRACFCOMP(g_trac_scom,"IbScomRetryTest::" printf_string,##args) +#else +#define SCOM_IBSCOM_TRACF(printf_string,args...) +#endif + +//Package the TS_FAIL macro with TRACFCOMP error reporting. +//The TS_FAIL macro output seems to be separated from +//TRACFCOMP output. This can be confusing when adding +//trace statements to the tests while debugging. The failure +//message from the SCOM_IBSCOM_TRACF macro will +//appear inline and in the proper context to other trace +//statements which may be added during debugging. +#define FAIL_IBSCOM_TEST(printf_string,args...) \ + SCOM_IBSCOM_TRACF(printf_string, ##args); \ + TS_FAIL("IbScomRetryTest::" printf_string, ##args) + +using namespace SCOM; +using namespace ERRORLOG; + +class IbScomRetryTest: public CxxTest::TestSuite +{ +public: + + //-------------------------------------------- + // The IbscomRetry workaround will request a + // retry if an error occurred with a result code + // of IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR. + // + // requestRetry parameters retry Conditions + // 1) errlHndl_t - Not Null and Reason Code is + // IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR + // 2) uint32_t i_retryCount - Must be 0. + // 3) DeviceFW::OperationType - Not Used + // 4) TARGETING::Target* i_target - Not Used + // 5) void* i_buffer - Not Used + // 6) size_t i_buflen - Not Used + // 7) int64_t i_accessType - Not Used + // 8) uint64_t i_addr - Not Used + // + void test_lbscom_retry() + { + bool l_result{true}; + + do + { + //Get the single IbscomRetry instance. + std::shared_ptr<const PostOpRetryCheck> l_wrkaround = + IbscomRetry::theInstance(); + + if(not l_wrkaround) + { + FAIL_IBSCOM_TEST("test_lbscom_retry: " + "IbscomRetry::theInstance returned a " + "nullptr!" + ); + + l_result = false; + break; + } + + uint16_t l_reasonCodeForTrue{IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR}; + uint16_t l_reasonCodeForFalse{ + static_cast<uint16_t>(l_reasonCodeForTrue + 1)}; + + uint32_t l_retryCount{0}; + std::shared_ptr<ErrlEntry> l_errl; + + // Test 1 + // Use a successful error entry (nullptr). + // + // 1) errlHndl_t - NULL <--- causes false result + // + // 2) uint32_t i_retryCount - 0. + // + // Expected return: FALSE. + // + bool l_retval = l_wrkaround->requestRetry(l_errl.get(), + l_retryCount, + DeviceFW::READ, + nullptr, + nullptr, + 0, + 0, + 0 + ); + if(l_retval) + { + FAIL_IBSCOM_TEST("test_lbscom_retry: " + "requestRetry unexpectedly returned true " + "for a nullptr errlHndl_t." + ); + + l_result = false; + break; + } + + l_errl.reset(new ErrlEntry(ERRL_SEV_INFORMATIONAL, + ERRL_TEST_MOD_ID, + l_reasonCodeForTrue, + 0, + 0, + false + ) + ); + + // Test 2 + // A non-nullptr error with reason code + // IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR and + // Retry Count equal to 0. + // + // 1) errlHndl_t - Not Null and Reason Code is + // IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR + // 2) uint32_t i_retryCount - 0. + // + // Expected result: TRUE + // + l_retval = l_wrkaround->requestRetry(l_errl.get(), + l_retryCount, + DeviceFW::READ, + nullptr, + nullptr, + 0, + 0, + 0 + ); + + if(not l_retval) + { + FAIL_IBSCOM_TEST("test_lbscom_retry: " + "requestRetry unexpectedly returned false " + "for reson code " + "IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR and retry " + "attempts %d.", + l_retryCount + ); + + l_result = false; + break; + } + + // Test 3 + // A non-nullptr error with reason code + // IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR and + // Retry Count equal to 1. + // + // 1) errlHndl_t - Not Null and Reason Code is + // IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR + // 2) uint32_t i_retryCount - 1 <--- Causes False Result + // + // Expected result: FALSE + // + ++l_retryCount; + l_retval = l_wrkaround->requestRetry(l_errl.get(), + l_retryCount, + DeviceFW::READ, + nullptr, + nullptr, + 0, + 0, + 0 + ); + + + if(l_retval) + { + FAIL_IBSCOM_TEST("test_lbscom_retry: " + "requestRetry unexpectedly returned true " + "for reson code " + "IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR and retry " + "attempts %d. The requestRetry should not " + "request more than one retry.", + l_retryCount + ); + + l_result = false; + break; + } + + l_retryCount = 0; + l_errl.reset(new ErrlEntry(ERRL_SEV_INFORMATIONAL, + ERRL_TEST_MOD_ID, + l_reasonCodeForFalse, + 0, + 0, + false + ) + ); + + // Test 4 + // A non-nullptr error with reason code NOT + // IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR and + // Retry Count equal to 0. + // + // 1) errlHndl_t - Not Null and Reason Code is NOT <-- Causes False + // IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR + // 2) uint32_t i_retryCount - 0. + // + // Expected result: FALSE + // + l_retval = l_wrkaround->requestRetry(l_errl.get(), + l_retryCount, + DeviceFW::READ, + nullptr, + nullptr, + 0, + 0, + 0 + ); + + if(l_retval) + { + FAIL_IBSCOM_TEST("test_lbscom_retry: " + "requestRetry unexpectedly returned true " + "for reson code NOT equal to " + "IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR. " + "A retry should only happen if the reason " + "code for the passed in error is equal to " + "IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR." + ); + + l_result = false; + break; + } + + } + while(0); + + if(l_result) + { + SCOM_IBSCOM_TRACF("IbScomRetryTest: Test Passed!"); + } + else + { + SCOM_IBSCOM_TRACF("IbScomRetryTest: Test Failed!"); + } + } +}; + + + +#endif diff --git a/src/usr/scom/test/makefile b/src/usr/scom/test/makefile index ce5b7777e..171d56e0b 100644 --- a/src/usr/scom/test/makefile +++ b/src/usr/scom/test/makefile @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2011,2014 +# Contributors Listed Below - COPYRIGHT 2011,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. @@ -25,4 +27,13 @@ ROOTPATH = ../../../.. MODULE = testscom TESTS = *.H +OBJS+=retryWorkaroundTestData.o + +#To enable tracing of SCOM Unit Tests +# TRACE_SCOM_UNIT_TEST=1 make -j32 +ifdef TRACE_SCOM_UNIT_TEST +CXXFLAGS+=-DTRACE_SCOM_UNIT_TEST +$(info Tracing Enabled For SCOM Unit Tests) +endif + include ${ROOTPATH}/config.mk diff --git a/src/usr/scom/test/postopchecks_test.H b/src/usr/scom/test/postopchecks_test.H new file mode 100644 index 000000000..13c93a8ca --- /dev/null +++ b/src/usr/scom/test/postopchecks_test.H @@ -0,0 +1,670 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/test/postopchecks_test.H $ */ +/* */ +/* OpenPOWER HostBoot 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 */ +#ifndef __SCOM_POSTOPCHECKS_TEST_H +#define __SCOM_POSTOPCHECKS_TEST_H + +#include "../DmiScomWorkaround.H" +#include "../ibscom_retry.H" +#include "../postopchecks.H" + +#include "retryWorkaroundTestData.H" + +#include <devicefw/userif.H> +#include <errl/errlreasoncodes.H> +#include <ibscom/ibscomreasoncodes.H> +#include <targeting/common/utilFilter.H> +#include <trace/interface.H> + +#include <cxxtest/TestSuite.H> + +//To enable tracing of SCOM Unit Tests +// TRACE_SCOM_UNIT_TEST=1 make -j32 +#ifdef TRACE_SCOM_UNIT_TEST +extern trace_desc_t* g_trac_scom; +#define __TRACE_USE_ONLY__ +#define SCOM_POSTOP_TRACF(printf_string,args...) \ + TRACFCOMP(g_trac_scom,"PostOPChecks_TEST::" printf_string,##args) +#else +#define __TRACE_USE_ONLY__ __attribute__((unused)) +#define SCOM_POSTOP_TRACF(printf_string,args...) +#endif + +//Package the TS_FAIL macro with TRACFCOMP error reporting. +//The TS_FAIL macro output seems to be separated from +//TRACFCOMP output. This can be confusing when adding +//trace statements to the tests while debugging. The failure +//message from the SCOM_POSTOP_TRACF macro will +//appear inline and in the proper context to other trace +//statements which may be added during debugging. +#define FAIL_POSTOP_TEST(printf_string,args...) \ + SCOM_POSTOP_TRACF(printf_string, ##args); \ + TS_FAIL("PostOPChecks_TEST::" printf_string, ##args) + +using namespace SCOM; +using namespace ERRORLOG; + +// PostOpChecks_for_test used for unit testing +// PostOpChecks. PostOpChecks_for_test allows us to +// insert test workarounds instead of the singleton which +// uses non-test workarounds. +class PostOpChecks_for_test: public PostOpChecks +{ +public: + PostOpChecks_for_test( + std::initializer_list<std::shared_ptr<const PostOpRetryCheck>> + i_retrychecks): PostOpChecks(i_retrychecks){} + + virtual ~PostOpChecks_for_test() = default; +}; + +//Create a publicly constructable version of IbscomRetry for testing. +class IbscomRetry_for_test: public IbscomRetry +{ +public: + IbscomRetry_for_test() = default; + virtual ~IbscomRetry_for_test() = default; +}; + +class PostOPChecks_TEST: public CxxTest::TestSuite +{ +public: + + //----------------------------------------- + // Test the PostOPChecks composite. + void test_postOpRetry() + { + bool l_result{true}; + bool l_rc{}; + + do + { + //Create a testable instance of IbscomRetry. + std::shared_ptr<const PostOpRetryCheck> + l_IbscomPtr{new IbscomRetry_for_test}; + + if(not l_IbscomPtr) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "IbscomRetry::theInstance returned a " + "nullptr!" + ); + + + l_result = false; + break; + } + + //Create a DmiScomWorkaround_for_test object + std::shared_ptr<const PostOpRetryCheck> + l_dmiptr(new DmiScomWorkaround_for_test); + + + if(not l_dmiptr) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "Unable to create a " + "DmiScomWorkaround_for_test " + "object." + ); + + l_result = false; + break; + } + + //Create PostOpChecks_for_test object + std::shared_ptr<const PostOpRetryCheck> + l_postopcheck(new PostOpChecks_for_test{ + l_IbscomPtr, + l_dmiptr + }); + + if(not l_postopcheck) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "Unable to create a " + "PostOpChecks_for_test " + "object." + ); + + l_result = false; + break; + } + + //initialize and check retry counts. Retry counts are used + //to determine which workaround requested a retry. + uint64_t l_total_retry_count{}; + uint64_t l_ibscom_retry_count{}; + uint64_t l_dmi_retry_count{}; + uint64_t l_no_retry_addr{0x22334455}; //Address that does not + //need a retry. + uint16_t l_reasonCodeForTrue{IBSCOM::IBSCOM_RETRY_DUE_TO_ERROR}; + uint32_t l_retryCount{0}; + + l_postopcheck->resetRetryCount(); + l_total_retry_count = l_postopcheck->getRetryCount(); + l_ibscom_retry_count = l_IbscomPtr->getRetryCount(); + l_dmi_retry_count = l_dmiptr->getRetryCount(); + + l_rc = checkExpectedRetryCounts("Pre Test", + l_total_retry_count, + l_ibscom_retry_count, + l_dmi_retry_count, + 0, + 0, + 0 + ); + + if(not l_rc) + { + l_result = false; + break; + } + + //Setup errlHndl_t pointer + std::shared_ptr<ErrlEntry> l_errl; + l_errl.reset(new ErrlEntry(ERRL_SEV_INFORMATIONAL, + ERRL_TEST_MOD_ID, + l_reasonCodeForTrue, + 0, + 0, + false + ) + ); + + if(not l_errl) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "Unable to create a ErrlEntry object." + ); + + l_result = false; + break; + } + + //Test 1 + // + // Ensure that the PostOpRetry composite returns false when + // its contained children return false. + // + // No Errl pointer - IBSCOM will not request retry. + // Address not in the list of addresses that require a DMI retry. + // - DmiWorkaround will not request retry. + // + //Expected Result: FALSE + // + l_rc = l_postopcheck->requestRetry(nullptr, + l_retryCount, + DeviceFW::READ, + iv_cumulus_proc_target, + nullptr, + 0, + 0, + l_no_retry_addr + ); + + if(l_rc) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "requestRetry unexpectedly returned true " + "for a cumulus proc target, null " + "errlHndl_t pointer and address 0x%016X", + l_no_retry_addr + ); + + l_result = false; + break; + } + + l_total_retry_count = l_postopcheck->getRetryCount(); + l_ibscom_retry_count = l_IbscomPtr->getRetryCount(); + l_dmi_retry_count = l_dmiptr->getRetryCount(); + + l_rc = checkExpectedRetryCounts("Test 1", + l_total_retry_count, + l_ibscom_retry_count, + l_dmi_retry_count, + 0, + 0, + 0 + ); + + if(not l_rc) + { + l_result = false; + break; + } + + //============================================= + // IBSCOM Retry test(s) + //============================================= + + //Test 2 + // + // Ensure that the PostOpRetry composite returns true when the + // contained IbscomRetry instance requests a retry and that + // the retry counts for both the children and composite are as + // expected. + // + // Errl pointer should trigger IBSCOM Retry. + // Address not in the list of addresses that require a DMI retry. + // - DmiWorkaround will not request retry. + // + //Expected Result: TRUE. + // + l_rc = l_postopcheck->requestRetry(l_errl.get(), + l_retryCount, + DeviceFW::READ, + iv_cumulus_proc_target, + nullptr, + 0, + 0, + l_no_retry_addr + ); + + if(not l_rc) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "requestRetry unexpectedly returned false " + "for a cumulus proc target, valid " + "errlHndl_t pointer and address 0x%016X", + l_no_retry_addr + ); + + l_result = false; + break; + } + + l_total_retry_count = l_postopcheck->getRetryCount(); + l_ibscom_retry_count = l_IbscomPtr->getRetryCount(); + l_dmi_retry_count = l_dmiptr->getRetryCount(); + + l_rc = checkExpectedRetryCounts("Test 2", + l_total_retry_count, + l_ibscom_retry_count, + l_dmi_retry_count, + 1, //total expected + 1, //ibscom expected + 0 //dmi retry expected + ); + + if(not l_rc) + { + l_result = false; + break; + } + + //============================================= + // DMI Retry test(s) + //============================================ + + //Test 3 + // + // Ensure that the PostOpRetry composite returns true when the + // contained DmiScomWorkaround instance requests a retry and that + // the retry counts for both the children and composite are as + // expected. + // + // Errl pointer is NULL and should not trigger a IBSCOM Retry. + // Address is in the list of addresses that require a DMI retry. + // - DmiWorkaround will request a retry. + // Expected Result: TRUE. + // + l_rc = l_postopcheck->requestRetry(nullptr, + l_retryCount, + DeviceFW::READ, + iv_cumulus_proc_target, + nullptr, + 0, + 0, + g_always_retry_addrs.front() + ); + if(not l_rc) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "requestRetry unexpectedly returned false " + "for a cumulus proc target, null " + "errlHndl_t pointer and address 0x%016X", + g_always_retry_addrs.front() + ); + + l_result = false; + break; + } + + l_total_retry_count = l_postopcheck->getRetryCount(); + l_ibscom_retry_count = l_IbscomPtr->getRetryCount(); + l_dmi_retry_count = l_dmiptr->getRetryCount(); + + l_rc = checkExpectedRetryCounts("Test 3", + l_total_retry_count, + l_ibscom_retry_count, + l_dmi_retry_count, + 2, //total expected + 1, //ibscom expected + 1 //dmi retry expected + ); + if(not l_rc) + { + l_result = false; + break; + } + } + while(0); + + if(l_result) + { + SCOM_POSTOP_TRACF("test_postOpRetry: Test Passed!"); + } + else + { + SCOM_POSTOP_TRACF("test_postOpRetry: Test Failed!"); + } + } + + //----------------------------------------------------------- + // Integration test for Scom workarounds + void test_scom_workaround_integration_test() + { + populateRealTargets(); + bool l_result{true}; + + do + { + //integration test valid on CUMULUS system only + if(TARGETING::MODEL_CUMULUS != iv_model) + { + __TRACE_USE_ONLY__ const char* model_name = ""; + if(TARGETING::MODEL_NIMBUS == iv_model) + { + model_name = "NIMBUS"; + } + + SCOM_POSTOP_TRACF("test_integration_test: " + "Not a Cumulus system. " + "Model: %s, " + "Aborting integration test.", + model_name + ); + + break; + } + else if(0x00 != iv_ecLevel && 0x10 != iv_ecLevel) + { + SCOM_POSTOP_TRACF("test_integration_test: " + "EC Level not valid for Test" + "EC Level: 0x%0x, " + "Aborting integration test.", + iv_ecLevel + ); + break; + } + else + { + SCOM_POSTOP_TRACF("test_scom_workaround_integration_test: " + "CUMULUS System Detected." + ); + } + + //Ensure that we have a real target for testing. + if(nullptr == iv_proc_target) + { + FAIL_POSTOP_TEST("test_scom_workaround_integration_test: " + "No Targets for test were found!" + ); + + l_result = false; + break; + } + + const PostOpChecks* l_postopptr = PostOpChecks::theInstance(); + if(nullptr == l_postopptr) + { + FAIL_POSTOP_TEST("test_scom_workaround_integration_test: " + "PostOpChecks::theInstance " + "returned a nullptr!" + ); + + l_result = false; + break; + } + + l_postopptr->resetRetryCount(); + + //STEP 1 + // + //Test Workarounds on Proc Targets + // + //Integration Test of Proc target and all + //retry addresses. + // + //TEST strategy. Iterate through all retry addresses and + //perform a deviceRead on that address. The retry count + //for the DmiScomWorkaround should increment for each retry. + // + if(iv_proc_target) + { + uint64_t l_retryCount{0}; + uint64_t l_expected_retryCount{0}; + + //iterate over all retry addresses + for(uint64_t l_addr: g_always_retry_addrs) + { + uint64_t l_buffer{0}; + size_t l_bufsize = sizeof(uint64_t); + l_expected_retryCount = l_postopptr->getRetryCount(); + errlHndl_t l_errl = DeviceFW::deviceRead( + iv_proc_target, + &l_buffer, + l_bufsize, + DEVICE_SCOM_ADDRESS(l_addr) + ); + if(l_errl) + { + delete l_errl; + l_errl = nullptr; + SCOM_POSTOP_TRACF( + "test_scom_workaround_integration_test: " + "Failed to read address " + "0x%016llX for processor target.", + l_addr + ); + } + else + { + //read succeeded, check that a retry occurred. + ++l_expected_retryCount; + l_retryCount = l_postopptr->getRetryCount(); + + //Because tests are run concurrently we cannot + //use equality to check the retry count. A test + //running in another thread may have read a + //register that requires a retry and thus bump + //the retry count up in addition to this test. + if(l_expected_retryCount > l_retryCount) + { + FAIL_POSTOP_TEST( + "test_scom_workaround_integration_test: " + "retry count not as expected. " + "Expected %d, Actual %d. " + "Target - Proc. Addr: 0x%016llX", + l_expected_retryCount, + l_retryCount, + l_addr + ); + + l_result = false; + break; + } + } + } + + if(not l_result) + { + break; + } + } + } + while(0); + + if(l_result) + { + SCOM_POSTOP_TRACF("test_scom_workaround_integration_test: " + "Test Passed!"); + } + else + { + SCOM_POSTOP_TRACF("test_scom_workaround_integration_test: " + "Test Failed!"); + } + } + +private: + + //Mock target, cumulus proc target. + const uint64_t iv_proc_addr{0x8100000000000010}; + + TARGETING::Target* + iv_cumulus_proc_target{reinterpret_cast<TARGETING::Target*>(iv_proc_addr)}; + + //Real Target + TARGETING::Target* iv_proc_target{}; + + TARGETING::MODEL iv_model{TARGETING::MODEL_NA}; + uint8_t iv_ecLevel{0xFF}; + + //------------------------------------------------------------------------- + bool checkExpectedRetryCounts( + const char* i_test, + uint64_t i_total, + uint64_t i_ibscom, + uint64_t i_dmi, + uint64_t i_expected_total, + uint64_t i_expected_ibscom, + uint64_t i_expected_dmi, + bool i_exactMatch = true + ) + { + bool l_result{true}; + + do + { + // For integration tests an exact match is not desirable + // because tests are run concurrently and retry counts + // may be influenced by tests running on other threads. + // For Unit Tests we use dedicated derived test classes + // whose retry count is unaffected by other tests. + if((i_exactMatch && (i_expected_total != i_total)) || + (!i_exactMatch && (i_expected_total > i_total)) + ) + { + + FAIL_POSTOP_TEST("test_postOpRetry: " + "Unexpected retry count for l_postopcheck. " + "Test: %s, Actual %d. Expected %d", + i_test, + i_total, + i_expected_total + ); + + l_result = false; + break; + } + else if((i_exactMatch && (i_expected_ibscom != i_ibscom)) || + (!i_exactMatch && (i_expected_ibscom > i_ibscom)) + ) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "Unexpected retry count for l_IbscomPtr. " + "Test: %s, Actual %d. Expected %d", + i_test, + i_ibscom, + i_expected_ibscom + ); + + l_result = false; + break; + } + else if((i_exactMatch && (i_expected_dmi != i_dmi)) || + (!i_exactMatch && (i_expected_dmi > i_dmi)) + ) + { + FAIL_POSTOP_TEST("test_postOpRetry: " + "Unexpected retry count for l_dmiptr. " + "Test: %s, Actual %d. Expected %d", + i_test, + i_dmi, + i_expected_dmi + ); + + l_result = false; + break; + } + } + while(0); + + return l_result; + } + + //------------------------------------------------------ + void populateRealTargets() + { + do + { + iv_ecLevel = 0xFF; + iv_model = TARGETING::MODEL_NA; + iv_proc_target = nullptr; + + uint8_t l_ecLevel{}; + + TARGETING::TargetHandleList l_targetList; + TARGETING::getAllChips(l_targetList, TARGETING::TYPE_PROC, false); + + for(int i=0; l_targetList.size(); ++i) + { + TARGETING::Target* l_target = l_targetList[i]; + if(nullptr != l_target && + TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL != l_target) + { + iv_proc_target = l_target; + break; + } + } + + if(nullptr != iv_proc_target) + { + if(iv_proc_target->tryGetAttr<TARGETING::ATTR_EC>(l_ecLevel)) + { + iv_ecLevel = l_ecLevel; + } + + iv_proc_target->tryGetAttr<TARGETING::ATTR_MODEL>(iv_model); + } + } + while(0); + } + +}; + +#endif diff --git a/src/usr/scom/test/retryWorkaroundTestData.C b/src/usr/scom/test/retryWorkaroundTestData.C new file mode 100644 index 000000000..ef8462d8d --- /dev/null +++ b/src/usr/scom/test/retryWorkaroundTestData.C @@ -0,0 +1,188 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/test/retryWorkaroundTestData.C $ */ +/* */ +/* OpenPOWER HostBoot 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 */ +#include "retryWorkaroundTestData.H" + +// A set of addresses that never require a SCOM DMI retry +std::vector<uint64_t> g_always_no_retry_addrs = { + 0x1319821, + 0x1319822, + 0x1319921, + 0x1319922, + 0x1319a21, + 0x1319a22, + 0x1319b21, + 0x1319b22, + + 0xF319821, + 0xF319822, + 0xF319921, + 0xF319922, + 0xF319a21, + 0xF319a22, + 0xF319b21, + 0xF319b22, + + 0x40108a3, + 0x40108a4, + 0x40108a5, + 0x40108a6, + 0x40108a7, + 0x40108a8, + 0x40108a9, + 0x40108aa, + + 0x3010820, + 0x3010821, + 0x3010822, + 0x301082b, + 0x301082c, + 0x301082d, + 0x301082e, + 0x301082f, + + 0x3010830, + 0x3010831, + 0x3010832, + 0x301083b, + 0x301083c, + 0x301083d, + 0x301083e, + 0x301083f, + + 0x30108a0, + 0x30108a1, + 0x30108a2, + 0x30108ab, + 0x30108ac, + 0x30108ad, + 0x30108ae, + 0x30108af, + + 0x30108b0, + 0x30108b1, + 0x30108b2, + 0x30108bb, + 0x30108bc, + 0x30108bd, + 0x30108be, + 0x30108bf, + + 0x3010803, + 0x3010813, + 0x3010843, + 0x3010853, + 0x3010863, + 0x3010873, + 0x3010883, + 0x3010893, + 0x30108c3, + 0x30108d3, + 0x30108e3, + 0x30108f3, + }; + +//All of the following addresses require retries +std::vector<uint64_t> g_always_retry_addrs = + { + //dmi-4 + 0x3010823, + 0x3010824, + 0x3010825, + 0x3010826, + 0x3010827, + 0x3010828, + 0x3010829, + 0x301082a, + + //dmi-5 + 0x3010833, + 0x3010834, + 0x3010835, + 0x3010836, + 0x3010837, + 0x3010838, + 0x3010839, + 0x301083a, + + //dmi-6 + 0x30108a3, + 0x30108a4, + 0x30108a5, + 0x30108a6, + 0x30108a7, + 0x30108a8, + 0x30108a9, + 0x30108aa, + + //dmi-7 + 0x30108b3, + 0x30108b4, + 0x30108b5, + 0x30108b6, + 0x30108b7, + 0x30108b8, + 0x30108b9, + 0x30108ba, + + //dmi-0 + 0x5010823, + 0x5010824, + 0x5010825, + 0x5010826, + 0x5010827, + 0x5010828, + 0x5010829, + 0x501082a, + + //dmi-1 + 0x5010833, + 0x5010834, + 0x5010835, + 0x5010836, + 0x5010837, + 0x5010838, + 0x5010839, + 0x501083a, + + //dmi-2 + 0x50108a3, + 0x50108a4, + 0x50108a5, + 0x50108a6, + 0x50108a7, + 0x50108a8, + 0x50108a9, + 0x50108aa, + + //dmi-3 + 0x50108b3, + 0x50108b4, + 0x50108b5, + 0x50108b6, + 0x50108b7, + 0x50108b8, + 0x50108b9, + 0x50108ba + }; diff --git a/src/usr/scom/test/retryWorkaroundTestData.H b/src/usr/scom/test/retryWorkaroundTestData.H new file mode 100644 index 000000000..211471a62 --- /dev/null +++ b/src/usr/scom/test/retryWorkaroundTestData.H @@ -0,0 +1,35 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/test/retryWorkaroundTestData.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] Google Inc. */ +/* [+] 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 __SCOM_RETRY_WORKAROUND_TEST_DATA +#define __SCOM_RETRY_WORKAROUND_TEST_DATA + +#include <stdint.h> +#include <vector> + +extern std::vector<uint64_t> g_always_no_retry_addrs; +extern std::vector<uint64_t> g_always_retry_addrs; + +#endif |