1 /** 2 * Copyright © 2022 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "extensions/phal/clock_logger.hpp" 18 19 #include "util.hpp" 20 21 #include <attributes_info.H> 22 #include <libphal.H> 23 24 #include <phosphor-logging/lg2.hpp> 25 #include <sdeventplus/event.hpp> 26 #include <sdeventplus/utility/timer.hpp> 27 28 #include <chrono> 29 30 using namespace openpower::pel; 31 32 PHOSPHOR_LOG2_USING; 33 34 namespace openpower::phal::clock 35 { 36 constexpr auto CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR = 24; 37 38 Manager::Manager(const sdeventplus::Event& event) : 39 _event(event), timer(event, std::bind(&Manager::timerExpired, this)) 40 41 { 42 try 43 { 44 // pdbg initialisation 45 openpower::phal::pdbg::init(); 46 47 // Create clock data log. 48 createClockDataLog(); 49 } 50 catch (const std::exception& e) 51 { 52 error("Clock Data Log exception ({ERROR})", "ERROR", e); 53 } 54 55 addTimer(); 56 } 57 58 void Manager::addTimer() 59 { 60 // Set timer for 24 hours. 61 timer.restart(std::chrono::hours(CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR)); 62 } 63 64 void Manager::timerExpired() 65 { 66 info("Clock daily logging started"); 67 68 try 69 { 70 // Create clock data log. 71 createClockDataLog(); 72 } 73 catch (const std::exception& e) 74 { 75 error("createClockDataLog exception ({ERROR})", "ERROR", e); 76 } 77 } 78 79 void Manager::createClockDataLog() 80 { 81 // check chassis power state. 82 auto powerState = openpower::util::getChassisPowerState(); 83 84 if (powerState != "xyz.openbmc_project.State.Chassis.PowerState.On") 85 { 86 warning("The chassis power state({POWERSTATE}) is not ON, Skipping " 87 "clock data " 88 "logging", 89 "POWERSTATE", powerState); 90 return; 91 } 92 93 // Data logger storage 94 FFDCData clockDataLog; 95 96 struct pdbg_target* procTarget; 97 ATTR_HWAS_STATE_Type hwasState; 98 pdbg_for_each_class_target("proc", procTarget) 99 { 100 if (DT_GET_PROP(ATTR_HWAS_STATE, procTarget, hwasState)) 101 { 102 error("{TARGET} Could not read HWAS_STATE attribute", "TARGET", 103 pdbg_target_path(procTarget)); 104 continue; 105 } 106 if (!hwasState.present) 107 { 108 continue; 109 } 110 111 auto index = std::to_string(pdbg_target_index(procTarget)); 112 113 // update functional State 114 std::string funState = "Non Functional"; 115 116 if (hwasState.functional) 117 { 118 funState = "Functional"; 119 } 120 std::stringstream ssState; 121 ssState << "Proc" << index; 122 clockDataLog.push_back(std::make_pair(ssState.str(), funState)); 123 124 // update location code information 125 ATTR_LOCATION_CODE_Type locationCode; 126 memset(&locationCode, '\0', sizeof(locationCode)); 127 try 128 { 129 openpower::phal::pdbg::getLocationCode(procTarget, locationCode); 130 } 131 catch (const std::exception& e) 132 { 133 error("getLocationCode on {TARGET} thrown exception ({ERROR})", 134 "TARGET", pdbg_target_path(procTarget), "ERROR", e); 135 } 136 std::stringstream ssLoc; 137 ssLoc << "Proc" << index << " Location Code"; 138 clockDataLog.push_back(std::make_pair(ssLoc.str(), locationCode)); 139 140 // Update Processor EC level 141 ATTR_EC_Type ecVal = 0; 142 if (DT_GET_PROP(ATTR_EC, procTarget, ecVal)) 143 { 144 error("Could not read ATTR_EC attribute"); 145 } 146 std::stringstream ssEC; 147 ssEC << "Proc" << index << " EC"; 148 149 std::stringstream ssECVal; 150 ssECVal << "0x" << std::setfill('0') << std::setw(10) << std::hex 151 << (uint16_t)ecVal; 152 clockDataLog.push_back(std::make_pair(ssEC.str(), ssECVal.str())); 153 154 // Add CFAM register information. 155 addCFAMData(procTarget, clockDataLog); 156 } 157 158 openpower::pel::createPEL("org.open_power.PHAL.Info.ClockDailyLog", 159 clockDataLog); 160 } 161 162 void Manager::addCFAMData(struct pdbg_target* proc, 163 openpower::pel::FFDCData& clockDataLog) 164 { 165 166 // collect Processor CFAM register data 167 const std::vector<int> procCFAMAddr = { 168 0x1007, 0x2804, 0x2810, 0x2813, 0x2814, 0x2815, 0x2816, 0x281D, 0x281E}; 169 170 auto index = std::to_string(pdbg_target_index(proc)); 171 172 for (int addr : procCFAMAddr) 173 { 174 auto val = 0xDEADBEEF; 175 try 176 { 177 val = openpower::phal::pdbg::getCFAM(proc, addr); 178 } 179 catch (const std::exception& e) 180 { 181 error("getCFAM on {TARGET} thrown exception({ERROR}): Addr ({REG})", 182 "TARGET", pdbg_target_path(proc), "ERROR", e, "REG", addr); 183 } 184 std::stringstream ssData; 185 ssData << "0x" << std::setfill('0') << std::setw(8) << std::hex << val; 186 std::stringstream ssAddr; 187 ssAddr << "Proc" << index << " REG 0x" << std::hex << addr; 188 // update the data 189 clockDataLog.push_back(make_pair(ssAddr.str(), ssData.str())); 190 } 191 } 192 193 } // namespace openpower::phal::clock 194