1 #include <attn/attn_common.hpp> 2 #include <attn/attn_dbus.hpp> 3 #include <attn/attn_dump.hpp> 4 #include <attn/attn_logging.hpp> 5 #include <attn/pel/pel_common.hpp> 6 #include <attn/ti_handler.hpp> 7 #include <sdbusplus/bus.hpp> 8 #include <sdbusplus/exception.hpp> 9 #include <util/dbus.hpp> 10 #include <util/trace.hpp> 11 12 #include <format> 13 #include <iomanip> 14 #include <iostream> 15 16 namespace attn 17 { 18 19 /** 20 * @brief Determine if this is a HB or PHYP TI event 21 * 22 * Use the TI info data area to determine if this is either a HB or a PHYP 23 * TI event then handle the event. 24 * 25 * @param i_tiDataArea pointer to the TI info data 26 */ 27 int tiHandler(TiDataArea* i_tiDataArea) 28 { 29 int rc = RC_SUCCESS; 30 31 // capture some additional data for logs/traces 32 addHbStatusRegs(); 33 34 // check TI data area if it is available 35 if (nullptr != i_tiDataArea) 36 { 37 // HB v. PHYP TI logic: Only hosboot will fill in hbTerminateType 38 // and it will be non-zero. Only hostboot will fill out source and 39 // it it will be non-zero. Only PHYP will fill in srcFormat and it 40 // will be non-zero. 41 if ((0 == i_tiDataArea->hbTerminateType) && 42 (0 == i_tiDataArea->source) && (0 != i_tiDataArea->srcFormat)) 43 { 44 handlePhypTi(i_tiDataArea); 45 } 46 else 47 { 48 handleHbTi(i_tiDataArea); 49 } 50 } 51 else 52 { 53 // TI data was not available This should not happen since we provide 54 // a default TI info in the case where get TI info was not successful. 55 eventAttentionFail((int)AttnSection::tiHandler | ATTN_INFO_NULL); 56 rc = RC_NOT_HANDLED; 57 } 58 59 return rc; 60 } 61 62 /** 63 * @brief Handle a PHYP terminate immediate special attention 64 * 65 * The TI info data area will contain information pertaining to the TI 66 * condition. We will wither quiesce the host or initiate a MPIPL depending 67 * depending on the auto reboot configuration. We will also create a PEL which 68 * will contain the TI info data and FFDC data captured in the system journal. 69 * 70 * @param i_tiDataArea pointer to TI information filled in by hostboot 71 */ 72 void handlePhypTi(TiDataArea* i_tiDataArea) 73 { 74 trace::inf("PHYP TI"); 75 76 // gather additional data for PEL 77 std::map<std::string, std::string> tiAdditionalData; 78 79 // make note of recoverable errors present 80 tiAdditionalData["recoverables"] = recoverableErrors() ? "true" : "false"; 81 82 if (nullptr != i_tiDataArea) 83 { 84 parsePhypOpalTiInfo(tiAdditionalData, i_tiDataArea); 85 86 tiAdditionalData["Subsystem"] = 87 std::to_string(static_cast<uint8_t>(pel::SubsystemID::hypervisor)); 88 89 // Copy all ascii src chars to additional data 90 char srcChar[33]; // 32 ascii chars + null term 91 memcpy(srcChar, &(i_tiDataArea->asciiData0), 32); 92 srcChar[32] = 0; 93 tiAdditionalData["SrcAscii"] = std::string{srcChar}; 94 95 // TI event 96 eventTerminate(tiAdditionalData, (char*)i_tiDataArea); 97 } 98 else 99 { 100 // TI data was not available This should not happen since we provide 101 // a default TI info in the case where get TI info was not successful. 102 eventAttentionFail((int)AttnSection::handlePhypTi | ATTN_INFO_NULL); 103 } 104 105 // We are finished creating the event log entries so transition host to 106 // the required state. 107 if (true == util::dbus::dumpPolicyEnabled()) 108 { 109 // MPIPL is considered a "dump" so we will qualify this transition with 110 // the dumpPolicyEnabled property. MPIPL is triggered by by starting 111 // the host "crash" target. 112 util::dbus::transitionHost(util::dbus::HostState::Crash); 113 } 114 else 115 { 116 // If dumpPolicyEnabled property is disabled we will quiesce the host 117 util::dbus::transitionHost(util::dbus::HostState::Quiesce); 118 } 119 } 120 121 /** 122 * @brief Handle a hostboot terminate immediate with SRC provided 123 * 124 * The TI info will contain the log ID of the event log that has already been 125 * submitted by hostboot. In this case the attention handler does not need to 126 * create a PEL. A hostboot dump may be requested and the host will be 127 * transitioned. 128 * 129 * @param i_tiDataArea pointer to TI information filled in by hostboot 130 */ 131 void handleHbTiWithEid(TiDataArea* i_tiDataArea) 132 { 133 trace::inf("HB TI with PLID/EID"); 134 135 if (nullptr != i_tiDataArea) 136 { 137 // see if HB dump is requested 138 if (i_tiDataArea->hbFlags & hbDumpFlag) 139 { 140 // retrieve log ID from TI info data 141 uint32_t logId = be32toh(i_tiDataArea->asciiData1); 142 requestDump(logId, DumpParameters{0, DumpType::Hostboot}); 143 } 144 } 145 146 util::dbus::transitionHost(util::dbus::HostState::Quiesce); 147 } 148 149 /** 150 * @brief Handle a hostboot terminate immediate with SRC provided 151 * 152 * The TI info will contain the reason code and additional data necessary 153 * to create a PEL on behalf of hostboot. A hostboot dump may be created 154 * (after generating the PEL) and the host may be transitioned depending 155 * on the reason code. 156 * 157 * @param i_tiDataArea pointer to TI information filled in by hostboot 158 */ 159 void handleHbTiWithSrc(TiDataArea* i_tiDataArea) 160 { 161 trace::inf("HB TI with SRC"); 162 163 // handle specific hostboot reason codes 164 if (nullptr != i_tiDataArea) 165 { 166 // Reason code is byte 2 and 3 of 4 byte srcWord12HbWord0 167 uint16_t reasonCode = be32toh(i_tiDataArea->srcWord12HbWord0); 168 169 trace::inf("reason code %04x", reasonCode); 170 171 // for clean shutdown (reason code 050B) no PEL and no dump 172 if (reasonCode != HB_SRC_SHUTDOWN_REQUEST) 173 { 174 // gather additional data for PEL 175 std::map<std::string, std::string> tiAdditionalData; 176 177 // make note of recoverable errors present 178 tiAdditionalData["recoverables"] = recoverableErrors() ? "true" 179 : "false"; 180 181 parseHbTiInfo(tiAdditionalData, i_tiDataArea); 182 183 tiAdditionalData["Subsystem"] = std::to_string( 184 static_cast<uint8_t>(pel::SubsystemID::hostboot)); 185 186 // Translate hex src value to ascii. This results in an 8 187 // character SRC (hostboot SRC is 32 bits) 188 tiAdditionalData["SrcAscii"] = 189 std::format("{:08X}", be32toh(i_tiDataArea->srcWord12HbWord0)); 190 191 // dump flag is only valid for TI with EID (not TI with SRC) 192 trace::inf("Ignoring TI info dump flag for HB TI with SRC"); 193 tiAdditionalData["Dump"] = "true"; 194 195 // TI with SRC will honor hbNotVisibleFlag 196 if (i_tiDataArea->hbFlags & hbNotVisibleFlag) 197 { 198 tiAdditionalData["hidden"] = "true"; 199 } 200 201 // Generate event log 202 eventTerminate(tiAdditionalData, (char*)i_tiDataArea); 203 } 204 205 if (HB_SRC_KEY_TRANSITION != reasonCode) 206 { 207 util::dbus::transitionHost(util::dbus::HostState::Quiesce); 208 } 209 } 210 else 211 { 212 // TI data was not available, this should not happen 213 eventAttentionFail((int)AttnSection::handleHbTi | ATTN_INFO_NULL); 214 } 215 } 216 217 /** 218 * @brief Handle a hostboot terminate immediate special attention 219 * 220 * The TI info data area will contain information pertaining to the TI 221 * condition. The course of action to take regarding the host state will 222 * depend on the contents of the TI info data area. We will also create a 223 * PEL containing the TI info data and FFDC data captured in the system 224 * journal. 225 * 226 * @param i_tiDataArea pointer to TI information filled in by hostboot 227 */ 228 void handleHbTi(TiDataArea* i_tiDataArea) 229 { 230 trace::inf("HB TI"); 231 232 // handle specific hostboot reason codes 233 if (nullptr != i_tiDataArea) 234 { 235 uint8_t terminateType = i_tiDataArea->hbTerminateType; 236 237 if (TI_WITH_SRC == terminateType) 238 { 239 handleHbTiWithSrc(i_tiDataArea); 240 } 241 else 242 { 243 handleHbTiWithEid(i_tiDataArea); 244 } 245 } 246 else 247 { 248 // TI data was not available, this should not happen 249 eventAttentionFail((int)AttnSection::handleHbTi | ATTN_INFO_NULL); 250 } 251 } 252 253 /** @brief Parse the TI info data area into map as PHYP/OPAL data */ 254 void parsePhypOpalTiInfo(std::map<std::string, std::string>& i_map, 255 TiDataArea* i_tiDataArea) 256 { 257 if (nullptr == i_tiDataArea) 258 { 259 return; 260 } 261 262 i_map["0x00 TI Area Valid"] = std::format("{:02x}", 263 i_tiDataArea->tiAreaValid); 264 i_map["0x01 Command"] = std::format("{:02x}", i_tiDataArea->command); 265 i_map["0x02 Num. Data Bytes"] = 266 std::format("{:04x}", be16toh(i_tiDataArea->numDataBytes)); 267 i_map["0x04 Reserved"] = std::format("{:02x}", i_tiDataArea->reserved1); 268 i_map["0x06 HWDump Type"] = 269 std::format("{:04x}", be16toh(i_tiDataArea->hardwareDumpType)); 270 i_map["0x08 SRC Format"] = std::format("{:02x}", i_tiDataArea->srcFormat); 271 i_map["0x09 SRC Flags"] = std::format("{:02x}", i_tiDataArea->srcFlags); 272 i_map["0x0a Num. ASCII Words"] = std::format("{:02x}", 273 i_tiDataArea->numAsciiWords); 274 i_map["0x0b Num. Hex Words"] = std::format("{:02x}", 275 i_tiDataArea->numHexWords); 276 i_map["0x0e Length of SRC"] = std::format("{:04x}", 277 be16toh(i_tiDataArea->lenSrc)); 278 i_map["0x10 SRC Word 12"] = 279 std::format("{:08x}", be32toh(i_tiDataArea->srcWord12HbWord0)); 280 i_map["0x14 SRC Word 13"] = 281 std::format("{:08x}", be32toh(i_tiDataArea->srcWord13HbWord2)); 282 i_map["0x18 SRC Word 14"] = 283 std::format("{:08x}", be32toh(i_tiDataArea->srcWord14HbWord3)); 284 i_map["0x1c SRC Word 15"] = 285 std::format("{:08x}", be32toh(i_tiDataArea->srcWord15HbWord4)); 286 i_map["0x20 SRC Word 16"] = 287 std::format("{:08x}", be32toh(i_tiDataArea->srcWord16HbWord5)); 288 i_map["0x24 SRC Word 17"] = 289 std::format("{:08x}", be32toh(i_tiDataArea->srcWord17HbWord6)); 290 i_map["0x28 SRC Word 18"] = 291 std::format("{:08x}", be32toh(i_tiDataArea->srcWord18HbWord7)); 292 i_map["0x2c SRC Word 19"] = 293 std::format("{:08x}", be32toh(i_tiDataArea->srcWord19HbWord8)); 294 i_map["0x30 ASCII Data"] = std::format("{:08x}", 295 be32toh(i_tiDataArea->asciiData0)); 296 i_map["0x34 ASCII Data"] = std::format("{:08x}", 297 be32toh(i_tiDataArea->asciiData1)); 298 i_map["0x38 ASCII Data"] = std::format("{:08x}", 299 be32toh(i_tiDataArea->asciiData2)); 300 i_map["0x3c ASCII Data"] = std::format("{:08x}", 301 be32toh(i_tiDataArea->asciiData3)); 302 i_map["0x40 ASCII Data"] = std::format("{:08x}", 303 be32toh(i_tiDataArea->asciiData4)); 304 i_map["0x44 ASCII Data"] = std::format("{:08x}", 305 be32toh(i_tiDataArea->asciiData5)); 306 i_map["0x48 ASCII Data"] = std::format("{:08x}", 307 be32toh(i_tiDataArea->asciiData6)); 308 i_map["0x4c ASCII Data"] = std::format("{:08x}", 309 be32toh(i_tiDataArea->asciiData7)); 310 i_map["0x50 Location"] = std::format("{:02x}", i_tiDataArea->location); 311 i_map["0x51 Code Sections"] = std::format("{:02x}", 312 i_tiDataArea->codeSection); 313 i_map["0x52 Additional Size"] = std::format("{:02x}", 314 i_tiDataArea->additionalSize); 315 i_map["0x53 Additional Data"] = std::format("{:02x}", 316 i_tiDataArea->andData); 317 } 318 319 /** @brief Parse the TI info data area into map as hostboot data */ 320 void parseHbTiInfo(std::map<std::string, std::string>& i_map, 321 TiDataArea* i_tiDataArea) 322 { 323 if (nullptr == i_tiDataArea) 324 { 325 return; 326 } 327 328 i_map["0x00 TI Area Valid"] = std::format("{:02x}", 329 i_tiDataArea->tiAreaValid); 330 i_map["0x04 Reserved"] = std::format("{:02x}", i_tiDataArea->reserved1); 331 i_map["0x05 HB_Term. Type"] = std::format("{:02x}", 332 i_tiDataArea->hbTerminateType); 333 i_map["0x0c HB Flags"] = std::format("{:02x}", i_tiDataArea->hbFlags); 334 i_map["0x0d Source"] = std::format("{:02x}", i_tiDataArea->source); 335 i_map["0x10 HB Word 0"] = 336 std::format("{:08x}", be32toh(i_tiDataArea->srcWord12HbWord0)); 337 i_map["0x14 HB Word 2"] = 338 std::format("{:08x}", be32toh(i_tiDataArea->srcWord13HbWord2)); 339 i_map["0x18 HB Word 3"] = 340 std::format("{:08x}", be32toh(i_tiDataArea->srcWord14HbWord3)); 341 i_map["0x1c HB Word 4"] = 342 std::format("{:08x}", be32toh(i_tiDataArea->srcWord15HbWord4)); 343 i_map["0x20 HB Word 5"] = 344 std::format("{:08x}", be32toh(i_tiDataArea->srcWord16HbWord5)); 345 i_map["0x24 HB Word 6"] = 346 std::format("{:08x}", be32toh(i_tiDataArea->srcWord17HbWord6)); 347 i_map["0x28 HB Word 7"] = 348 std::format("{:08x}", be32toh(i_tiDataArea->srcWord18HbWord7)); 349 i_map["0x2c HB Word 8"] = 350 std::format("{:08x}", be32toh(i_tiDataArea->srcWord19HbWord8)); 351 i_map["0x30 error_data"] = std::format("{:08x}", 352 be32toh(i_tiDataArea->asciiData0)); 353 i_map["0x34 EID"] = std::format("{:08x}", 354 be32toh(i_tiDataArea->asciiData1)); 355 } 356 357 } // namespace attn 358