create PluginMap and plugin definition
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: I1d4c9c59657f7c07f0fffdd6dc94d5d21033ff0a
diff --git a/analyzer/meson.build b/analyzer/meson.build
index be37557..3cf063e 100644
--- a/analyzer/meson.build
+++ b/analyzer/meson.build
@@ -10,6 +10,10 @@
'service_data.cpp',
)
+plugins_src = files(
+ 'plugins/p10-plugins.cpp',
+)
+
# Library dependencies.
analyzer_deps = [
dbus_interfaces_dep,
@@ -22,7 +26,7 @@
# Create static library.
analyzer_lib = static_library(
'analyzer_lib',
- analyzer_src,
+ [ analyzer_src, plugins_src ],
include_directories : incdir,
dependencies : analyzer_deps,
cpp_args : [ package_args, test_arg ],
diff --git a/analyzer/plugins/p10-plugins.cpp b/analyzer/plugins/p10-plugins.cpp
new file mode 100644
index 0000000..dd14457
--- /dev/null
+++ b/analyzer/plugins/p10-plugins.cpp
@@ -0,0 +1,31 @@
+
+#include <analyzer/plugins/plugin.hpp>
+#include <util/trace.hpp>
+
+namespace analyzer
+{
+
+namespace P10
+{
+
+/**
+ * @brief Adds all clocks/chips reporting PLL unlock attentions to the callout
+ * list.
+ *
+ * Processors are always called out at medium priority and never guarded. If
+ * more than one processor is reporting a PLL unlock attention on the same
+ * clock, the clock is called out with high priority. Otherwise, the clock
+ * callout priority is medium.
+ */
+void pll_unlock(unsigned int i_instance, const libhei::Chip&, ServiceData&)
+{
+ // TODO
+ trace::inf("pll_unlock plugin: i_instance=%u", i_instance);
+}
+
+} // namespace P10
+
+PLUGIN_DEFINE_NS(P10_10, P10, pll_unlock);
+PLUGIN_DEFINE_NS(P10_20, P10, pll_unlock);
+
+} // namespace analyzer
diff --git a/analyzer/plugins/plugin.hpp b/analyzer/plugins/plugin.hpp
new file mode 100644
index 0000000..c5db3f0
--- /dev/null
+++ b/analyzer/plugins/plugin.hpp
@@ -0,0 +1,173 @@
+#pragma once
+
+#include <string.h>
+
+#include <analyzer/service_data.hpp>
+#include <hei_chip.hpp>
+
+#include <functional>
+#include <map>
+
+namespace analyzer
+{
+
+// A plugin is special function called by the RAS data files specifically for
+// service actions that cannot be characterized by the RAS data files.
+//
+// IMPORTANT:
+// Use of these plugins should be limited to avoid maintaining chip specific
+// functionality in this repository.
+//
+// Each plugin must be defined in a specific form. See PluginFunction below.
+// Then the plugin must registered in the PluginMap using the PLUGIN_DEFINE or
+// PLUGIN_DEFINE_NS macros below.
+
+// All plugins will have the following parameters:
+// - The plugin instance for plugins that may be defined for a chip that has
+// multiple instance of a unit/register.
+// - The chip containing the root cause attention.
+// - The service data object containing service actions and FFDC for the root
+// cause attention.
+using PluginFunction =
+ std::function<void(unsigned int, const libhei::Chip&, ServiceData&)>;
+
+// These are provided as know chip types for plugin definitions.
+constexpr libhei::ChipType_t EXPLORER_11 = 0x60d20011;
+constexpr libhei::ChipType_t EXPLORER_20 = 0x60d20020;
+constexpr libhei::ChipType_t P10_10 = 0x20da0010;
+constexpr libhei::ChipType_t P10_20 = 0x20da0020;
+
+/**
+ * @brief This is simply a global container for all of the registered plugins.
+ *
+ * @note This class cannot be instantiated. Instead, use the getSingleton()
+ * function to access.
+ */
+class PluginMap
+{
+ private:
+ /** @brief Default constructor. */
+ PluginMap() = default;
+
+ /** @brief Destructor. */
+ ~PluginMap() = default;
+
+ /** @brief Copy constructor. */
+ PluginMap(const PluginMap&) = delete;
+
+ /** @brief Assignment operator. */
+ PluginMap& operator=(const PluginMap&) = delete;
+
+ public:
+ /** @brief Provides access to a singleton instance of this object. */
+ static PluginMap& getSingleton()
+ {
+ static PluginMap thePluginMap;
+ return thePluginMap;
+ }
+
+ private:
+ /** A nested map that contains the function for each chip type and plugin
+ * name. */
+ std::map<libhei::ChipType_t, std::map<std::string, PluginFunction>> iv_map;
+
+ public:
+ /**
+ * @brief Registers a plugin with the plugin map.
+ *
+ * @param i_type The chip type associated with the plugin.
+ * @param i_name The name of the plugin.
+ * @param i_plugin The plugin function.
+ *
+ * @throw std::logic_error if a plugin is defined more than once.
+ */
+ void add(libhei::ChipType_t i_type, const std::string& i_name,
+ PluginFunction i_plugin)
+ {
+ auto itr = iv_map.find(i_type);
+ if (iv_map.end() == itr ||
+ itr->second.end() == itr->second.find(i_name))
+ {
+ iv_map[i_type][i_name] = i_plugin;
+ }
+ else
+ {
+ throw std::logic_error("Duplicate plugin found");
+ }
+ }
+
+ /**
+ * @return The plugin function for the target plugin.
+ *
+ * @param i_type The chip type associated with the plugin.
+ * @param i_name The name of the plugin.
+ *
+ * @throw std::out_of_range if the target plugin does not exist.
+ */
+ PluginFunction get(libhei::ChipType_t i_type,
+ const std::string& i_name) const
+ {
+ return iv_map.at(i_type).at(i_name);
+ }
+};
+
+// These defines a unique class and a global variable for each plugin. Because
+// the variables are defined in the global scope, they will be initialized with
+// the default constructor before execution of the program. This allows all of
+// the plugins to be registered in the plugin map before execution.
+
+#define __PLUGIN_MAKE(X, Y, Z) X##Y##Z
+
+#define __PLUGIN_DEFINE(CHIP, NAME, FUNC) \
+ class __PLUGIN_MAKE(Plugin_, CHIP, NAME) \
+ { \
+ public: \
+ __PLUGIN_MAKE(Plugin_, CHIP, NAME) \
+ () \
+ { \
+ PluginMap::getSingleton().add(CHIP, #NAME, &FUNC); \
+ } \
+ }; \
+ __PLUGIN_MAKE(Plugin_, CHIP, NAME) __PLUGIN_MAKE(g_Plugin_, CHIP, NAME)
+
+#define PLUGIN_DEFINE(CHIP, NAME) __PLUGIN_DEFINE(CHIP, NAME, CHIP::NAME)
+
+#define PLUGIN_DEFINE_NS(CHIP, NS, NAME) __PLUGIN_DEFINE(CHIP, NAME, NS::NAME)
+
+// Regarding the use of PLUGIN_DEFINE_NS. This is provided for cases where the
+// same plugin needs to be defined differently for different chips. Example:
+//
+// namespace A
+// {
+// void foo(...) { /* definition for chip A */ }
+// };
+//
+// namespace B
+// {
+// void foo(...) { /* definition for chip B */ }
+// };
+//
+// PLUGIN_DEFINE_NS(CHIP_A, A, foo);
+// PLUGIN_DEFINE_NS(CHIP_B, B, foo);
+//
+// Also, it is important that the plugin definitions should be declared outside
+// of the function namespaces (see the example above). This helps find
+// duplicate plugin definitions at compile time. Otherwise, if you do something
+// like this:
+//
+// namespace A
+// {
+// void foo(...) { /* definition for chip A */ }
+// PLUGIN_DEFINE_NS(CHIP_A, A, foo);
+// };
+//
+// namespace B
+// {
+// void foo(...) { /* definition again for chip A */ }
+// PLUGIN_DEFINE_NS(CHIP_A, B, foo);
+// };
+//
+// The compiler will not find the duplicate and instead it will be found during
+// program execution, which will result in an exception.
+
+} // namespace analyzer
diff --git a/analyzer/resolution.cpp b/analyzer/resolution.cpp
index c47cb31..3183216 100644
--- a/analyzer/resolution.cpp
+++ b/analyzer/resolution.cpp
@@ -1,3 +1,4 @@
+#include <analyzer/plugins/plugin.hpp>
#include <analyzer/resolution.hpp>
#include <util/pdbg.hpp>
#include <util/trace.hpp>
@@ -282,10 +283,15 @@
//------------------------------------------------------------------------------
-void PluginResolution::resolve(ServiceData&) const
+void PluginResolution::resolve(ServiceData& io_sd) const
{
- trace::inf("PluginResolution: iv_name=%s iv_instance=%u", iv_name.c_str(),
- iv_instance);
+ // Get the plugin function and call it.
+
+ auto chip = io_sd.getRootCause().getChip();
+
+ auto func = PluginMap::getSingleton().get(chip.getType(), iv_name);
+
+ func(iv_instance, chip, io_sd);
}
//------------------------------------------------------------------------------