blob: 5bcfff89a5b323d287567cbad82d52873ff4ab6e [file] [log] [blame]
Zane Shelley7bf1f6d2019-10-18 16:03:51 -05001#include <isolator/hei_isolation_node.hpp>
Zane Shelley995be6c2021-02-24 15:48:55 -06002#include <util/hei_bit_string.hpp>
Zane Shelley7bf1f6d2019-10-18 16:03:51 -05003
4namespace libhei
5{
6
7//------------------------------------------------------------------------------
8
Zane Shelleyfe27b652019-10-28 11:33:07 -05009bool IsolationNode::analyze(const Chip& i_chip, AttentionType_t i_attnType,
10 IsolationData& io_isoData) const
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050011{
12 bool o_activeAttn = false; // Initially, assume no active attentions.
13
14 // Keep track of nodes that have been analyzed to avoid cyclic isolation.
15 pushIsolationStack();
16
Zane Shelleye8dc72c2020-05-14 16:40:52 -050017 // Capture all registers for this node.
18 for (const auto& hwReg : iv_capRegs)
19 {
20 // Read the register (adds BitString to register cache).
21 if (hwReg->read(i_chip))
22 {
Zane Shelleydae1af62021-01-14 11:00:46 -060023 // The register read failed.
Zane Shelleye8dc72c2020-05-14 16:40:52 -050024 // TODO: Would be nice to add SCOM errors to the log just in case
25 // traces are not available.
Zane Shelley734cfe92020-08-10 19:57:27 -050026 // TODO: This trace could be redundant with the user application,
27 // which will have more information on the actual chip that
28 // failed anyway. Leaving it commented out for now until the
29 // SCOM errors are added to the log.
30 // HEI_ERR("register read failed on chip type=0x%0" PRIx32
31 // "address=0x%0" PRIx64,
32 // i_chip.getType(), hwReg->getAddress());
Zane Shelleye8dc72c2020-05-14 16:40:52 -050033 }
Zane Shelleydae1af62021-01-14 11:00:46 -060034 else
35 {
36 // Add to the FFDC.
37 io_isoData.addRegister(i_chip, hwReg->getId(), hwReg->getInstance(),
38 hwReg->getBitString(i_chip));
39 }
Zane Shelleye8dc72c2020-05-14 16:40:52 -050040 }
41
Zane Shelleybcb43952021-07-08 22:13:57 -050042 // Get the rule for this attention type.
Zane Shelley83da2452019-10-25 15:45:34 -050043 auto rule_itr = iv_rules.find(i_attnType);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050044
Zane Shelleybcb43952021-07-08 22:13:57 -050045 // It is possible that a rule does not exist. The likely scenario is that
46 // this node is intended to only gather FFDC for a specific bit in the
47 // parent node.
48 if (iv_rules.end() != rule_itr)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050049 {
Zane Shelleybcb43952021-07-08 22:13:57 -050050 // Get the returned BitString for this rule.
51 const BitString* bs = rule_itr->second->getBitString(i_chip);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050052
Zane Shelleybcb43952021-07-08 22:13:57 -050053 // Ensure this BitString is not longer than the maximum bit field.
54 HEI_ASSERT(bs->getBitLen() <= (1 << (sizeof(BitPosition_t) * 8)));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050055
Zane Shelleybcb43952021-07-08 22:13:57 -050056 // Find all active bits for this rule.
57 for (BitPosition_t bit = 0; bit < bs->getBitLen(); bit++)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050058 {
Zane Shelleybcb43952021-07-08 22:13:57 -050059 // Continue to the next bit if not active.
60 if (!bs->isBitSet(bit))
61 continue;
62
63 // At least one active bit was found.
64 o_activeAttn = true;
65
66 // Determine if this attention originated from another register or
67 // if it is a leaf in the isolation tree.
68 auto child_itr = iv_children.find(bit);
69 if (iv_children.end() != child_itr)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050070 {
Zane Shelleybcb43952021-07-08 22:13:57 -050071 // This bit was driven from an attention from another register.
72 // Continue down the isolation tree to look for more attentions.
73 bool attnFound =
74 child_itr->second->analyze(i_chip, i_attnType, io_isoData);
75 if (!attnFound)
76 {
77 // It is possible the child node is only intended for FFDC.
78 // See comment near the check for a valid rule above.
79 // Otherwise, it is possible something went wrong. If there
80 // should have been an active attention, it's possible there
81 // is a bug in the Chip Data File. Or, it is also possible
82 // some other piece of code is clearing the attention before
83 // this code is able to analyze it. Another possibility is
84 // that the hardware it not behaving as expected. Since we
85 // really don't know what happened, we should not assert.
86 // Instead, add this bit's signature to io_isoData. If there
87 // are no other active attentions, the user application
88 // could use this signature to help determine, and
89 // circumvent, the isolation problem.
90 io_isoData.addSignature(
91 Signature{i_chip, iv_id, iv_instance, bit, i_attnType});
92 }
93 }
94 else
95 {
96 // We have reached a leaf in the isolation tree. Add this bit's
97 // signature to io_isoData.
Zane Shelley6722b5b2020-05-12 22:09:04 -050098 io_isoData.addSignature(
99 Signature{i_chip, iv_id, iv_instance, bit, i_attnType});
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500100 }
101 }
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500102 }
103
104 // Analysis is complete on this node. So remove it from cv_isolationStack.
105 popIsolationStack();
106
107 return o_activeAttn;
108}
109
110//------------------------------------------------------------------------------
111
Zane Shelleye8dc72c2020-05-14 16:40:52 -0500112void IsolationNode::addCaptureRegister(HardwareRegister::ConstPtr i_hwReg)
113{
114 HEI_ASSERT(i_hwReg); // should not be null
115
116 // If the register already exists, ignore it. Otherwise, add it to the list.
117 auto itr = std::find(iv_capRegs.begin(), iv_capRegs.end(), i_hwReg);
118 if (iv_capRegs.end() == itr)
119 {
120 iv_capRegs.push_back(i_hwReg);
121 }
122}
123
124//------------------------------------------------------------------------------
125
Zane Shelley4de8ff82020-05-14 15:39:01 -0500126void IsolationNode::addRule(AttentionType_t i_attnType,
127 Register::ConstPtr i_rule)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500128{
Zane Shelley6722b5b2020-05-12 22:09:04 -0500129 HEI_ASSERT(i_rule); // should not be null
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500130
Zane Shelley6722b5b2020-05-12 22:09:04 -0500131 auto ret = iv_rules.emplace(i_attnType, i_rule);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500132
Zane Shelley6722b5b2020-05-12 22:09:04 -0500133 // If an entry already existed, it must point to the same object.
134 HEI_ASSERT(ret.second || (ret.first->second == i_rule));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500135}
136
137//------------------------------------------------------------------------------
138
Zane Shelley4de8ff82020-05-14 15:39:01 -0500139void IsolationNode::addChild(uint8_t i_bit, ConstPtr i_child)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500140{
Zane Shelley6722b5b2020-05-12 22:09:04 -0500141 HEI_ASSERT(i_child); // should not be null
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500142
Zane Shelley6722b5b2020-05-12 22:09:04 -0500143 auto ret = iv_children.emplace(i_bit, i_child);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500144
Zane Shelley6722b5b2020-05-12 22:09:04 -0500145 // If an entry already existed, it must point to the same object.
146 HEI_ASSERT(ret.second || (ret.first->second == i_child));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500147}
148
149//------------------------------------------------------------------------------
150
Zane Shelley2467db82020-05-18 19:56:30 -0500151std::vector<const IsolationNode*> IsolationNode::cv_isolationStack{};
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500152
153//------------------------------------------------------------------------------
154
155void IsolationNode::pushIsolationStack() const
156{
157 // Ensure this node does not already exist in cv_isolationStack.
Zane Shelley2467db82020-05-18 19:56:30 -0500158 auto itr =
159 std::find(cv_isolationStack.begin(), cv_isolationStack.end(), this);
Zane Shelley83da2452019-10-25 15:45:34 -0500160 HEI_ASSERT(cv_isolationStack.end() == itr);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500161
162 // Push to node to the stack.
Zane Shelley2467db82020-05-18 19:56:30 -0500163 cv_isolationStack.push_back(this);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500164}
165
166//------------------------------------------------------------------------------
167
168} // end namespace libhei