Add support for TOD clock callouts

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: I42726f6d1b036120fcfe217e6dd47be8dd6d927b
diff --git a/analyzer/callout.hpp b/analyzer/callout.hpp
index b4f7912..0ec3241 100644
--- a/analyzer/callout.hpp
+++ b/analyzer/callout.hpp
@@ -158,6 +158,9 @@
     /** Oscillator reference clock 1. */
     static const ClockType OSC_REF_CLOCK_1;
 
+    /** Time of Day (TOD) clock. */
+    static const ClockType TOD_CLOCK;
+
   private:
     /**
      * @brief Constructor from components.
@@ -180,6 +183,7 @@
 
 inline const ClockType ClockType::OSC_REF_CLOCK_0{"OSC_REF_CLOCK_0"};
 inline const ClockType ClockType::OSC_REF_CLOCK_1{"OSC_REF_CLOCK_1"};
+inline const ClockType ClockType::TOD_CLOCK{"TOD_CLOCK"};
 
 /** @brief Container class for part callout service actions. */
 class PartType
diff --git a/analyzer/meson.build b/analyzer/meson.build
index 3cf063e..c849130 100644
--- a/analyzer/meson.build
+++ b/analyzer/meson.build
@@ -12,6 +12,7 @@
 
 plugins_src = files(
     'plugins/p10-plugins.cpp',
+    'plugins/p10-tod-plugins.cpp',
 )
 
 # Library dependencies.
diff --git a/analyzer/plugins/p10-plugins.cpp b/analyzer/plugins/p10-plugins.cpp
index 3e61135..a3ac1ca 100644
--- a/analyzer/plugins/p10-plugins.cpp
+++ b/analyzer/plugins/p10-plugins.cpp
@@ -108,14 +108,6 @@
     }
 }
 
-/**
- * @brief Handles TOD step check fault attentions.
- */
-void tod_step_check_fault(unsigned int, const libhei::Chip&, ServiceData&)
-{
-    // TODO
-}
-
 } // namespace P10
 
 PLUGIN_DEFINE_NS(P10_10, P10, pll_unlock);
@@ -124,7 +116,4 @@
 PLUGIN_DEFINE_NS(P10_10, P10, lpc_timeout);
 PLUGIN_DEFINE_NS(P10_20, P10, lpc_timeout);
 
-PLUGIN_DEFINE_NS(P10_10, P10, tod_step_check_fault);
-PLUGIN_DEFINE_NS(P10_20, P10, tod_step_check_fault);
-
 } // namespace analyzer
diff --git a/analyzer/plugins/p10-tod-plugins.cpp b/analyzer/plugins/p10-tod-plugins.cpp
new file mode 100644
index 0000000..84a8cfe
--- /dev/null
+++ b/analyzer/plugins/p10-tod-plugins.cpp
@@ -0,0 +1,34 @@
+
+#include <analyzer/plugins/plugin.hpp>
+#include <util/pdbg.hpp>
+#include <util/trace.hpp>
+
+namespace analyzer
+{
+
+namespace P10
+{
+
+/**
+ * @brief Handles TOD step check fault attentions.
+ */
+void tod_step_check_fault(unsigned int, const libhei::Chip& i_chip,
+                          ServiceData& io_servData)
+{
+    // TODO: The TOD step check fault analysis is complicated. It requires
+    //       analysis of multiple status registers on all processors in the
+    //       system. Until that support is available, call out the TOD clock and
+    //       the processor reporting the attention.
+    trace::err("Warning: TOD step check fault handling not fully supported");
+    io_servData.calloutClock(callout::ClockType::TOD_CLOCK,
+                             callout::Priority::MED, true);
+    io_servData.calloutTarget(util::pdbg::getTrgt(i_chip),
+                              callout::Priority::MED, false);
+}
+
+} // namespace P10
+
+PLUGIN_DEFINE_NS(P10_10, P10, tod_step_check_fault);
+PLUGIN_DEFINE_NS(P10_20, P10, tod_step_check_fault);
+
+} // namespace analyzer
diff --git a/analyzer/ras-data/ras-data-definition.md b/analyzer/ras-data/ras-data-definition.md
index 9c4b10f..007d01f 100644
--- a/analyzer/ras-data/ras-data-definition.md
+++ b/analyzer/ras-data/ras-data-definition.md
@@ -180,6 +180,7 @@
 |-----------------|------------------------------------------------------------|
 | OSC_REF_CLOCK_0 | Oscillator reference clock 0                               |
 | OSC_REF_CLOCK_1 | Oscillator reference clock 1                               |
+| TOD_CLOCK       | Time of Day (TOD) clock                                    |
 
 #### 5.1.7) action type `callout_procedure`
 
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
index e3b86f6..861283b 100644
--- a/analyzer/ras-data/ras-data-parser.cpp
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -225,6 +225,7 @@
             {
                 {"OSC_REF_CLOCK_0", callout::ClockType::OSC_REF_CLOCK_0},
                 {"OSC_REF_CLOCK_1", callout::ClockType::OSC_REF_CLOCK_1},
+                {"TOD_CLOCK",       callout::ClockType::TOD_CLOCK},
             };
             // clang-format on
 
diff --git a/analyzer/ras-data/schema/ras-data-schema-v01.json b/analyzer/ras-data/schema/ras-data-schema-v01.json
index e1bced1..77773e5 100644
--- a/analyzer/ras-data/schema/ras-data-schema-v01.json
+++ b/analyzer/ras-data/schema/ras-data-schema-v01.json
@@ -158,7 +158,8 @@
                                         "name": {
                                             "enum": [
                                                 "OSC_REF_CLOCK_0",
-                                                "OSC_REF_CLOCK_1"
+                                                "OSC_REF_CLOCK_1",
+                                                "TOD_CLOCK"
                                             ]
                                         }
                                     }
diff --git a/test/meson.build b/test/meson.build
index 662274d..c484b2e 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -31,6 +31,8 @@
     command : [ find_program('dtc'), '-I', 'dts', '-O', 'dtb',
                 '-o', '@OUTPUT@', '@INPUT@' ])
 
+pdbg_env = 'PDBG_DTB=' + pdbg_test_dtb.full_path()
+
 # end2end code exerciser for experiment and testing
 subdir('end2end')
 
@@ -70,5 +72,29 @@
                     dependencies : [ libhei_dep, libpdbg_dep, gtest_dep ],
                     cpp_args : test_arg,
                     include_directories : incdir),
-         env : [ 'PDBG_DTB=' + pdbg_test_dtb.full_path() ])
+         env : pdbg_env)
 endforeach
+
+################################################################################
+
+tc = 'test-tod-step-check-fault'
+
+src = [
+  files(
+    tc + '.cpp',
+    '../analyzer/plugins/p10-tod-plugins.cpp',
+    '../analyzer/service_data.cpp',
+    '../util/pdbg.cpp',
+  ),
+  pdbg_test_dtb,
+]
+
+dep = [ libhei_dep, libpdbg_dep, gtest_dep ]
+
+var = [ pdbg_env ]
+
+exe = executable(tc.underscorify(), src, dependencies: dep,
+                 cpp_args: test_arg, include_directories: incdir)
+
+test(tc, exe, env: var)
+
diff --git a/test/test-tod-step-check-fault.cpp b/test/test-tod-step-check-fault.cpp
new file mode 100644
index 0000000..d27b72b
--- /dev/null
+++ b/test/test-tod-step-check-fault.cpp
@@ -0,0 +1,71 @@
+#include <stdio.h>
+
+#include <analyzer/plugins/plugin.hpp>
+#include <hei_util.hpp>
+#include <util/pdbg.hpp>
+#include <util/trace.hpp>
+
+#include "gtest/gtest.h"
+
+using namespace analyzer;
+
+static const auto nodeId =
+    static_cast<libhei::NodeId_t>(libhei::hash<libhei::NodeId_t>("TOD_ERROR"));
+
+TEST(TodStepCheckFault, TestSet1)
+{
+    pdbg_targets_init(nullptr);
+
+    libhei::Chip chip1{util::pdbg::getTrgt("/proc1"), P10_20};
+
+    // TOD_ERROR(0)[16]
+    libhei::Signature sig{chip1, nodeId, 0, 16, libhei::ATTN_TYPE_CHECKSTOP};
+
+    auto plugin =
+        PluginMap::getSingleton().get(chip1.getType(), "tod_step_check_fault");
+
+    libhei::IsolationData isoData{};
+    isoData.addSignature(sig);
+    ServiceData sd{sig, AnalysisType::SYSTEM_CHECKSTOP, isoData};
+
+    // Call the plugin.
+    plugin(1, chip1, sd);
+
+    nlohmann::json j{};
+    std::string s{};
+
+    // Callout list
+    j = sd.getCalloutList();
+    s = R"([
+    {
+        "Deconfigured": false,
+        "Guarded": false,
+        "LocationCode": "P0",
+        "Priority": "M"
+    },
+    {
+        "Deconfigured": false,
+        "Guarded": false,
+        "LocationCode": "/proc1",
+        "Priority": "M"
+    }
+])";
+    EXPECT_EQ(s, j.dump(4));
+
+    // Callout FFDC
+    j = sd.getCalloutFFDC();
+    s = R"([
+    {
+        "Callout Type": "Clock Callout",
+        "Clock Type": "TOD_CLOCK",
+        "Priority": "medium"
+    },
+    {
+        "Callout Type": "Hardware Callout",
+        "Guard": false,
+        "Priority": "medium",
+        "Target": "/proc1"
+    }
+])";
+    EXPECT_EQ(s, j.dump(4));
+}