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