blob: 78c5b65dad7cf26d9a25fbc104b7045b63433113 [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 Shelley6b1fe162022-11-18 13:37:42 -060017 // Capture default set of registers for this node.
18 captureRegisters(i_chip, io_isoData);
Zane Shelleye8dc72c2020-05-14 16:40:52 -050019
Zane Shelleybcb43952021-07-08 22:13:57 -050020 // Get the rule for this attention type.
Zane Shelley83da2452019-10-25 15:45:34 -050021 auto rule_itr = iv_rules.find(i_attnType);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050022
Zane Shelleybcb43952021-07-08 22:13:57 -050023 // It is possible that a rule does not exist. The likely scenario is that
24 // this node is intended to only gather FFDC for a specific bit in the
25 // parent node.
26 if (iv_rules.end() != rule_itr)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050027 {
Zane Shelleybcb43952021-07-08 22:13:57 -050028 // Get the returned BitString for this rule.
29 const BitString* bs = rule_itr->second->getBitString(i_chip);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050030
Zane Shelleybcb43952021-07-08 22:13:57 -050031 // Ensure this BitString is not longer than the maximum bit field.
32 HEI_ASSERT(bs->getBitLen() <= (1 << (sizeof(BitPosition_t) * 8)));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050033
Zane Shelleybcb43952021-07-08 22:13:57 -050034 // Find all active bits for this rule.
35 for (BitPosition_t bit = 0; bit < bs->getBitLen(); bit++)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050036 {
Zane Shelleybcb43952021-07-08 22:13:57 -050037 // Continue to the next bit if not active.
38 if (!bs->isBitSet(bit))
39 continue;
40
41 // At least one active bit was found.
42 o_activeAttn = true;
43
Zane Shelley6b1fe162022-11-18 13:37:42 -060044 // Capture registers specific to this isolation bit.
45 captureRegisters(i_chip, io_isoData, bit);
46
Zane Shelleybcb43952021-07-08 22:13:57 -050047 // Determine if this attention originated from another register or
48 // if it is a leaf in the isolation tree.
49 auto child_itr = iv_children.find(bit);
50 if (iv_children.end() != child_itr)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050051 {
Zane Shelleybcb43952021-07-08 22:13:57 -050052 // This bit was driven from an attention from another register.
53 // Continue down the isolation tree to look for more attentions.
Patrick Williams2f7537d2023-05-10 07:51:39 -050054 bool attnFound = child_itr->second->analyze(i_chip, i_attnType,
55 io_isoData);
Zane Shelleybcb43952021-07-08 22:13:57 -050056 if (!attnFound)
57 {
58 // It is possible the child node is only intended for FFDC.
59 // See comment near the check for a valid rule above.
60 // Otherwise, it is possible something went wrong. If there
61 // should have been an active attention, it's possible there
62 // is a bug in the Chip Data File. Or, it is also possible
63 // some other piece of code is clearing the attention before
64 // this code is able to analyze it. Another possibility is
65 // that the hardware it not behaving as expected. Since we
66 // really don't know what happened, we should not assert.
67 // Instead, add this bit's signature to io_isoData. If there
68 // are no other active attentions, the user application
69 // could use this signature to help determine, and
70 // circumvent, the isolation problem.
71 io_isoData.addSignature(
72 Signature{i_chip, iv_id, iv_instance, bit, i_attnType});
73 }
74 }
75 else
76 {
77 // We have reached a leaf in the isolation tree. Add this bit's
78 // signature to io_isoData.
Zane Shelley6722b5b2020-05-12 22:09:04 -050079 io_isoData.addSignature(
80 Signature{i_chip, iv_id, iv_instance, bit, i_attnType});
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050081 }
82 }
Zane Shelley7bf1f6d2019-10-18 16:03:51 -050083 }
84
85 // Analysis is complete on this node. So remove it from cv_isolationStack.
86 popIsolationStack();
87
88 return o_activeAttn;
89}
90
91//------------------------------------------------------------------------------
92
Zane Shelley6b1fe162022-11-18 13:37:42 -060093void IsolationNode::addCaptureRegister(HardwareRegister::ConstPtr i_hwReg,
94 BitPosition_t i_bit)
Zane Shelleye8dc72c2020-05-14 16:40:52 -050095{
96 HEI_ASSERT(i_hwReg); // should not be null
97
Zane Shelley6b1fe162022-11-18 13:37:42 -060098 // Check the bit range.
99 if (MAX_BIT_POSITION != i_bit)
Zane Shelleye8dc72c2020-05-14 16:40:52 -0500100 {
Zane Shelley6b1fe162022-11-18 13:37:42 -0600101 if (REG_TYPE_SCOM == iv_regType || REG_TYPE_ID_SCOM == iv_regType)
102 {
103 HEI_ASSERT(i_bit < 64);
104 }
105 else
106 {
107 HEI_ASSERT(false); // register type unsupported
108 }
109 }
110
111 // Add this capture register only if it does not already exist in the list.
112 auto itr = iv_capRegs.find(i_bit);
113 if (iv_capRegs.end() == itr ||
114 itr->second.end() ==
115 std::find(itr->second.begin(), itr->second.end(), i_hwReg))
116 {
117 iv_capRegs[i_bit].push_back(i_hwReg);
Zane Shelleye8dc72c2020-05-14 16:40:52 -0500118 }
119}
120
121//------------------------------------------------------------------------------
122
Zane Shelley4de8ff82020-05-14 15:39:01 -0500123void IsolationNode::addRule(AttentionType_t i_attnType,
124 Register::ConstPtr i_rule)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500125{
Zane Shelley6722b5b2020-05-12 22:09:04 -0500126 HEI_ASSERT(i_rule); // should not be null
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500127
Zane Shelley6722b5b2020-05-12 22:09:04 -0500128 auto ret = iv_rules.emplace(i_attnType, i_rule);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500129
Zane Shelley6722b5b2020-05-12 22:09:04 -0500130 // If an entry already existed, it must point to the same object.
131 HEI_ASSERT(ret.second || (ret.first->second == i_rule));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500132}
133
134//------------------------------------------------------------------------------
135
Zane Shelley4de8ff82020-05-14 15:39:01 -0500136void IsolationNode::addChild(uint8_t i_bit, ConstPtr i_child)
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500137{
Zane Shelley6722b5b2020-05-12 22:09:04 -0500138 HEI_ASSERT(i_child); // should not be null
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500139
Zane Shelley6722b5b2020-05-12 22:09:04 -0500140 auto ret = iv_children.emplace(i_bit, i_child);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500141
Zane Shelley6722b5b2020-05-12 22:09:04 -0500142 // If an entry already existed, it must point to the same object.
143 HEI_ASSERT(ret.second || (ret.first->second == i_child));
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500144}
145
146//------------------------------------------------------------------------------
147
Zane Shelley2467db82020-05-18 19:56:30 -0500148std::vector<const IsolationNode*> IsolationNode::cv_isolationStack{};
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500149
150//------------------------------------------------------------------------------
151
152void IsolationNode::pushIsolationStack() const
153{
154 // Ensure this node does not already exist in cv_isolationStack.
Patrick Williams2f7537d2023-05-10 07:51:39 -0500155 auto itr = std::find(cv_isolationStack.begin(), cv_isolationStack.end(),
156 this);
Zane Shelley83da2452019-10-25 15:45:34 -0500157 HEI_ASSERT(cv_isolationStack.end() == itr);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500158
159 // Push to node to the stack.
Zane Shelley2467db82020-05-18 19:56:30 -0500160 cv_isolationStack.push_back(this);
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500161}
162
163//------------------------------------------------------------------------------
164
Zane Shelley6b1fe162022-11-18 13:37:42 -0600165void IsolationNode::captureRegisters(const Chip& i_chip,
166 IsolationData& io_isoData,
167 BitPosition_t i_bit) const
168{
169 auto itr = iv_capRegs.find(i_bit);
170 if (iv_capRegs.end() != itr)
171 {
172 // Capture all registers for this node.
173 for (const auto& hwReg : itr->second)
174 {
175 // Read the register (adds BitString to register cache).
176 if (hwReg->read(i_chip))
177 {
178 // The register read failed.
179 // TODO: Would be nice to add SCOM errors to the log just in
180 // case
181 // traces are not available.
182 // TODO: This trace could be redundant with the user
183 // application,
184 // which will have more information on the actual chip
185 // that failed anyway. Leaving it commented out for now
186 // until the SCOM errors are added to the log.
187 // HEI_ERR("register read failed on chip type=0x%0" PRIx32
188 // "address=0x%0" PRIx64,
189 // i_chip.getType(), hwReg->getAddress());
190 }
191 else
192 {
193 // Add to the FFDC.
194 io_isoData.addRegister(i_chip, hwReg->getId(),
195 hwReg->getInstance(),
196 hwReg->getBitString(i_chip));
197 }
198 }
199 }
200}
201
202//------------------------------------------------------------------------------
203
Zane Shelley7bf1f6d2019-10-18 16:03:51 -0500204} // end namespace libhei