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 #include <util/trace.hpp> 9 10 #include <iomanip> 11 #include <iostream> 12 #include <map> 13 14 namespace attn 15 { 16 17 /** @brief Traces some regs for hostboot */ 18 void addHbStatusRegs() 19 { 20 // Only do this for P10 systems 21 if (util::pdbg::queryHardwareAnalysisSupported()) 22 { 23 // We only need this for PRIMARY processor 24 pdbg_target* pibTarget = pdbg_target_from_path(nullptr, "/proc0/pib"); 25 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, "/proc0/fsi"); 26 27 uint32_t l_cfamData = 0xFFFFFFFF; 28 uint64_t l_scomData1 = 0xFFFFFFFFFFFFFFFFull; 29 uint64_t l_scomData2 = 0xFFFFFFFFFFFFFFFFull; 30 uint32_t l_cfamAddr = 0x283C; 31 uint64_t l_scomAddr1 = 0x4602F489; 32 uint64_t l_scomAddr2 = 0x4602F487; 33 34 if ((nullptr != fsiTarget) && (nullptr != pibTarget)) 35 { 36 // get first debug reg (CFAM) 37 if (RC_SUCCESS != fsi_read(fsiTarget, l_cfamAddr, &l_cfamData)) 38 { 39 trace::err("cfam read error: 0x%08x", l_cfamAddr); 40 l_cfamData = 0xFFFFFFFF; 41 } 42 43 // Get SCOM regs next (just 2 of them) 44 if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr1, &l_scomData1)) 45 { 46 trace::err("scom read error: 0x%016" PRIx64 "", l_scomAddr1); 47 l_scomData1 = 0xFFFFFFFFFFFFFFFFull; 48 } 49 50 if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr2, &l_scomData2)) 51 { 52 trace::err("scom read error: 0x%016" PRIx64 "", l_scomAddr2); 53 l_scomData2 = 0xFFFFFFFFFFFFFFFFull; 54 } 55 } 56 57 // Trace out the results here of all 3 regs 58 // (Format should resemble FSP: HostBoot Reg:0000283C Data:AA801504 59 // 00000000 Proc:00050001 ) 60 trace::inf("HostBoot Reg:%08x Data:%08x Proc:00000000", l_cfamAddr, 61 l_cfamData); 62 trace::inf("HostBoot Reg:%08" PRIx64 " Data:%016" PRIx64 63 " Proc:00000000", 64 l_scomAddr1, l_scomData1); 65 trace::inf("HostBoot Reg:%08" PRIx64 " Data:%016" PRIx64 66 " Proc:00000000", 67 l_scomAddr2, l_scomData2); 68 } 69 70 return; 71 72 } // end addHbStatusRegs 73 74 /** @brief Capture some scratch registers for PRD */ 75 void addPrdScratchRegs(std::vector<util::FFDCFile>& o_files) 76 { 77 // Get primary processor FSI target for CFAM reads 78 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, "/proc0/fsi"); 79 80 if (nullptr == fsiTarget) 81 { 82 trace::err("error getting scratch register target"); 83 } 84 else 85 { 86 uint32_t chipId = 0; 87 uint32_t signatureId = 0; 88 89 // get scratch register 9 (CFAM) 90 if (RC_SUCCESS != fsi_read(fsiTarget, 0x2980, &chipId)) 91 { 92 trace::err("error reading scratch register 9"); 93 chipId = 0; 94 } 95 96 // get scratch register 10 (CFAM) 97 if (RC_SUCCESS != fsi_read(fsiTarget, 0x2981, &signatureId)) 98 { 99 trace::err("error reading scratch register 10"); 100 signatureId = 0; 101 } 102 103 // Add data to traces and create user data section 104 if (0 != chipId || 0 != signatureId) 105 { 106 // trace scratch register data 107 trace::inf("PRD scratch Proc0, Chip ID: %08x, Signature ID: %08x", 108 chipId, signatureId); 109 110 // create ffdc data for user data section 111 try 112 { 113 util::FFDCFile file{util::FFDCFormat::Text}; 114 int fd = file.getFileDescriptor(); 115 char buffer[150]; 116 int len = sprintf(buffer, 117 "Scratch Register Error Signature\n" 118 "Processor : 0\n" 119 "Chip ID : %08x\n" 120 "Signature ID : %08x\n", 121 chipId, signatureId); 122 if (write(fd, buffer, len) < 0) 123 { 124 trace::err("error writing scratch register user data"); 125 } 126 else 127 { 128 o_files.push_back(std::move(file)); 129 } 130 } 131 catch (const std::exception& e) 132 { 133 trace::err( 134 "exception when creating scratch register user data"); 135 trace::inf(e.what()); 136 } 137 } 138 } 139 140 return; 141 } 142 143 /** @brief Check for recoverable errors present */ 144 bool recoverableErrors() 145 { 146 bool recoverableErrors = false; // assume no recoverable attentions 147 148 pdbg_target* target; 149 pdbg_for_each_class_target("proc", target) 150 { 151 if (PDBG_TARGET_ENABLED == pdbg_target_probe(target)) 152 { 153 auto proc = pdbg_target_index(target); // get processor number 154 155 // Use PIB target to determine if a processor is enabled 156 char path[16]; 157 sprintf(path, "/proc%d/pib", proc); 158 pdbg_target* pibTarget = pdbg_target_from_path(nullptr, path); 159 160 // sanity check 161 if (nullptr == pibTarget) 162 { 163 trace::inf("pib path or target not found"); 164 continue; 165 } 166 167 // check if pib target is enabled - indicates proc is enabled 168 if (PDBG_TARGET_ENABLED == pdbg_target_probe(pibTarget)) 169 { 170 // The processor FSI target is required for CFAM read 171 sprintf(path, "/proc%d/fsi", proc); 172 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path); 173 174 // sanity check 175 if (nullptr == fsiTarget) 176 { 177 trace::inf("fsi path or target not found"); 178 continue; 179 } 180 181 uint32_t isr_val = 0xffffffff; // invalid isr value 182 183 // get active attentions on processor 184 if (RC_SUCCESS != fsi_read(fsiTarget, 0x1007, &isr_val)) 185 { 186 // log cfam read error 187 trace::err("cfam read 0x1007 FAILED"); 188 eventAttentionFail((int)AttnSection::attnHandler | 189 ATTN_PDBG_CFAM); 190 } 191 // check for invalid/stale value 192 else if (0xffffffff == isr_val) 193 { 194 trace::err("cfam read 0x1007 INVALID"); 195 continue; 196 } 197 // check recoverable error status bit 198 else if (0 != (isr_val & RECOVERABLE_ATTN)) 199 { 200 recoverableErrors = true; 201 break; 202 } 203 } // fsi target enabled 204 } // pib target enabled 205 } // next processor 206 207 return recoverableErrors; 208 } 209 210 /** @brief timesec less-than-equal-to compare */ 211 bool operator<=(const timespec& lhs, const timespec& rhs) 212 { 213 if (lhs.tv_sec == rhs.tv_sec) 214 return lhs.tv_nsec <= rhs.tv_nsec; 215 else 216 return lhs.tv_sec <= rhs.tv_sec; 217 } 218 219 /** @brief sleep for n-seconds */ 220 void sleepSeconds(const unsigned int seconds) 221 { 222 auto count = seconds; 223 struct timespec requested, remaining; 224 225 while (0 < count) 226 { 227 requested.tv_sec = 1; 228 requested.tv_nsec = 0; 229 remaining = requested; 230 231 while (-1 == nanosleep(&requested, &remaining)) 232 { 233 // if not changing or implausible then abort 234 if (requested <= remaining) 235 { 236 break; 237 } 238 239 // back to sleep 240 requested = remaining; 241 } 242 count--; 243 } 244 } 245 246 } // namespace attn 247