Capture data support for an isolation bit
User applications can not specify registers to capture if there is an
active attention on a specific bit in an isolation node. This helps
reduce the number of registers captured by default when analyzing an
isolation node.
Change-Id: I50c88cb8a2fa3d89d2c7446dbc04d0f33bbb0cd2
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/src/isolator/hei_isolation_node.cpp b/src/isolator/hei_isolation_node.cpp
index 5bcfff8..119c5ae 100644
--- a/src/isolator/hei_isolation_node.cpp
+++ b/src/isolator/hei_isolation_node.cpp
@@ -14,30 +14,8 @@
// Keep track of nodes that have been analyzed to avoid cyclic isolation.
pushIsolationStack();
- // Capture all registers for this node.
- for (const auto& hwReg : iv_capRegs)
- {
- // Read the register (adds BitString to register cache).
- if (hwReg->read(i_chip))
- {
- // The register read failed.
- // TODO: Would be nice to add SCOM errors to the log just in case
- // traces are not available.
- // TODO: This trace could be redundant with the user application,
- // which will have more information on the actual chip that
- // failed anyway. Leaving it commented out for now until the
- // SCOM errors are added to the log.
- // HEI_ERR("register read failed on chip type=0x%0" PRIx32
- // "address=0x%0" PRIx64,
- // i_chip.getType(), hwReg->getAddress());
- }
- else
- {
- // Add to the FFDC.
- io_isoData.addRegister(i_chip, hwReg->getId(), hwReg->getInstance(),
- hwReg->getBitString(i_chip));
- }
- }
+ // Capture default set of registers for this node.
+ captureRegisters(i_chip, io_isoData);
// Get the rule for this attention type.
auto rule_itr = iv_rules.find(i_attnType);
@@ -63,6 +41,9 @@
// At least one active bit was found.
o_activeAttn = true;
+ // Capture registers specific to this isolation bit.
+ captureRegisters(i_chip, io_isoData, bit);
+
// Determine if this attention originated from another register or
// if it is a leaf in the isolation tree.
auto child_itr = iv_children.find(bit);
@@ -109,15 +90,31 @@
//------------------------------------------------------------------------------
-void IsolationNode::addCaptureRegister(HardwareRegister::ConstPtr i_hwReg)
+void IsolationNode::addCaptureRegister(HardwareRegister::ConstPtr i_hwReg,
+ BitPosition_t i_bit)
{
HEI_ASSERT(i_hwReg); // should not be null
- // If the register already exists, ignore it. Otherwise, add it to the list.
- auto itr = std::find(iv_capRegs.begin(), iv_capRegs.end(), i_hwReg);
- if (iv_capRegs.end() == itr)
+ // Check the bit range.
+ if (MAX_BIT_POSITION != i_bit)
{
- iv_capRegs.push_back(i_hwReg);
+ if (REG_TYPE_SCOM == iv_regType || REG_TYPE_ID_SCOM == iv_regType)
+ {
+ HEI_ASSERT(i_bit < 64);
+ }
+ else
+ {
+ HEI_ASSERT(false); // register type unsupported
+ }
+ }
+
+ // Add this capture register only if it does not already exist in the list.
+ auto itr = iv_capRegs.find(i_bit);
+ if (iv_capRegs.end() == itr ||
+ itr->second.end() ==
+ std::find(itr->second.begin(), itr->second.end(), i_hwReg))
+ {
+ iv_capRegs[i_bit].push_back(i_hwReg);
}
}
@@ -165,4 +162,43 @@
//------------------------------------------------------------------------------
+void IsolationNode::captureRegisters(const Chip& i_chip,
+ IsolationData& io_isoData,
+ BitPosition_t i_bit) const
+{
+ auto itr = iv_capRegs.find(i_bit);
+ if (iv_capRegs.end() != itr)
+ {
+ // Capture all registers for this node.
+ for (const auto& hwReg : itr->second)
+ {
+ // Read the register (adds BitString to register cache).
+ if (hwReg->read(i_chip))
+ {
+ // The register read failed.
+ // TODO: Would be nice to add SCOM errors to the log just in
+ // case
+ // traces are not available.
+ // TODO: This trace could be redundant with the user
+ // application,
+ // which will have more information on the actual chip
+ // that failed anyway. Leaving it commented out for now
+ // until the SCOM errors are added to the log.
+ // HEI_ERR("register read failed on chip type=0x%0" PRIx32
+ // "address=0x%0" PRIx64,
+ // i_chip.getType(), hwReg->getAddress());
+ }
+ else
+ {
+ // Add to the FFDC.
+ io_isoData.addRegister(i_chip, hwReg->getId(),
+ hwReg->getInstance(),
+ hwReg->getBitString(i_chip));
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
} // end namespace libhei
diff --git a/src/isolator/hei_isolation_node.hpp b/src/isolator/hei_isolation_node.hpp
index ebb1850..858a8c1 100644
--- a/src/isolator/hei_isolation_node.hpp
+++ b/src/isolator/hei_isolation_node.hpp
@@ -85,10 +85,14 @@
const RegisterType_t iv_regType;
/**
- * The list of register to capture and add to the log for additional
- * debugging.
+ * The lists of register to capture and add to the log for additional
+ * debugging. The lists are indexed in a map where the key is a bit
+ * position. All registers that should be captured by default when
+ * isolating to this node will have a bit position of `MAX_BIT_POSITION`.
+ * Otherwise, any other list targeted for a specific bit will only be
+ * captured if there is an active attention on that bit.
*/
- std::vector<HardwareRegister::ConstPtr> iv_capRegs;
+ std::map<BitPosition_t, std::vector<HardwareRegister::ConstPtr>> iv_capRegs;
/**
* This register could report multiple types of attentions. We can use a
@@ -131,9 +135,14 @@
* This is only intended to be used during initialization of the isolator.
* Duplicate registers will be ignored.
*
- * @param The target hardware register.
+ * @param i_hwReg The target hardware register.
+ * @param i_bit If specified, the given register should only be captured
+ * when there is an active attention on the given bit. If
+ * omitted, the given register will be captured any time
+ * this isolation node is analyzed.
*/
- void addCaptureRegister(HardwareRegister::ConstPtr i_hwReg);
+ void addCaptureRegister(HardwareRegister::ConstPtr i_hwReg,
+ BitPosition_t i_bit = MAX_BIT_POSITION);
/**
* @brief Adds a register rule for the given attention type. See iv_rules
@@ -183,6 +192,19 @@
return iv_regType;
}
+ private: // Member functions
+ /**
+ * @param i_chip The target chip for isolation.
+ * @param io_isoData The isolation data returned back to the user
+ * application.
+ * @param i_bit If specified, only the registers specifically
+ * targeted for the given bit are captured. If omitted,
+ * the default list of registers for this isolation node
+ * will be captured.
+ */
+ void captureRegisters(const Chip& i_chip, IsolationData& io_isoData,
+ BitPosition_t i_bit = MAX_BIT_POSITION) const;
+
private: // Isolation stack and supporting functions.
/** When analyze() is called at the tree root, all recursive calls to
* analyze() will target the same chip and attention type. So we only need