Add simulated SCOM/CFAM read support for test
Change-Id: I615f1819cd309528735d63f2e6e4b4181c58fd34
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/test/meson.build b/test/meson.build
index 8a17b52..911b709 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -116,6 +116,7 @@
files(
tc + '.cpp',
'../util/pdbg.cpp',
+ 'pdbg-sim-only.cpp',
),
pdbg_test_dtb,
]
@@ -166,6 +167,7 @@
'../analyzer/resolution.cpp',
'../analyzer/service_data.cpp',
'../util/pdbg.cpp',
+ 'pdbg-sim-only.cpp',
),
pdbg_test_dtb,
]
@@ -189,6 +191,7 @@
'../analyzer/plugins/p10-tod-plugins.cpp',
'../analyzer/service_data.cpp',
'../util/pdbg.cpp',
+ 'pdbg-sim-only.cpp',
),
pdbg_test_dtb,
]
diff --git a/test/pdbg-sim-only.cpp b/test/pdbg-sim-only.cpp
index efeee51..2e81fe5 100644
--- a/test/pdbg-sim-only.cpp
+++ b/test/pdbg-sim-only.cpp
@@ -8,6 +8,7 @@
#include <assert.h>
+#include <test/sim-hw-access.hpp>
#include <util/pdbg.hpp>
#include <util/trace.hpp>
@@ -22,6 +23,8 @@
namespace pdbg
{
+//------------------------------------------------------------------------------
+
// This is the simulated version of this function.
bool queryLpcTimeout(pdbg_target* target)
{
@@ -32,5 +35,44 @@
return g_lpcTimeout;
}
+//------------------------------------------------------------------------------
+
+int getScom(pdbg_target* i_target, uint64_t i_addr, uint64_t& o_val)
+{
+ assert(nullptr != i_target);
+ assert(TYPE_PROC == getTrgtType(i_target) ||
+ TYPE_OCMB == getTrgtType(i_target));
+
+ int rc = sim::ScomAccess::getSingleton().get(i_target, i_addr, o_val);
+
+ if (0 != rc)
+ {
+ trace::err("SCOM read failure: target=%s addr=0x%0" PRIx64,
+ getPath(i_target), i_addr);
+ }
+
+ return rc;
+}
+
+//------------------------------------------------------------------------------
+
+int getCfam(pdbg_target* i_target, uint32_t i_addr, uint32_t& o_val)
+{
+ assert(nullptr != i_target);
+ assert(TYPE_PROC == getTrgtType(i_target));
+
+ int rc = sim::CfamAccess::getSingleton().get(i_target, i_addr, o_val);
+
+ if (0 != rc)
+ {
+ trace::err("CFAM read failure: target=%s addr=0x%08x",
+ getPath(i_target), i_addr);
+ }
+
+ return rc;
+}
+
+//------------------------------------------------------------------------------
+
} // namespace pdbg
} // namespace util
diff --git a/test/sim-hw-access.hpp b/test/sim-hw-access.hpp
new file mode 100644
index 0000000..6bc7a30
--- /dev/null
+++ b/test/sim-hw-access.hpp
@@ -0,0 +1,190 @@
+#include <assert.h>
+
+#include <util/pdbg.hpp>
+
+#include <map>
+
+namespace sim
+{
+
+class ScomAccess
+{
+ private:
+ /** @brief Default constructor. */
+ ScomAccess() = default;
+
+ /** @brief Destructor. */
+ ~ScomAccess() = default;
+
+ /** @brief Copy constructor. */
+ ScomAccess(const ScomAccess&) = delete;
+
+ /** @brief Assignment operator. */
+ ScomAccess& operator=(const ScomAccess&) = delete;
+
+ public:
+ /** @brief Provides access to a singleton instance of this object. */
+ static ScomAccess& getSingleton()
+ {
+ static ScomAccess theScomAccess;
+ return theScomAccess;
+ }
+
+ private:
+ /** The SCOM values for each chip and address. */
+ std::map<pdbg_target*, std::map<uint64_t, uint64_t>> iv_values;
+
+ /** All addresses that will return a SCOM error. */
+ std::map<pdbg_target*, std::map<uint64_t, bool>> iv_errors;
+
+ public:
+ /**
+ * @brief Stores a SCOM register value, which can be accessed later in test.
+ * @param i_target The target chip.
+ * @param i_addr A SCOM address on the given chip.
+ * @param i_val The value of the given address.
+ */
+ void add(pdbg_target* i_target, uint64_t i_addr, uint64_t i_val)
+ {
+ assert(nullptr != i_target);
+
+ iv_values[i_target][i_addr] = i_val;
+ }
+
+ /**
+ * @brief This can be used to specify if a specific SCOM address will return
+ * an error when accessed. This is useful for error path testing.
+ * @param i_target The target chip.
+ * @param i_addr A SCOM address on the given chip.
+ */
+ void error(pdbg_target* i_target, uint64_t i_addr)
+ {
+ assert(nullptr != i_target);
+
+ iv_errors[i_target][i_addr] = true;
+ }
+
+ /**
+ * @brief Clears all SCOM value/error data.
+ */
+ void flush()
+ {
+ iv_values.clear();
+ iv_errors.clear();
+ }
+
+ /**
+ * @brief Returns the stored SCOM register value.
+ * @param i_target The target chip.
+ * @param i_addr A SCOM address on the given chip.
+ * @param o_val The value of the given address. If the target address
+ * does not exist in iv_values, a value of 0 is returned.
+ * @return Will return 1 if the target address exists in iv_errors.
+ * Otherwise, will return 0 for a successful SCOM access.
+ */
+ int get(pdbg_target* i_target, uint64_t i_addr, uint64_t& o_val)
+ {
+ assert(nullptr != i_target);
+
+ if (iv_errors[i_target][i_addr])
+ {
+ return 1;
+ }
+
+ o_val = iv_values[i_target][i_addr];
+
+ return 0;
+ }
+};
+
+class CfamAccess
+{
+ private:
+ /** @brief Default constructor. */
+ CfamAccess() = default;
+
+ /** @brief Destructor. */
+ ~CfamAccess() = default;
+
+ /** @brief Copy constructor. */
+ CfamAccess(const CfamAccess&) = delete;
+
+ /** @brief Assignment operator. */
+ CfamAccess& operator=(const CfamAccess&) = delete;
+
+ public:
+ /** @brief Provides access to a singleton instance of this object. */
+ static CfamAccess& getSingleton()
+ {
+ static CfamAccess theCfamAccess;
+ return theCfamAccess;
+ }
+
+ private:
+ /** The CFAM values for each chip and address. */
+ std::map<pdbg_target*, std::map<uint32_t, uint32_t>> iv_values;
+
+ /** All addresses that will return a CFAM error. */
+ std::map<pdbg_target*, std::map<uint32_t, bool>> iv_errors;
+
+ public:
+ /**
+ * @brief Stores a CFAM register value, which can be accessed later in test.
+ * @param i_target The target chip.
+ * @param i_addr A CFAM address on the given chip.
+ * @param i_val The value of the given address.
+ */
+ void add(pdbg_target* i_target, uint32_t i_addr, uint32_t i_val)
+ {
+ assert(nullptr != i_target);
+
+ iv_values[i_target][i_addr] = i_val;
+ }
+
+ /**
+ * @brief This can be used to specify if a specific CFAM address will return
+ * an error when accessed. This is useful for error path testing.
+ * @param i_target The target chip.
+ * @param i_addr A CFAM address on the given chip.
+ */
+ void error(pdbg_target* i_target, uint32_t i_addr)
+ {
+ assert(nullptr != i_target);
+
+ iv_errors[i_target][i_addr] = true;
+ }
+
+ /**
+ * @brief Clears all CFAM value/error data.
+ */
+ void flush()
+ {
+ iv_values.clear();
+ iv_errors.clear();
+ }
+
+ /**
+ * @brief Returns the stored CFAM register value.
+ * @param i_target The target chip.
+ * @param i_addr A CFAM address on the given chip.
+ * @param o_val The value of the given address. If the target address
+ * does not exist in iv_values, a value of 0 is returned.
+ * @return Will return 1 if the target address exists in iv_errors.
+ * Otherwise, will return 0 for a successful CFAM access.
+ */
+ int get(pdbg_target* i_target, uint32_t i_addr, uint32_t& o_val)
+ {
+ assert(nullptr != i_target);
+
+ if (iv_errors[i_target][i_addr])
+ {
+ return 1;
+ }
+
+ o_val = iv_values[i_target][i_addr];
+
+ return 0;
+ }
+};
+
+} // namespace sim
diff --git a/test/test-pdbg-dts.cpp b/test/test-pdbg-dts.cpp
index 1e5075c..9fd49fd 100644
--- a/test/test-pdbg-dts.cpp
+++ b/test/test-pdbg-dts.cpp
@@ -1,5 +1,6 @@
#include <fcntl.h>
+#include <test/sim-hw-access.hpp>
#include <util/pdbg.hpp>
#include <util/trace.hpp>
@@ -161,3 +162,72 @@
EXPECT_EQ(memPortUnit,
getChipUnit(ocmbChip, TYPE_MEM_PORT, memPortUnitPos));
}
+
+TEST(util_pdbg, getScom)
+{
+ using namespace util::pdbg;
+ pdbg_targets_init(nullptr);
+
+ auto procChip = getTrgt("/proc0");
+ auto ocmbChip = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1/ocmb0");
+ auto omiUnit = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1");
+
+ sim::ScomAccess& scom = sim::ScomAccess::getSingleton();
+ scom.flush();
+ scom.add(procChip, 0x11111111, 0x0011223344556677);
+ scom.error(ocmbChip, 0x22222222);
+
+ int rc = 0;
+ uint64_t val = 0;
+
+ // Test good path.
+ rc = getScom(procChip, 0x11111111, val);
+ EXPECT_EQ(0, rc);
+ EXPECT_EQ(0x0011223344556677, val);
+
+ // Test address that has not been added to ScomAccess.
+ rc = getScom(procChip, 0x33333333, val);
+ EXPECT_EQ(0, rc);
+ EXPECT_EQ(0, val);
+
+ // Test SCOM error.
+ rc = getScom(ocmbChip, 0x22222222, val);
+ EXPECT_EQ(1, rc);
+
+ // Test non-chip target.
+ EXPECT_DEATH({ getScom(omiUnit, 0x11111111, val); }, "");
+}
+
+TEST(util_pdbg, getCfam)
+{
+ using namespace util::pdbg;
+ pdbg_targets_init(nullptr);
+
+ auto procChip = getTrgt("/proc0");
+ auto omiUnit = getTrgt("/proc0/pib/perv13/mc1/mi0/mcc0/omi1");
+
+ sim::CfamAccess& cfam = sim::CfamAccess::getSingleton();
+ cfam.flush();
+ cfam.add(procChip, 0x11111111, 0x00112233);
+ cfam.error(procChip, 0x22222222);
+
+ int rc = 0;
+ uint32_t val = 0;
+
+ // Test good path.
+ rc = getCfam(procChip, 0x11111111, val);
+ EXPECT_EQ(0, rc);
+ EXPECT_EQ(0x00112233, val);
+
+ // Test address that has not been added to CfamAccess.
+ rc = getCfam(procChip, 0x33333333, val);
+ EXPECT_EQ(0, rc);
+ EXPECT_EQ(0, val);
+
+ // Test CFAM error.
+ rc = getCfam(procChip, 0x22222222, val);
+ EXPECT_EQ(1, rc);
+
+ // Test non-chip target.
+ EXPECT_DEATH({ getCfam(omiUnit, 0x11111111, val); }, "");
+}
diff --git a/util/pdbg-no-sim.cpp b/util/pdbg-no-sim.cpp
index 8237052..87b49cf 100644
--- a/util/pdbg-no-sim.cpp
+++ b/util/pdbg-no-sim.cpp
@@ -44,6 +44,57 @@
//------------------------------------------------------------------------------
+int getScom(pdbg_target* i_target, uint64_t i_addr, uint64_t& o_val)
+{
+ assert(nullptr != i_target);
+
+ int rc = 0;
+
+ auto targetType = getTrgtType(i_target);
+
+ if (TYPE_PROC == targetType)
+ {
+ rc = pib_read(getPibTrgt(i_target), i_addr, &o_val);
+ }
+ else if (TYPE_OCMB == targetType)
+ {
+ rc = ocmb_getscom(i_target, i_addr, &o_val);
+ }
+ else
+ {
+ throw std::logic_error("Invalid type for SCOM operation: target=" +
+ std::string{getPath(i_target)});
+ }
+
+ if (0 != rc)
+ {
+ trace::err("SCOM read failure: target=%s addr=0x%0" PRIx64,
+ getPath(i_target), i_addr);
+ }
+
+ return rc;
+}
+
+//------------------------------------------------------------------------------
+
+int getCfam(pdbg_target* i_target, uint32_t i_addr, uint32_t& o_val)
+{
+ assert(nullptr != i_target);
+ assert(TYPE_PROC == getTrgtType(i_target));
+
+ int rc = fsi_read(getFsiTrgt(i_target), i_addr, &o_val);
+
+ if (0 != rc)
+ {
+ trace::err("CFAM read failure: target=%s addr=0x%08x",
+ getPath(i_target), i_addr);
+ }
+
+ return rc;
+}
+
+//------------------------------------------------------------------------------
+
} // namespace pdbg
} // namespace util
diff --git a/util/pdbg.cpp b/util/pdbg.cpp
index 381e6fe..10f3b73 100644
--- a/util/pdbg.cpp
+++ b/util/pdbg.cpp
@@ -308,47 +308,6 @@
//------------------------------------------------------------------------------
-int getScom(pdbg_target* i_trgt, uint64_t i_addr, uint64_t& o_val)
-{
- // Only processor targets are supported.
- // TODO: Will need to add OCMB support later.
- assert(TYPE_PROC == getTrgtType(i_trgt));
-
- auto pibTrgt = util::pdbg::getPibTrgt(i_trgt);
-
- int rc = pib_read(pibTrgt, i_addr, &o_val);
-
- if (0 != rc)
- {
- trace::err("pib_read failure: target=%s addr=0x%0" PRIx64,
- util::pdbg::getPath(pibTrgt), i_addr);
- }
-
- return rc;
-}
-
-//------------------------------------------------------------------------------
-
-int getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val)
-{
- // Only processor targets are supported.
- assert(TYPE_PROC == getTrgtType(i_trgt));
-
- auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt);
-
- int rc = fsi_read(fsiTrgt, i_addr, &o_val);
-
- if (0 != rc)
- {
- trace::err("fsi_read failure: target=%s addr=0x%08x",
- util::pdbg::getPath(fsiTrgt), i_addr);
- }
-
- return rc;
-}
-
-//------------------------------------------------------------------------------
-
// IMPORTANT:
// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some
// point during the IPL. It is possible that this information is needed before