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())); 153*91bf93e0SJayanth Othayoth 154*91bf93e0SJayanth Othayoth // Add CFAM register information. 155*91bf93e0SJayanth Othayoth addCFAMData(procTarget, clockDataLog); 156ed7fb7aeSJayanth Othayoth } 157ed7fb7aeSJayanth Othayoth 158ed7fb7aeSJayanth Othayoth openpower::pel::createPEL("org.open_power.PHAL.Info.ClockDailyLog", 159ed7fb7aeSJayanth Othayoth clockDataLog); 160ed7fb7aeSJayanth Othayoth } 161ed7fb7aeSJayanth Othayoth 162*91bf93e0SJayanth Othayoth void Manager::addCFAMData(struct pdbg_target* proc, 163*91bf93e0SJayanth Othayoth openpower::pel::FFDCData& clockDataLog) 164*91bf93e0SJayanth Othayoth { 165*91bf93e0SJayanth Othayoth 166*91bf93e0SJayanth Othayoth // collect Processor CFAM register data 167*91bf93e0SJayanth Othayoth const std::vector<int> procCFAMAddr = { 168*91bf93e0SJayanth Othayoth 0x1007, 0x2804, 0x2810, 0x2813, 0x2814, 0x2815, 0x2816, 0x281D, 0x281E}; 169*91bf93e0SJayanth Othayoth 170*91bf93e0SJayanth Othayoth auto index = std::to_string(pdbg_target_index(proc)); 171*91bf93e0SJayanth Othayoth 172*91bf93e0SJayanth Othayoth for (int addr : procCFAMAddr) 173*91bf93e0SJayanth Othayoth { 174*91bf93e0SJayanth Othayoth auto val = 0xDEADBEEF; 175*91bf93e0SJayanth Othayoth try 176*91bf93e0SJayanth Othayoth { 177*91bf93e0SJayanth Othayoth val = openpower::phal::pdbg::getCFAM(proc, addr); 178*91bf93e0SJayanth Othayoth } 179*91bf93e0SJayanth Othayoth catch (const std::exception& e) 180*91bf93e0SJayanth Othayoth { 181*91bf93e0SJayanth Othayoth error("getCFAM on {TARGET} thrown exception({ERROR}): Addr ({REG})", 182*91bf93e0SJayanth Othayoth "TARGET", pdbg_target_path(proc), "ERROR", e, "REG", addr); 183*91bf93e0SJayanth Othayoth } 184*91bf93e0SJayanth Othayoth std::stringstream ssData; 185*91bf93e0SJayanth Othayoth ssData << "0x" << std::setfill('0') << std::setw(8) << std::hex << val; 186*91bf93e0SJayanth Othayoth std::stringstream ssAddr; 187*91bf93e0SJayanth Othayoth ssAddr << "Proc" << index << " REG 0x" << std::hex << addr; 188*91bf93e0SJayanth Othayoth // update the data 189*91bf93e0SJayanth Othayoth clockDataLog.push_back(make_pair(ssAddr.str(), ssData.str())); 190*91bf93e0SJayanth Othayoth } 191*91bf93e0SJayanth Othayoth } 192*91bf93e0SJayanth Othayoth 193ed7fb7aeSJayanth Othayoth } // namespace openpower::phal::clock 194