// Copyright (c) 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "speed_select.hpp"

#include "cpuinfo.hpp"
#include "cpuinfo_utils.hpp"

#include <peci.h>

#include <boost/asio/steady_timer.hpp>
#include <xyz/openbmc_project/Common/Device/error.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/Control/Processor/CurrentOperatingConfig/server.hpp>
#include <xyz/openbmc_project/Inventory/Item/Cpu/OperatingConfig/server.hpp>

#include <iostream>
#include <memory>
#include <string>

namespace cpu_info
{
namespace sst
{

class PECIError : public std::runtime_error
{
    using std::runtime_error::runtime_error;
};

constexpr uint64_t bit(int index)
{
    return (1ull << index);
}

constexpr int extendedModel(CPUModel model)
{
    return (model >> 16) & 0xF;
}

constexpr bool modelSupportsDiscovery(CPUModel model)
{
    return extendedModel(model) >= extendedModel(icx);
}

constexpr bool modelSupportsControl(CPUModel model)
{
    return extendedModel(model) > extendedModel(icx);
}

/**
 * Construct a list of indexes of the set bits in the input value.
 * E.g. fn(0x7A) -> {1,3,4,5,6}
 *
 * @param[in]   mask    Bitmask to convert.
 *
 * @return  List of bit indexes.
 */
static std::vector<uint32_t> convertMaskToList(std::bitset<64> mask)
{
    std::vector<uint32_t> bitList;
    for (size_t i = 0; i < mask.size(); ++i)
    {
        if (mask.test(i))
        {
            bitList.push_back(i);
        }
    }
    return bitList;
}

static bool checkPECIStatus(EPECIStatus libStatus, uint8_t completionCode)
{
    if (libStatus != PECI_CC_SUCCESS || completionCode != PECI_DEV_CC_SUCCESS)
    {
        std::cerr << "PECI command failed."
                  << " Driver Status = " << libStatus << ","
                  << " Completion Code = " << static_cast<int>(completionCode)
                  << '\n';
        return false;
    }
    return true;
}

/**
 * Convenience RAII object for Wake-On-PECI (WOP) management, since PECI Config
 * Local accesses to the OS Mailbox require the package to pop up to PC2. Also
 * provides PCode OS Mailbox routine.
 *
 * Since multiple applications may be modifing WOP, we'll use this algorithm:
 * Whenever a PECI command fails with associated error code, set WOP bit and
 * retry command. Upon manager destruction, clear WOP bit only if we previously
 * set it.
 */
struct PECIManager
{
    int peciAddress;
    bool peciWoken;
    CPUModel cpuModel;
    int mbBus;

    PECIManager(int address, CPUModel model) :
        peciAddress(address), peciWoken(false), cpuModel(model)
    {
        mbBus = (model == icx) ? 14 : 31;
    }

    ~PECIManager()
    {
        // If we're being destroyed due to a PECIError, try to clear the mode
        // bit, but catch and ignore any duplicate error it might raise to
        // prevent termination.
        try
        {
            if (peciWoken)
            {
                setWakeOnPECI(false);
            }
        }
        catch (const PECIError& err)
        {}
    }

    static bool isSleeping(EPECIStatus libStatus, uint8_t completionCode)
    {
        // PECI completion code defined in peci-ioctl.h which is not available
        // for us to include.
        constexpr int PECI_DEV_CC_UNAVAIL_RESOURCE = 0x82;
        // Observed library returning DRIVER_ERR for reads and TIMEOUT for
        // writes while PECI is sleeping. Either way, the completion code from
        // PECI client should be reliable indicator of need to set WOP.
        return libStatus != PECI_CC_SUCCESS &&
               completionCode == PECI_DEV_CC_UNAVAIL_RESOURCE;
    }

    /**
     * Send a single PECI PCS write to modify the Wake-On-PECI mode bit
     */
    void setWakeOnPECI(bool enable)
    {
        uint8_t completionCode;
        EPECIStatus libStatus =
            peci_WrPkgConfig(peciAddress, 5, enable ? 1 : 0, 0,
                             sizeof(uint32_t), &completionCode);
        if (!checkPECIStatus(libStatus, completionCode))
        {
            throw PECIError("Failed to set Wake-On-PECI mode bit");
        }

        if (enable)
        {
            peciWoken = true;
        }
    }

    // PCode OS Mailbox interface register locations
    static constexpr int mbSegment = 0;
    static constexpr int mbDevice = 30;
    static constexpr int mbFunction = 1;
    static constexpr int mbDataReg = 0xA0;
    static constexpr int mbInterfaceReg = 0xA4;
    static constexpr int mbRegSize = sizeof(uint32_t);

    enum class MailboxStatus
    {
        NoError = 0x0,
        InvalidCommand = 0x1,
        IllegalData = 0x16
    };

    /**
     * Send a single Write PCI Config Local command, targeting the PCU CR1
     * register block.
     *
     * @param[in]   regAddress  PCI Offset of register.
     * @param[in]   data        Data to write.
     */
    void wrMailboxReg(uint16_t regAddress, uint32_t data)
    {
        uint8_t completionCode;
        bool tryWaking = true;
        while (true)
        {
            EPECIStatus libStatus = peci_WrEndPointPCIConfigLocal(
                peciAddress, mbSegment, mbBus, mbDevice, mbFunction, regAddress,
                mbRegSize, data, &completionCode);
            if (tryWaking && isSleeping(libStatus, completionCode))
            {
                setWakeOnPECI(true);
                tryWaking = false;
                continue;
            }
            else if (!checkPECIStatus(libStatus, completionCode))
            {
                throw PECIError("Failed to write mailbox reg");
            }
            break;
        }
    }

    /**
     * Send a single Read PCI Config Local command, targeting the PCU CR1
     * register block.
     *
     * @param[in]   regAddress  PCI offset of register.
     *
     * @return  Register value
     */
    uint32_t rdMailboxReg(uint16_t regAddress)
    {
        uint8_t completionCode;
        uint32_t outputData;
        bool tryWaking = true;
        while (true)
        {
            EPECIStatus libStatus = peci_RdEndPointConfigPciLocal(
                peciAddress, mbSegment, mbBus, mbDevice, mbFunction, regAddress,
                mbRegSize, reinterpret_cast<uint8_t*>(&outputData),
                &completionCode);
            if (tryWaking && isSleeping(libStatus, completionCode))
            {
                setWakeOnPECI(true);
                tryWaking = false;
                continue;
            }
            if (!checkPECIStatus(libStatus, completionCode))
            {
                throw PECIError("Failed to read mailbox reg");
            }
            break;
        }
        return outputData;
    }

    /**
     * Send command on PCode OS Mailbox interface.
     *
     * @param[in]   command     Main command ID.
     * @param[in]   subCommand  Sub command ID.
     * @param[in]   inputData   Data to put in mailbox. Is always written, but
     *                          will be ignored by PCode if command is a
     *                          "getter".
     * @param[out]  responseCode    Optional parameter to receive the
     *                              mailbox-level response status. If null, a
     *                              PECIError will be thrown for error status.
     *
     * @return  Data returned in mailbox. Value is undefined if command is a
     *          "setter".
     */
    uint32_t sendPECIOSMailboxCmd(uint8_t command, uint8_t subCommand,
                                  uint32_t inputData = 0,
                                  MailboxStatus* responseCode = nullptr)
    {
        // The simple mailbox algorithm just says to wait until the busy bit
        // is clear, but we'll give up after 10 tries. It's arbitrary but that's
        // quite long wall clock time.
        constexpr int mbRetries = 10;
        constexpr uint32_t mbBusyBit = bit(31);

        // Wait until RUN_BUSY == 0
        int attempts = mbRetries;
        while ((rdMailboxReg(mbInterfaceReg) & mbBusyBit) != 0 &&
               --attempts > 0)
            ;
        if (attempts == 0)
        {
            throw PECIError("OS Mailbox failed to become free");
        }

        // Write required command specific input data to data register
        wrMailboxReg(mbDataReg, inputData);

        // Write required command specific command/sub-command values and set
        // RUN_BUSY bit in interface register.
        uint32_t interfaceReg =
            mbBusyBit | (static_cast<uint32_t>(subCommand) << 8) | command;
        wrMailboxReg(mbInterfaceReg, interfaceReg);

        // Wait until RUN_BUSY == 0
        attempts = mbRetries;
        do
        {
            interfaceReg = rdMailboxReg(mbInterfaceReg);
        } while ((interfaceReg & mbBusyBit) != 0 && --attempts > 0);
        if (attempts == 0)
        {
            throw PECIError("OS Mailbox failed to return");
        }

        // Read command return status or error code from interface register
        auto status = static_cast<MailboxStatus>(interfaceReg & 0xFF);
        if (responseCode != nullptr)
        {
            *responseCode = status;
        }
        else if (status != MailboxStatus::NoError)
        {
            throw PECIError(std::string("OS Mailbox returned with error: ") +
                            std::to_string(static_cast<int>(status)));
        }

        // Read command return data from the data register
        return rdMailboxReg(mbDataReg);
    }
};

/**
 * Base class for set of PECI OS Mailbox commands.
 * Constructing it runs the command and stores the value for use by derived
 * class accessor methods.
 */
template <uint8_t subcommand>
struct OsMailboxCommand
{
    enum ErrorPolicy
    {
        Throw,
        NoThrow
    };

    uint32_t value;
    PECIManager::MailboxStatus status;
    /**
     * Construct the command object with required PECI address and up to 4
     * optional 1-byte input data parameters.
     */
    OsMailboxCommand(PECIManager& pm, uint8_t param1 = 0, uint8_t param2 = 0,
                     uint8_t param3 = 0, uint8_t param4 = 0) :
        OsMailboxCommand(pm, ErrorPolicy::Throw, param1, param2, param3, param4)
    {}

    OsMailboxCommand(PECIManager& pm, ErrorPolicy errorPolicy,
                     uint8_t param1 = 0, uint8_t param2 = 0, uint8_t param3 = 0,
                     uint8_t param4 = 0)
    {
        PECIManager::MailboxStatus* callStatus =
            errorPolicy == Throw ? nullptr : &status;
        uint32_t param =
            (param4 << 24) | (param3 << 16) | (param2 << 8) | param1;
        value = pm.sendPECIOSMailboxCmd(0x7F, subcommand, param, callStatus);
    }

    /** Return whether the mailbox status indicated success or not. */
    bool success() const
    {
        return status == PECIManager::MailboxStatus::NoError;
    }
};

/**
 * Macro to define a derived class accessor method.
 *
 * @param[in]   type    Return type of accessor method.
 * @param[in]   name    Name of accessor method.
 * @param[in]   hibit   Most significant bit of field to access.
 * @param[in]   lobit   Least significant bit of field to access.
 */
#define FIELD(type, name, hibit, lobit)                                        \
    type name() const                                                          \
    {                                                                          \
        return (value >> lobit) & (bit(hibit - lobit + 1) - 1);                \
    }

struct GetLevelsInfo : OsMailboxCommand<0x0>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(bool, enabled, 31, 31)
    FIELD(bool, lock, 24, 24)
    FIELD(int, currentConfigTdpLevel, 23, 16)
    FIELD(int, configTdpLevels, 15, 8)
    FIELD(int, version, 7, 0)
};

struct GetConfigTdpControl : OsMailboxCommand<0x1>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(bool, pbfEnabled, 17, 17);
    FIELD(bool, factEnabled, 16, 16);
    FIELD(bool, pbfSupport, 1, 1);
    FIELD(bool, factSupport, 0, 0);
};

struct SetConfigTdpControl : OsMailboxCommand<0x2>
{
    using OsMailboxCommand::OsMailboxCommand;
};

struct GetTdpInfo : OsMailboxCommand<0x3>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(int, tdpRatio, 23, 16);
    FIELD(int, pkgTdp, 14, 0);
};

struct GetCoreMask : OsMailboxCommand<0x6>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(uint32_t, coresMask, 31, 0);
};

struct GetTurboLimitRatios : OsMailboxCommand<0x7>
{
    using OsMailboxCommand::OsMailboxCommand;
};

struct SetLevel : OsMailboxCommand<0x8>
{
    using OsMailboxCommand::OsMailboxCommand;
};

struct GetRatioInfo : OsMailboxCommand<0xC>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(int, pm, 31, 24);
    FIELD(int, pn, 23, 16);
    FIELD(int, p1, 15, 8);
    FIELD(int, p0, 7, 0);
};

struct GetTjmaxInfo : OsMailboxCommand<0x5>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(int, tProchot, 7, 0);
};

struct PbfGetCoreMaskInfo : OsMailboxCommand<0x20>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(uint32_t, p1HiCoreMask, 31, 0);
};

struct PbfGetP1HiP1LoInfo : OsMailboxCommand<0x21>
{
    using OsMailboxCommand::OsMailboxCommand;
    FIELD(int, p1Hi, 15, 8);
    FIELD(int, p1Lo, 7, 0);
};

using BaseCurrentOperatingConfig =
    sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::Control::
                                    Processor::server::CurrentOperatingConfig>;

using BaseOperatingConfig =
    sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::Inventory::
                                    Item::Cpu::server::OperatingConfig>;

class OperatingConfig : public BaseOperatingConfig
{
  public:
    std::string path;
    int level;

  public:
    using BaseOperatingConfig::BaseOperatingConfig;
    OperatingConfig(sdbusplus::bus::bus& bus, int level_, std::string path_) :
        BaseOperatingConfig(bus, path_.c_str(), action::defer_emit),
        path(std::move(path_)), level(level_)
    {}
};

class CPUConfig : public BaseCurrentOperatingConfig
{
  private:
    /** Objects describing all available SST configs - not modifiable. */
    std::vector<std::unique_ptr<OperatingConfig>> availConfigs;
    sdbusplus::bus::bus& bus;
    const int peciAddress;
    const std::string path; ///< D-Bus path of CPU object
    const CPUModel cpuModel;
    const bool modificationAllowed;

    // Keep mutable copies of the properties so we can cache values that we
    // retrieve in the getters. We don't want to throw an error on a D-Bus
    // get-property call (extra error handling in clients), so by caching we can
    // hide any temporary hiccup in PECI communication.
    // These values can be changed by in-band software so we have to do a full
    // PECI read on every get-property, and can't assume that values will change
    // only when set-property is done.
    mutable int currentLevel;
    mutable bool bfEnabled;
    /**
     * Cached SST-TF enablement status. This is not exposed on D-Bus, but it's
     * needed because the command SetConfigTdpControl requires setting both
     * bits at once.
     */
    mutable bool tfEnabled;

    /**
     * Enforce common pre-conditions for D-Bus set property handlers.
     */
    void setPropertyCheckOrThrow()
    {
        if (!modificationAllowed)
        {
            throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
        }
        if (hostState != HostState::postComplete)
        {
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }
    }

  public:
    CPUConfig(sdbusplus::bus::bus& bus_, int index, CPUModel model) :
        BaseCurrentOperatingConfig(bus_, generatePath(index).c_str(),
                                   action::defer_emit),
        bus(bus_), peciAddress(index + MIN_CLIENT_ADDR),
        path(generatePath(index)), cpuModel(model),
        modificationAllowed(modelSupportsControl(model)), currentLevel(0),
        bfEnabled(false), tfEnabled(false)
    {}

    //
    // D-Bus Property Overrides
    //

    sdbusplus::message::object_path appliedConfig() const override
    {
        // If CPU is powered off, return power-up default value of Level 0.
        int level = 0;
        if (hostState != HostState::off)
        {
            // Otherwise, try to read current state
            try
            {
                PECIManager pm(peciAddress, cpuModel);
                currentLevel = GetLevelsInfo(pm).currentConfigTdpLevel();
            }
            catch (const PECIError& error)
            {
                std::cerr << "Failed to get SST-PP level: " << error.what()
                          << "\n";
            }
            level = currentLevel;
        }
        return generateConfigPath(level);
    }

    bool baseSpeedPriorityEnabled() const override
    {
        bool enabled = false;
        if (hostState != HostState::off)
        {
            try
            {
                PECIManager pm(peciAddress, cpuModel);
                GetConfigTdpControl tdpControl(pm, currentLevel);
                bfEnabled = tdpControl.pbfEnabled();
                tfEnabled = tdpControl.factEnabled();
            }
            catch (const PECIError& error)
            {
                std::cerr << "Failed to get SST-BF status: " << error.what()
                          << "\n";
            }
            enabled = bfEnabled;
        }
        return enabled;
    }

    sdbusplus::message::object_path
        appliedConfig(sdbusplus::message::object_path value) override
    {
        setPropertyCheckOrThrow();

        const OperatingConfig* newConfig = nullptr;
        for (const auto& config : availConfigs)
        {
            if (config->path == value.str)
            {
                newConfig = config.get();
            }
        }

        if (newConfig == nullptr)
        {
            throw sdbusplus::xyz::openbmc_project::Common::Error::
                InvalidArgument();
        }

        try
        {
            PECIManager pm(peciAddress, cpuModel);
            SetLevel(pm, newConfig->level);
            currentLevel = newConfig->level;
        }
        catch (const PECIError& error)
        {
            std::cerr << "Failed to set new SST-PP level: " << error.what()
                      << "\n";
            throw sdbusplus::xyz::openbmc_project::Common::Device::Error::
                WriteFailure();
        }

        // return value not used
        return sdbusplus::message::object_path();
    }

    bool baseSpeedPriorityEnabled(bool value) override
    {
        setPropertyCheckOrThrow();

        try
        {
            constexpr uint32_t bfEnabledBit = bit(17);
            constexpr uint32_t tfEnabledBit = bit(16);
            PECIManager pm(peciAddress, cpuModel);
            uint32_t param =
                (value ? bfEnabledBit : 0) | (tfEnabled ? tfEnabledBit : 0);
            SetConfigTdpControl tdpControl(pm, 0, 0, param >> 16);
        }
        catch (const PECIError& error)
        {
            std::cerr << "Failed to set SST-BF status: " << error.what()
                      << "\n";
            throw sdbusplus::xyz::openbmc_project::Common::Device::Error::
                WriteFailure();
        }

        // return value not used
        return false;
    }

    //
    // Additions
    //

    OperatingConfig& newConfig(int level)
    {
        availConfigs.emplace_back(std::make_unique<OperatingConfig>(
            bus, level, generateConfigPath(level)));
        return *availConfigs.back();
    }

    std::string generateConfigPath(int level) const
    {
        return path + "/config" + std::to_string(level);
    }

    /**
     * Emit the interface added signals which were deferred. This is required
     * for ObjectMapper to pick up the objects, if we initially defered the
     * signal emitting.
     */
    void finalize()
    {
        emit_added();
        for (auto& config : availConfigs)
        {
            config->emit_added();
        }
    }

    static std::string generatePath(int index)
    {
        return phosphor::cpu_info::cpuPath + std::to_string(index);
    }
};

/**
 * Retrieve the SST parameters for a single config and fill the values into the
 * properties on the D-Bus interface.
 *
 * @param[in,out]   peciManager     PECI context to use.
 * @param[in]       level           Config TDP level to retrieve.
 * @param[out]      config          D-Bus interface to update.
 * @param[in]       trlCores        Turbo ratio limit core ranges from MSR
 *                                  0x1AE. This is constant across all configs
 *                                  in a CPU.
 */
static void getSingleConfig(PECIManager& peciManager, int level,
                            OperatingConfig& config, uint64_t trlCores)
{
    constexpr int mhzPerRatio = 100;

    // PowerLimit <= GET_TDP_INFO.PKG_TDP
    config.powerLimit(GetTdpInfo(peciManager, level).pkgTdp());

    // AvailableCoreCount <= GET_CORE_MASK.CORES_MASK
    uint64_t coreMaskLo = GetCoreMask(peciManager, level, 0).coresMask();
    uint64_t coreMaskHi = GetCoreMask(peciManager, level, 1).coresMask();
    std::bitset<64> coreMask = (coreMaskHi << 32) | coreMaskLo;
    config.availableCoreCount(coreMask.count());

    // BaseSpeed <= GET_RATIO_INFO.P1
    GetRatioInfo getRatioInfo(peciManager, level);
    config.baseSpeed(getRatioInfo.p1() * mhzPerRatio);

    // MaxSpeed <= GET_RATIO_INFO.P0
    config.maxSpeed(getRatioInfo.p0() * mhzPerRatio);

    // MaxJunctionTemperature <= GET_TJMAX_INFO.T_PROCHOT
    config.maxJunctionTemperature(GetTjmaxInfo(peciManager, level).tProchot());

    // Construct BaseSpeedPrioritySettings
    GetConfigTdpControl getConfigTdpControl(peciManager, level);
    std::vector<std::tuple<uint32_t, std::vector<uint32_t>>> baseSpeeds;
    if (getConfigTdpControl.pbfSupport())
    {
        coreMaskLo = PbfGetCoreMaskInfo(peciManager, level, 0).p1HiCoreMask();
        coreMaskHi = PbfGetCoreMaskInfo(peciManager, level, 1).p1HiCoreMask();
        std::bitset<64> hiFreqCoreMask = (coreMaskHi << 32) | coreMaskLo;

        std::vector<uint32_t> hiFreqCoreList, loFreqCoreList;
        hiFreqCoreList = convertMaskToList(hiFreqCoreMask);
        loFreqCoreList = convertMaskToList(coreMask & ~hiFreqCoreMask);

        PbfGetP1HiP1LoInfo pbfGetP1HiP1LoInfo(peciManager, level);
        baseSpeeds = {
            {pbfGetP1HiP1LoInfo.p1Hi() * mhzPerRatio, hiFreqCoreList},
            {pbfGetP1HiP1LoInfo.p1Lo() * mhzPerRatio, loFreqCoreList}};
    }
    config.baseSpeedPrioritySettings(baseSpeeds);

    // Construct TurboProfile
    std::vector<std::tuple<uint32_t, size_t>> turboSpeeds;

    // Only read the SSE ratios (don't need AVX2/AVX512).
    uint64_t limitRatioLo = GetTurboLimitRatios(peciManager, level, 0, 0).value;
    uint64_t limitRatioHi = GetTurboLimitRatios(peciManager, level, 1, 0).value;
    uint64_t limitRatios = (limitRatioHi << 32) | limitRatioLo;

    constexpr int maxTFBuckets = 8;
    for (int i = 0; i < maxTFBuckets; ++i)
    {
        size_t bucketCount = trlCores & 0xFF;
        int bucketSpeed = limitRatios & 0xFF;
        if (bucketCount != 0 && bucketSpeed != 0)
        {
            turboSpeeds.push_back({bucketSpeed * mhzPerRatio, bucketCount});
        }
        trlCores >>= 8;
        limitRatios >>= 8;
    }
    config.turboProfile(turboSpeeds);
}

/**
 * Retrieve all SST configuration info for all discoverable CPUs, and publish
 * the info on new D-Bus objects on the given bus connection.
 *
 * @param[out]  cpuList     List to append info about discovered CPUs,
 *                          including pointers to D-Bus objects to keep them
 *                          alive. No items may be added to list in case host
 *                          system is powered off and no CPUs are accessible.
 * @param[in,out]   conn    D-Bus ASIO connection.
 *
 * @return  Whether discovery was successfully finished.
 *
 * @throw PECIError     A PECI command failed on a CPU which had previously
 *                      responded to a command.
 */
static bool
    discoverCPUsAndConfigs(std::vector<std::unique_ptr<CPUConfig>>& cpuList,
                           boost::asio::io_context& ioc,
                           sdbusplus::asio::connection& conn)
{
    for (int i = MIN_CLIENT_ADDR; i <= MAX_CLIENT_ADDR; ++i)
    {
        // Let the event handler run any waiting tasks. If there is a lot of
        // PECI contention, SST discovery could take a long time. This lets us
        // get updates to hostState and handle any D-Bus requests.
        ioc.poll();

        if (hostState == HostState::off)
        {
            return false;
        }

        // We could possibly check D-Bus for CPU presence and model, but PECI is
        // 10x faster and so much simpler.
        uint8_t cc, stepping;
        CPUModel cpuModel;
        EPECIStatus status = peci_GetCPUID(i, &cpuModel, &stepping, &cc);
        if (status == PECI_CC_TIMEOUT)
        {
            // Timing out indicates the CPU is present but PCS services not
            // working yet. Try again later.
            throw PECIError("Get CPUID timed out");
        }
        if (status != PECI_CC_SUCCESS || cc != PECI_DEV_CC_SUCCESS ||
            !modelSupportsDiscovery(cpuModel))
        {
            continue;
        }

        PECIManager peciManager(i, cpuModel);

        // Continue if processor does not support SST-PP
        GetLevelsInfo getLevelsInfo(peciManager);
        if (!getLevelsInfo.enabled())
        {
            continue;
        }

        // Generate D-Bus object path for this processor.
        int cpuIndex = i - MIN_CLIENT_ADDR;

        // Read the Turbo Ratio Limit Cores MSR which is used to generate the
        // Turbo Profile for each profile. This is a package scope MSR, so just
        // read thread 0.
        uint64_t trlCores;
        status = peci_RdIAMSR(i, 0, 0x1AE, &trlCores, &cc);
        if (!checkPECIStatus(status, cc))
        {
            throw PECIError("Failed to read TRL MSR");
        }

        // Create the per-CPU configuration object
        cpuList.emplace_back(
            std::make_unique<CPUConfig>(conn, cpuIndex, cpuModel));
        CPUConfig& cpu = *cpuList.back();

        bool foundCurrentLevel = false;

        for (int level = 0; level <= getLevelsInfo.configTdpLevels(); ++level)
        {
            // levels 1 and 2 are legacy/deprecated, originally used for AVX
            // license pre-granting. They may be reused for more levels in
            // future generations.
            // We can check if they are supported by running any command for
            // this level and checking the mailbox return status.
            GetConfigTdpControl tdpControl(
                peciManager, GetConfigTdpControl::ErrorPolicy::NoThrow, level);
            if (!tdpControl.success())
            {
                continue;
            }

            getSingleConfig(peciManager, level, cpu.newConfig(level), trlCores);

            if (level == getLevelsInfo.currentConfigTdpLevel())
            {
                foundCurrentLevel = true;
            }
        }

        if (!foundCurrentLevel)
        {
            // In case we didn't encounter a PECI error, but also didn't find
            // the config which is supposedly applied, we won't be able to
            // populate the CurrentOperatingConfig so we have to remove this CPU
            // from consideration.
            std::cerr << "CPU " << cpuIndex
                      << " claimed SST support but invalid configs\n";
            cpuList.pop_back();
            continue;
        }

        cpu.finalize();
    }

    return true;
}

void init(boost::asio::io_context& ioc,
          const std::shared_ptr<sdbusplus::asio::connection>& conn)
{
    static boost::asio::steady_timer peciRetryTimer(ioc);
    static std::vector<std::unique_ptr<CPUConfig>> cpus;
    static int peciErrorCount = 0;

    bool finished = false;
    try
    {
        DEBUG_PRINT << "Starting discovery\n";
        finished = discoverCPUsAndConfigs(cpus, ioc, *conn);
    }
    catch (const PECIError& err)
    {
        std::cerr << "PECI Error: " << err.what() << '\n';

        // In case of repeated failure to finish discovery, turn off this
        // feature altogether. Possible cause is that the CPU model does not
        // actually support the necessary mailbox commands.
        if (++peciErrorCount >= 50)
        {
            std::cerr << "Aborting SST discovery\n";
            return;
        }

        std::cerr << "Retrying SST discovery later\n";
    }

    DEBUG_PRINT << "Finished discovery attempt: " << finished << '\n';

    // Retry later if no CPUs were available, or there was a PECI error.
    if (!finished)
    {
        // Drop any created interfaces to avoid presenting incomplete info
        cpus.clear();
        peciRetryTimer.expires_after(std::chrono::seconds(10));
        peciRetryTimer.async_wait([&ioc, conn](boost::system::error_code ec) {
            if (ec)
            {
                std::cerr << "SST PECI Retry Timer failed: " << ec << '\n';
                return;
            }
            init(ioc, conn);
        });
    }
}

} // namespace sst
} // namespace cpu_info
