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 // Trace relevant TI data. 138 trace::inf("TI data HB Flags = 0x%02x", i_tiDataArea->hbFlags); 139 trace::inf("TI data HB Word 0 = 0x%08x", 140 be32toh(i_tiDataArea->srcWord12HbWord0)); 141 trace::inf("TI data HB Word 2 = 0x%08x", 142 be32toh(i_tiDataArea->srcWord13HbWord2)); 143 trace::inf("TI data HB Word 3 = 0x%08x", 144 be32toh(i_tiDataArea->srcWord14HbWord3)); 145 trace::inf("TI data HB Word 4 = 0x%08x", 146 be32toh(i_tiDataArea->srcWord15HbWord4)); 147 trace::inf("TI data HB Word 5 = 0x%08x", 148 be32toh(i_tiDataArea->srcWord16HbWord5)); 149 trace::inf("TI data HB Word 6 = 0x%08x", 150 be32toh(i_tiDataArea->srcWord17HbWord6)); 151 trace::inf("TI data HB Word 7 = 0x%08x", 152 be32toh(i_tiDataArea->srcWord18HbWord7)); 153 trace::inf("TI data HB Word 8 = 0x%08x", 154 be32toh(i_tiDataArea->srcWord19HbWord8)); 155 trace::inf("TI data Error Data = 0x%08x", 156 be32toh(i_tiDataArea->asciiData0)); 157 trace::inf("TI data EID = 0x%08x", be32toh(i_tiDataArea->asciiData1)); 158 159 // see if HB dump is requested 160 if (i_tiDataArea->hbFlags & hbDumpFlag) 161 { 162 // retrieve log ID from TI info data 163 uint32_t logId = be32toh(i_tiDataArea->asciiData1); 164 requestDump(logId, DumpParameters{0, DumpType::Hostboot}); 165 } 166 } 167 168 util::dbus::transitionHost(util::dbus::HostState::Quiesce); 169 } 170 171 /** 172 * @brief Handle a hostboot terminate immediate with SRC provided 173 * 174 * The TI info will contain the reason code and additional data necessary 175 * to create a PEL on behalf of hostboot. A hostboot dump may be created 176 * (after generating the PEL) and the host may be transitioned depending 177 * on the reason code. 178 * 179 * @param i_tiDataArea pointer to TI information filled in by hostboot 180 */ 181 void handleHbTiWithSrc(TiDataArea* i_tiDataArea) 182 { 183 trace::inf("HB TI with SRC"); 184 185 // handle specific hostboot reason codes 186 if (nullptr != i_tiDataArea) 187 { 188 // Reason code is byte 2 and 3 of 4 byte srcWord12HbWord0 189 uint16_t reasonCode = be32toh(i_tiDataArea->srcWord12HbWord0); 190 191 trace::inf("reason code %04x", reasonCode); 192 193 // for clean shutdown (reason code 050B) no PEL and no dump 194 if (reasonCode != HB_SRC_SHUTDOWN_REQUEST) 195 { 196 // gather additional data for PEL 197 std::map<std::string, std::string> tiAdditionalData; 198 199 // make note of recoverable errors present 200 tiAdditionalData["recoverables"] = 201 recoverableErrors() ? "true" : "false"; 202 203 parseHbTiInfo(tiAdditionalData, i_tiDataArea); 204 205 tiAdditionalData["Subsystem"] = std::to_string( 206 static_cast<uint8_t>(pel::SubsystemID::hostboot)); 207 208 // Translate hex src value to ascii. This results in an 8 209 // character SRC (hostboot SRC is 32 bits) 210 tiAdditionalData["SrcAscii"] = 211 std::format("{:08X}", be32toh(i_tiDataArea->srcWord12HbWord0)); 212 213 // dump flag is only valid for TI with EID (not TI with SRC) 214 trace::inf("Ignoring TI info dump flag for HB TI with SRC"); 215 tiAdditionalData["Dump"] = "true"; 216 217 // TI with SRC will honor hbNotVisibleFlag 218 if (i_tiDataArea->hbFlags & hbNotVisibleFlag) 219 { 220 tiAdditionalData["hidden"] = "true"; 221 } 222 223 // Generate event log 224 eventTerminate(tiAdditionalData, (char*)i_tiDataArea); 225 } 226 227 if (HB_SRC_KEY_TRANSITION != reasonCode) 228 { 229 util::dbus::transitionHost(util::dbus::HostState::Quiesce); 230 } 231 } 232 else 233 { 234 // TI data was not available, this should not happen 235 eventAttentionFail((int)AttnSection::handleHbTi | ATTN_INFO_NULL); 236 } 237 } 238 239 /** 240 * @brief Handle a hostboot terminate immediate special attention 241 * 242 * The TI info data area will contain information pertaining to the TI 243 * condition. The course of action to take regarding the host state will 244 * depend on the contents of the TI info data area. We will also create a 245 * PEL containing the TI info data and FFDC data captured in the system 246 * journal. 247 * 248 * @param i_tiDataArea pointer to TI information filled in by hostboot 249 */ 250 void handleHbTi(TiDataArea* i_tiDataArea) 251 { 252 trace::inf("HB TI"); 253 254 // handle specific hostboot reason codes 255 if (nullptr != i_tiDataArea) 256 { 257 uint8_t terminateType = i_tiDataArea->hbTerminateType; 258 259 if (TI_WITH_SRC == terminateType) 260 { 261 handleHbTiWithSrc(i_tiDataArea); 262 } 263 else 264 { 265 handleHbTiWithEid(i_tiDataArea); 266 } 267 } 268 else 269 { 270 // TI data was not available, this should not happen 271 eventAttentionFail((int)AttnSection::handleHbTi | ATTN_INFO_NULL); 272 } 273 } 274 275 /** @brief Parse the TI info data area into map as PHYP/OPAL data */ 276 void parsePhypOpalTiInfo(std::map<std::string, std::string>& i_map, 277 TiDataArea* i_tiDataArea) 278 { 279 if (nullptr == i_tiDataArea) 280 { 281 return; 282 } 283 284 i_map["0x00 TI Area Valid"] = 285 std::format("{:02x}", i_tiDataArea->tiAreaValid); 286 i_map["0x01 Command"] = std::format("{:02x}", i_tiDataArea->command); 287 i_map["0x02 Num. Data Bytes"] = 288 std::format("{:04x}", be16toh(i_tiDataArea->numDataBytes)); 289 i_map["0x04 Reserved"] = std::format("{:02x}", i_tiDataArea->reserved1); 290 i_map["0x06 HWDump Type"] = 291 std::format("{:04x}", be16toh(i_tiDataArea->hardwareDumpType)); 292 i_map["0x08 SRC Format"] = std::format("{:02x}", i_tiDataArea->srcFormat); 293 i_map["0x09 SRC Flags"] = std::format("{:02x}", i_tiDataArea->srcFlags); 294 i_map["0x0a Num. ASCII Words"] = 295 std::format("{:02x}", i_tiDataArea->numAsciiWords); 296 i_map["0x0b Num. Hex Words"] = 297 std::format("{:02x}", i_tiDataArea->numHexWords); 298 i_map["0x0e Length of SRC"] = 299 std::format("{:04x}", be16toh(i_tiDataArea->lenSrc)); 300 i_map["0x10 SRC Word 12"] = 301 std::format("{:08x}", be32toh(i_tiDataArea->srcWord12HbWord0)); 302 i_map["0x14 SRC Word 13"] = 303 std::format("{:08x}", be32toh(i_tiDataArea->srcWord13HbWord2)); 304 i_map["0x18 SRC Word 14"] = 305 std::format("{:08x}", be32toh(i_tiDataArea->srcWord14HbWord3)); 306 i_map["0x1c SRC Word 15"] = 307 std::format("{:08x}", be32toh(i_tiDataArea->srcWord15HbWord4)); 308 i_map["0x20 SRC Word 16"] = 309 std::format("{:08x}", be32toh(i_tiDataArea->srcWord16HbWord5)); 310 i_map["0x24 SRC Word 17"] = 311 std::format("{:08x}", be32toh(i_tiDataArea->srcWord17HbWord6)); 312 i_map["0x28 SRC Word 18"] = 313 std::format("{:08x}", be32toh(i_tiDataArea->srcWord18HbWord7)); 314 i_map["0x2c SRC Word 19"] = 315 std::format("{:08x}", be32toh(i_tiDataArea->srcWord19HbWord8)); 316 i_map["0x30 ASCII Data"] = 317 std::format("{:08x}", be32toh(i_tiDataArea->asciiData0)); 318 i_map["0x34 ASCII Data"] = 319 std::format("{:08x}", be32toh(i_tiDataArea->asciiData1)); 320 i_map["0x38 ASCII Data"] = 321 std::format("{:08x}", be32toh(i_tiDataArea->asciiData2)); 322 i_map["0x3c ASCII Data"] = 323 std::format("{:08x}", be32toh(i_tiDataArea->asciiData3)); 324 i_map["0x40 ASCII Data"] = 325 std::format("{:08x}", be32toh(i_tiDataArea->asciiData4)); 326 i_map["0x44 ASCII Data"] = 327 std::format("{:08x}", be32toh(i_tiDataArea->asciiData5)); 328 i_map["0x48 ASCII Data"] = 329 std::format("{:08x}", be32toh(i_tiDataArea->asciiData6)); 330 i_map["0x4c ASCII Data"] = 331 std::format("{:08x}", be32toh(i_tiDataArea->asciiData7)); 332 i_map["0x50 Location"] = std::format("{:02x}", i_tiDataArea->location); 333 i_map["0x51 Code Sections"] = 334 std::format("{:02x}", i_tiDataArea->codeSection); 335 i_map["0x52 Additional Size"] = 336 std::format("{:02x}", i_tiDataArea->additionalSize); 337 i_map["0x53 Additional Data"] = 338 std::format("{:02x}", i_tiDataArea->andData); 339 } 340 341 /** @brief Parse the TI info data area into map as hostboot data */ 342 void parseHbTiInfo(std::map<std::string, std::string>& i_map, 343 TiDataArea* i_tiDataArea) 344 { 345 if (nullptr == i_tiDataArea) 346 { 347 return; 348 } 349 350 i_map["0x00 TI Area Valid"] = 351 std::format("{:02x}", i_tiDataArea->tiAreaValid); 352 i_map["0x04 Reserved"] = std::format("{:02x}", i_tiDataArea->reserved1); 353 i_map["0x05 HB_Term. Type"] = 354 std::format("{:02x}", i_tiDataArea->hbTerminateType); 355 i_map["0x0c HB Flags"] = std::format("{:02x}", i_tiDataArea->hbFlags); 356 i_map["0x0d Source"] = std::format("{:02x}", i_tiDataArea->source); 357 i_map["0x10 HB Word 0"] = 358 std::format("{:08x}", be32toh(i_tiDataArea->srcWord12HbWord0)); 359 i_map["0x14 HB Word 2"] = 360 std::format("{:08x}", be32toh(i_tiDataArea->srcWord13HbWord2)); 361 i_map["0x18 HB Word 3"] = 362 std::format("{:08x}", be32toh(i_tiDataArea->srcWord14HbWord3)); 363 i_map["0x1c HB Word 4"] = 364 std::format("{:08x}", be32toh(i_tiDataArea->srcWord15HbWord4)); 365 i_map["0x20 HB Word 5"] = 366 std::format("{:08x}", be32toh(i_tiDataArea->srcWord16HbWord5)); 367 i_map["0x24 HB Word 6"] = 368 std::format("{:08x}", be32toh(i_tiDataArea->srcWord17HbWord6)); 369 i_map["0x28 HB Word 7"] = 370 std::format("{:08x}", be32toh(i_tiDataArea->srcWord18HbWord7)); 371 i_map["0x2c HB Word 8"] = 372 std::format("{:08x}", be32toh(i_tiDataArea->srcWord19HbWord8)); 373 i_map["0x30 error_data"] = 374 std::format("{:08x}", be32toh(i_tiDataArea->asciiData0)); 375 i_map["0x34 EID"] = 376 std::format("{:08x}", be32toh(i_tiDataArea->asciiData1)); 377 } 378 379 } // namespace attn 380