1 #include <libpdbg.h> 2 3 #include <attn/attn_common.hpp> 4 #include <attn/attn_handler.hpp> 5 #include <attn/attn_logging.hpp> 6 #include <sdbusplus/bus.hpp> 7 #include <util/pdbg.hpp> 8 9 #include <iomanip> 10 #include <iostream> 11 #include <map> 12 13 namespace attn 14 { 15 16 /** @brief Traces some regs for hostboot */ 17 void addHbStatusRegs() 18 { 19 // Only do this for P10 systems 20 if (util::pdbg::queryHardwareAnalysisSupported()) 21 { 22 // We only need this for PRIMARY processor 23 pdbg_target* pibTarget = pdbg_target_from_path(nullptr, "/proc0/pib"); 24 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, "/proc0/fsi"); 25 26 uint32_t l_cfamData = 0xFFFFFFFF; 27 uint64_t l_scomData1 = 0xFFFFFFFFFFFFFFFFull; 28 uint64_t l_scomData2 = 0xFFFFFFFFFFFFFFFFull; 29 uint32_t l_cfamAddr = 0x283C; 30 uint64_t l_scomAddr1 = 0x4602F489; 31 uint64_t l_scomAddr2 = 0x4602F487; 32 33 if ((nullptr != fsiTarget) && (nullptr != pibTarget)) 34 { 35 // buffer for formatted strings (+1 for null, just in case) 36 char buffer[sizeof("some read error: 0x0123456789ABCDEF ")]; 37 38 // get first debug reg (CFAM) 39 if (RC_SUCCESS != fsi_read(fsiTarget, l_cfamAddr, &l_cfamData)) 40 { 41 sprintf(buffer, "cfam read error: 0x%08x", l_cfamAddr); 42 trace<level::ERROR>(buffer); 43 l_cfamData = 0xFFFFFFFF; 44 } 45 46 // Get SCOM regs next (just 2 of them) 47 if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr1, &l_scomData1)) 48 { 49 sprintf(buffer, "scom read error: 0x%016" PRIx64 "", 50 l_scomAddr1); 51 trace<level::ERROR>(buffer); 52 l_scomData1 = 0xFFFFFFFFFFFFFFFFull; 53 } 54 55 if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr2, &l_scomData2)) 56 { 57 sprintf(buffer, "scom read error: 0x%016" PRIx64 "", 58 l_scomAddr2); 59 trace<level::ERROR>(buffer); 60 l_scomData2 = 0xFFFFFFFFFFFFFFFFull; 61 } 62 } 63 64 // Trace out the results here of all 3 regs 65 // (Format should resemble FSP: HostBoot Reg:0000283C Data:AA801504 66 // 00000000 Proc:00050001 ) 67 std::stringstream ss1, ss2, ss3; 68 69 ss1 << "HostBoot Reg:" << std::setw(8) << std::setfill('0') << std::hex 70 << l_cfamAddr << " Data:" << l_cfamData << " Proc:00000000"; 71 72 ss2 << "HostBoot Reg:" << std::setw(8) << std::setfill('0') << std::hex 73 << l_scomAddr1 << " Data:" << std::setw(16) << l_scomData1 74 << " Proc:00000000"; 75 76 ss3 << "HostBoot Reg:" << std::setw(8) << std::setfill('0') << std::hex 77 << l_scomAddr2 << " Data:" << std::setw(16) << l_scomData2 78 << " Proc:00000000"; 79 80 std::string strobj1 = ss1.str(); 81 std::string strobj2 = ss2.str(); 82 std::string strobj3 = ss3.str(); 83 84 trace<level::INFO>(strobj1.c_str()); 85 trace<level::INFO>(strobj2.c_str()); 86 trace<level::INFO>(strobj3.c_str()); 87 } 88 89 return; 90 91 } // end addHbStatusRegs 92 93 /** @brief Check for recoverable errors present */ 94 bool recoverableErrors() 95 { 96 bool recoverableErrors = false; // assume no recoverable attentions 97 98 pdbg_target* target; 99 pdbg_for_each_class_target("proc", target) 100 { 101 if (PDBG_TARGET_ENABLED == pdbg_target_probe(target)) 102 { 103 auto proc = pdbg_target_index(target); // get processor number 104 105 // Use PIB target to determine if a processor is enabled 106 char path[16]; 107 sprintf(path, "/proc%d/pib", proc); 108 pdbg_target* pibTarget = pdbg_target_from_path(nullptr, path); 109 110 // sanity check 111 if (nullptr == pibTarget) 112 { 113 trace<level::INFO>("pib path or target not found"); 114 continue; 115 } 116 117 // check if pib target is enabled - indicates proc is enabled 118 if (PDBG_TARGET_ENABLED == pdbg_target_probe(pibTarget)) 119 { 120 // The processor FSI target is required for CFAM read 121 sprintf(path, "/proc%d/fsi", proc); 122 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path); 123 124 // sanity check 125 if (nullptr == fsiTarget) 126 { 127 trace<level::INFO>("fsi path or target not found"); 128 continue; 129 } 130 131 uint32_t isr_val = 0xffffffff; // invalid isr value 132 133 // get active attentions on processor 134 if (RC_SUCCESS != fsi_read(fsiTarget, 0x1007, &isr_val)) 135 { 136 // log cfam read error 137 trace<level::ERROR>("Error! cfam read 0x1007 FAILED"); 138 eventAttentionFail((int)AttnSection::attnHandler | 139 ATTN_PDBG_CFAM); 140 } 141 // check for invalid/stale value 142 else if (0xffffffff == isr_val) 143 { 144 trace<level::ERROR>("Error! cfam read 0x1007 INVALID"); 145 continue; 146 } 147 // check recoverable error status bit 148 else if (0 != (isr_val & RECOVERABLE_ATTN)) 149 { 150 recoverableErrors = true; 151 break; 152 } 153 } // fsi target enabled 154 } // pib target enabled 155 } // next processor 156 157 return recoverableErrors; 158 } 159 160 /** @brief timesec less-than-equal-to compare */ 161 bool operator<=(const timespec& lhs, const timespec& rhs) 162 { 163 if (lhs.tv_sec == rhs.tv_sec) 164 return lhs.tv_nsec <= rhs.tv_nsec; 165 else 166 return lhs.tv_sec <= rhs.tv_sec; 167 } 168 169 /** @brief sleep for n-seconds */ 170 void sleepSeconds(const unsigned int seconds) 171 { 172 auto count = seconds; 173 struct timespec requested, remaining; 174 175 while (0 < count) 176 { 177 requested.tv_sec = 1; 178 requested.tv_nsec = 0; 179 remaining = requested; 180 181 while (-1 == nanosleep(&requested, &remaining)) 182 { 183 // if not changing or implausible then abort 184 if (requested <= remaining) 185 { 186 break; 187 } 188 189 // back to sleep 190 requested = remaining; 191 } 192 count--; 193 } 194 } 195 196 } // namespace attn 197