1ed7fb7aeSJayanth Othayoth /** 2ed7fb7aeSJayanth Othayoth * Copyright © 2022 IBM Corporation 3ed7fb7aeSJayanth Othayoth * 4ed7fb7aeSJayanth Othayoth * Licensed under the Apache License, Version 2.0 (the "License"); 5ed7fb7aeSJayanth Othayoth * you may not use this file except in compliance with the License. 6ed7fb7aeSJayanth Othayoth * You may obtain a copy of the License at 7ed7fb7aeSJayanth Othayoth * 8ed7fb7aeSJayanth Othayoth * http://www.apache.org/licenses/LICENSE-2.0 9ed7fb7aeSJayanth Othayoth * 10ed7fb7aeSJayanth Othayoth * Unless required by applicable law or agreed to in writing, software 11ed7fb7aeSJayanth Othayoth * distributed under the License is distributed on an "AS IS" BASIS, 12ed7fb7aeSJayanth Othayoth * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ed7fb7aeSJayanth Othayoth * See the License for the specific language governing permissions and 14ed7fb7aeSJayanth Othayoth * limitations under the License. 15ed7fb7aeSJayanth Othayoth */ 16ed7fb7aeSJayanth Othayoth 17ed7fb7aeSJayanth Othayoth #include "extensions/phal/clock_logger.hpp" 18ed7fb7aeSJayanth Othayoth 19ed7fb7aeSJayanth Othayoth #include "util.hpp" 20ed7fb7aeSJayanth Othayoth 21ed7fb7aeSJayanth Othayoth #include <attributes_info.H> 22ed7fb7aeSJayanth Othayoth #include <libphal.H> 23ed7fb7aeSJayanth Othayoth 24ed7fb7aeSJayanth Othayoth #include <phosphor-logging/lg2.hpp> 25ed7fb7aeSJayanth Othayoth #include <sdeventplus/event.hpp> 26ed7fb7aeSJayanth Othayoth #include <sdeventplus/utility/timer.hpp> 27ed7fb7aeSJayanth Othayoth 28ed7fb7aeSJayanth Othayoth #include <chrono> 29ed7fb7aeSJayanth Othayoth 30ed7fb7aeSJayanth Othayoth using namespace openpower::pel; 31ed7fb7aeSJayanth Othayoth 32ed7fb7aeSJayanth Othayoth PHOSPHOR_LOG2_USING; 33ed7fb7aeSJayanth Othayoth 34ed7fb7aeSJayanth Othayoth namespace openpower::phal::clock 35ed7fb7aeSJayanth Othayoth { 36ed7fb7aeSJayanth Othayoth constexpr auto CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR = 24; 37ed7fb7aeSJayanth Othayoth 38ed7fb7aeSJayanth Othayoth Manager::Manager(const sdeventplus::Event& event) : 39ed7fb7aeSJayanth Othayoth _event(event), timer(event, std::bind(&Manager::timerExpired, this)) 40ed7fb7aeSJayanth Othayoth 41ed7fb7aeSJayanth Othayoth { 42ed7fb7aeSJayanth Othayoth try 43ed7fb7aeSJayanth Othayoth { 44ed7fb7aeSJayanth Othayoth // pdbg initialisation 45ed7fb7aeSJayanth Othayoth openpower::phal::pdbg::init(); 46ed7fb7aeSJayanth Othayoth 47ed7fb7aeSJayanth Othayoth // Create clock data log. 48ed7fb7aeSJayanth Othayoth createClockDataLog(); 49ed7fb7aeSJayanth Othayoth } 50ed7fb7aeSJayanth Othayoth catch (const std::exception& e) 51ed7fb7aeSJayanth Othayoth { 52ed7fb7aeSJayanth Othayoth error("Clock Data Log exception ({ERROR})", "ERROR", e); 53ed7fb7aeSJayanth Othayoth } 54ed7fb7aeSJayanth Othayoth 55ed7fb7aeSJayanth Othayoth addTimer(); 56ed7fb7aeSJayanth Othayoth } 57ed7fb7aeSJayanth Othayoth 58ed7fb7aeSJayanth Othayoth void Manager::addTimer() 59ed7fb7aeSJayanth Othayoth { 60ed7fb7aeSJayanth Othayoth // Set timer for 24 hours. 61ed7fb7aeSJayanth Othayoth timer.restart(std::chrono::hours(CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR)); 62ed7fb7aeSJayanth Othayoth } 63ed7fb7aeSJayanth Othayoth 64ed7fb7aeSJayanth Othayoth void Manager::timerExpired() 65ed7fb7aeSJayanth Othayoth { 66ed7fb7aeSJayanth Othayoth info("Clock daily logging started"); 67ed7fb7aeSJayanth Othayoth 68ed7fb7aeSJayanth Othayoth try 69ed7fb7aeSJayanth Othayoth { 70ed7fb7aeSJayanth Othayoth // Create clock data log. 71ed7fb7aeSJayanth Othayoth createClockDataLog(); 72ed7fb7aeSJayanth Othayoth } 73ed7fb7aeSJayanth Othayoth catch (const std::exception& e) 74ed7fb7aeSJayanth Othayoth { 75ed7fb7aeSJayanth Othayoth error("createClockDataLog exception ({ERROR})", "ERROR", e); 76ed7fb7aeSJayanth Othayoth } 77ed7fb7aeSJayanth Othayoth } 78ed7fb7aeSJayanth Othayoth 79ed7fb7aeSJayanth Othayoth void Manager::createClockDataLog() 80ed7fb7aeSJayanth Othayoth { 81ed7fb7aeSJayanth Othayoth // check chassis power state. 82ed7fb7aeSJayanth Othayoth auto powerState = openpower::util::getChassisPowerState(); 83ed7fb7aeSJayanth Othayoth 84ed7fb7aeSJayanth Othayoth if (powerState != "xyz.openbmc_project.State.Chassis.PowerState.On") 85ed7fb7aeSJayanth Othayoth { 86ed7fb7aeSJayanth Othayoth warning("The chassis power state({POWERSTATE}) is not ON, Skipping " 87ed7fb7aeSJayanth Othayoth "clock data " 88ed7fb7aeSJayanth Othayoth "logging", 89ed7fb7aeSJayanth Othayoth "POWERSTATE", powerState); 90ed7fb7aeSJayanth Othayoth return; 91ed7fb7aeSJayanth Othayoth } 92ed7fb7aeSJayanth Othayoth 93ed7fb7aeSJayanth Othayoth // Data logger storage 94ed7fb7aeSJayanth Othayoth FFDCData clockDataLog; 95ed7fb7aeSJayanth Othayoth 96ed7fb7aeSJayanth Othayoth struct pdbg_target* procTarget; 97ed7fb7aeSJayanth Othayoth ATTR_HWAS_STATE_Type hwasState; 98ed7fb7aeSJayanth Othayoth pdbg_for_each_class_target("proc", procTarget) 99ed7fb7aeSJayanth Othayoth { 100ed7fb7aeSJayanth Othayoth if (DT_GET_PROP(ATTR_HWAS_STATE, procTarget, hwasState)) 101ed7fb7aeSJayanth Othayoth { 102ed7fb7aeSJayanth Othayoth error("{TARGET} Could not read HWAS_STATE attribute", "TARGET", 103ed7fb7aeSJayanth Othayoth pdbg_target_path(procTarget)); 104ed7fb7aeSJayanth Othayoth continue; 105ed7fb7aeSJayanth Othayoth } 106ed7fb7aeSJayanth Othayoth if (!hwasState.present) 107ed7fb7aeSJayanth Othayoth { 108ed7fb7aeSJayanth Othayoth continue; 109ed7fb7aeSJayanth Othayoth } 110ed7fb7aeSJayanth Othayoth 111ed7fb7aeSJayanth Othayoth auto index = std::to_string(pdbg_target_index(procTarget)); 112ed7fb7aeSJayanth Othayoth 113ed7fb7aeSJayanth Othayoth // update functional State 114ed7fb7aeSJayanth Othayoth std::string funState = "Non Functional"; 115ed7fb7aeSJayanth Othayoth 116ed7fb7aeSJayanth Othayoth if (hwasState.functional) 117ed7fb7aeSJayanth Othayoth { 118ed7fb7aeSJayanth Othayoth funState = "Functional"; 119ed7fb7aeSJayanth Othayoth } 120ed7fb7aeSJayanth Othayoth std::stringstream ssState; 121ed7fb7aeSJayanth Othayoth ssState << "Proc" << index; 122ed7fb7aeSJayanth Othayoth clockDataLog.push_back(std::make_pair(ssState.str(), funState)); 123ed7fb7aeSJayanth Othayoth 124ed7fb7aeSJayanth Othayoth // update location code information 125ed7fb7aeSJayanth Othayoth ATTR_LOCATION_CODE_Type locationCode; 126ed7fb7aeSJayanth Othayoth memset(&locationCode, '\0', sizeof(locationCode)); 127ed7fb7aeSJayanth Othayoth try 128ed7fb7aeSJayanth Othayoth { 129ed7fb7aeSJayanth Othayoth openpower::phal::pdbg::getLocationCode(procTarget, locationCode); 130ed7fb7aeSJayanth Othayoth } 131ed7fb7aeSJayanth Othayoth catch (const std::exception& e) 132ed7fb7aeSJayanth Othayoth { 133ed7fb7aeSJayanth Othayoth error("getLocationCode on {TARGET} thrown exception ({ERROR})", 134ed7fb7aeSJayanth Othayoth "TARGET", pdbg_target_path(procTarget), "ERROR", e); 135ed7fb7aeSJayanth Othayoth } 136ed7fb7aeSJayanth Othayoth std::stringstream ssLoc; 137ed7fb7aeSJayanth Othayoth ssLoc << "Proc" << index << " Location Code"; 138ed7fb7aeSJayanth Othayoth clockDataLog.push_back(std::make_pair(ssLoc.str(), locationCode)); 139ed7fb7aeSJayanth Othayoth 140ed7fb7aeSJayanth Othayoth // Update Processor EC level 141ed7fb7aeSJayanth Othayoth ATTR_EC_Type ecVal = 0; 142ed7fb7aeSJayanth Othayoth if (DT_GET_PROP(ATTR_EC, procTarget, ecVal)) 143ed7fb7aeSJayanth Othayoth { 144ed7fb7aeSJayanth Othayoth error("Could not read ATTR_EC attribute"); 145ed7fb7aeSJayanth Othayoth } 146ed7fb7aeSJayanth Othayoth std::stringstream ssEC; 147ed7fb7aeSJayanth Othayoth ssEC << "Proc" << index << " EC"; 148ed7fb7aeSJayanth Othayoth 149ed7fb7aeSJayanth Othayoth std::stringstream ssECVal; 150ed7fb7aeSJayanth Othayoth ssECVal << "0x" << std::setfill('0') << std::setw(10) << std::hex 151ed7fb7aeSJayanth Othayoth << (uint16_t)ecVal; 152ed7fb7aeSJayanth Othayoth clockDataLog.push_back(std::make_pair(ssEC.str(), ssECVal.str())); 15391bf93e0SJayanth Othayoth 15491bf93e0SJayanth Othayoth // Add CFAM register information. 15591bf93e0SJayanth Othayoth addCFAMData(procTarget, clockDataLog); 156ed7fb7aeSJayanth Othayoth } 157ed7fb7aeSJayanth Othayoth 158*5ffe7fb7SJayanth Othayoth // Add clock register information 159*5ffe7fb7SJayanth Othayoth addClockRegData(clockDataLog); 160*5ffe7fb7SJayanth Othayoth 161ed7fb7aeSJayanth Othayoth openpower::pel::createPEL("org.open_power.PHAL.Info.ClockDailyLog", 162ed7fb7aeSJayanth Othayoth clockDataLog); 163ed7fb7aeSJayanth Othayoth } 164ed7fb7aeSJayanth Othayoth 16591bf93e0SJayanth Othayoth void Manager::addCFAMData(struct pdbg_target* proc, 16691bf93e0SJayanth Othayoth openpower::pel::FFDCData& clockDataLog) 16791bf93e0SJayanth Othayoth { 16891bf93e0SJayanth Othayoth 16991bf93e0SJayanth Othayoth // collect Processor CFAM register data 17091bf93e0SJayanth Othayoth const std::vector<int> procCFAMAddr = { 17191bf93e0SJayanth Othayoth 0x1007, 0x2804, 0x2810, 0x2813, 0x2814, 0x2815, 0x2816, 0x281D, 0x281E}; 17291bf93e0SJayanth Othayoth 17391bf93e0SJayanth Othayoth auto index = std::to_string(pdbg_target_index(proc)); 17491bf93e0SJayanth Othayoth 17591bf93e0SJayanth Othayoth for (int addr : procCFAMAddr) 17691bf93e0SJayanth Othayoth { 17791bf93e0SJayanth Othayoth auto val = 0xDEADBEEF; 17891bf93e0SJayanth Othayoth try 17991bf93e0SJayanth Othayoth { 18091bf93e0SJayanth Othayoth val = openpower::phal::pdbg::getCFAM(proc, addr); 18191bf93e0SJayanth Othayoth } 18291bf93e0SJayanth Othayoth catch (const std::exception& e) 18391bf93e0SJayanth Othayoth { 18491bf93e0SJayanth Othayoth error("getCFAM on {TARGET} thrown exception({ERROR}): Addr ({REG})", 18591bf93e0SJayanth Othayoth "TARGET", pdbg_target_path(proc), "ERROR", e, "REG", addr); 18691bf93e0SJayanth Othayoth } 18791bf93e0SJayanth Othayoth std::stringstream ssData; 18891bf93e0SJayanth Othayoth ssData << "0x" << std::setfill('0') << std::setw(8) << std::hex << val; 18991bf93e0SJayanth Othayoth std::stringstream ssAddr; 19091bf93e0SJayanth Othayoth ssAddr << "Proc" << index << " REG 0x" << std::hex << addr; 19191bf93e0SJayanth Othayoth // update the data 19291bf93e0SJayanth Othayoth clockDataLog.push_back(make_pair(ssAddr.str(), ssData.str())); 19391bf93e0SJayanth Othayoth } 19491bf93e0SJayanth Othayoth } 19591bf93e0SJayanth Othayoth 196*5ffe7fb7SJayanth Othayoth void Manager::addClockRegData(openpower::pel::FFDCData& clockDataLog) 197*5ffe7fb7SJayanth Othayoth { 198*5ffe7fb7SJayanth Othayoth info("Adding clock register information to daily logger"); 199*5ffe7fb7SJayanth Othayoth 200*5ffe7fb7SJayanth Othayoth struct pdbg_target* clockTarget; 201*5ffe7fb7SJayanth Othayoth pdbg_for_each_class_target("oscrefclk", clockTarget) 202*5ffe7fb7SJayanth Othayoth { 203*5ffe7fb7SJayanth Othayoth ATTR_HWAS_STATE_Type hwasState; 204*5ffe7fb7SJayanth Othayoth if (DT_GET_PROP(ATTR_HWAS_STATE, clockTarget, hwasState)) 205*5ffe7fb7SJayanth Othayoth { 206*5ffe7fb7SJayanth Othayoth error("({TARGET}) Could not read HWAS_STATE attribute", "TARGET", 207*5ffe7fb7SJayanth Othayoth pdbg_target_path(clockTarget)); 208*5ffe7fb7SJayanth Othayoth continue; 209*5ffe7fb7SJayanth Othayoth } 210*5ffe7fb7SJayanth Othayoth 211*5ffe7fb7SJayanth Othayoth if (!hwasState.present) 212*5ffe7fb7SJayanth Othayoth { 213*5ffe7fb7SJayanth Othayoth continue; 214*5ffe7fb7SJayanth Othayoth } 215*5ffe7fb7SJayanth Othayoth 216*5ffe7fb7SJayanth Othayoth std::string funState = "Non Functional"; 217*5ffe7fb7SJayanth Othayoth 218*5ffe7fb7SJayanth Othayoth if (hwasState.functional) 219*5ffe7fb7SJayanth Othayoth { 220*5ffe7fb7SJayanth Othayoth funState = "Functional"; 221*5ffe7fb7SJayanth Othayoth } 222*5ffe7fb7SJayanth Othayoth 223*5ffe7fb7SJayanth Othayoth auto index = std::to_string(pdbg_target_index(clockTarget)); 224*5ffe7fb7SJayanth Othayoth 225*5ffe7fb7SJayanth Othayoth std::stringstream ssState; 226*5ffe7fb7SJayanth Othayoth ssState << "Clock" << index; 227*5ffe7fb7SJayanth Othayoth clockDataLog.push_back(std::make_pair(ssState.str(), funState)); 228*5ffe7fb7SJayanth Othayoth 229*5ffe7fb7SJayanth Othayoth // Add clcok device path information 230*5ffe7fb7SJayanth Othayoth std::stringstream ssName; 231*5ffe7fb7SJayanth Othayoth ssName << "Clock" << index << " path"; 232*5ffe7fb7SJayanth Othayoth clockDataLog.push_back( 233*5ffe7fb7SJayanth Othayoth std::make_pair(ssName.str(), pdbg_target_path(clockTarget))); 234*5ffe7fb7SJayanth Othayoth 235*5ffe7fb7SJayanth Othayoth auto status = pdbg_target_probe(clockTarget); 236*5ffe7fb7SJayanth Othayoth if (status != PDBG_TARGET_ENABLED) 237*5ffe7fb7SJayanth Othayoth { 238*5ffe7fb7SJayanth Othayoth continue; 239*5ffe7fb7SJayanth Othayoth } 240*5ffe7fb7SJayanth Othayoth 241*5ffe7fb7SJayanth Othayoth // Update Buffer with clock I2C register data. 242*5ffe7fb7SJayanth Othayoth auto constexpr I2C_READ_SIZE = 0x08; 243*5ffe7fb7SJayanth Othayoth auto constexpr I2C_ADDR_MAX = 0xFF; 244*5ffe7fb7SJayanth Othayoth 245*5ffe7fb7SJayanth Othayoth for (auto addr = 0; addr <= I2C_ADDR_MAX; addr += I2C_READ_SIZE) 246*5ffe7fb7SJayanth Othayoth { 247*5ffe7fb7SJayanth Othayoth std::stringstream ssData; 248*5ffe7fb7SJayanth Othayoth 249*5ffe7fb7SJayanth Othayoth uint8_t data[0x8]; 250*5ffe7fb7SJayanth Othayoth auto i2cRc = i2c_read(clockTarget, 0, addr, I2C_READ_SIZE, data); 251*5ffe7fb7SJayanth Othayoth if (i2cRc) 252*5ffe7fb7SJayanth Othayoth { 253*5ffe7fb7SJayanth Othayoth error("({TARGET}) I2C read error({ERROR}) reported {ADDRESS} ", 254*5ffe7fb7SJayanth Othayoth "TARGET", pdbg_target_path(clockTarget), "ERROR", i2cRc, 255*5ffe7fb7SJayanth Othayoth "ADDRESS", addr); 256*5ffe7fb7SJayanth Othayoth continue; 257*5ffe7fb7SJayanth Othayoth } 258*5ffe7fb7SJayanth Othayoth 259*5ffe7fb7SJayanth Othayoth for (auto i = 0; i < I2C_READ_SIZE; i++) 260*5ffe7fb7SJayanth Othayoth { 261*5ffe7fb7SJayanth Othayoth ssData << " " << std::hex << std::setfill('0') << std::setw(2) 262*5ffe7fb7SJayanth Othayoth << (uint16_t)data[i]; 263*5ffe7fb7SJayanth Othayoth } 264*5ffe7fb7SJayanth Othayoth std::stringstream ssAddr; 265*5ffe7fb7SJayanth Othayoth ssAddr << "Clock" << index << "_0x" << std::hex << std::setfill('0') 266*5ffe7fb7SJayanth Othayoth << std::setw(2) << addr; 267*5ffe7fb7SJayanth Othayoth clockDataLog.push_back(make_pair(ssAddr.str(), ssData.str())); 268*5ffe7fb7SJayanth Othayoth } 269*5ffe7fb7SJayanth Othayoth } 270*5ffe7fb7SJayanth Othayoth } 271*5ffe7fb7SJayanth Othayoth 272ed7fb7aeSJayanth Othayoth } // namespace openpower::phal::clock 273