194c94bfbSJonathan Doman // Copyright (c) 2020 Intel Corporation
294c94bfbSJonathan Doman //
394c94bfbSJonathan Doman // Licensed under the Apache License, Version 2.0 (the "License");
494c94bfbSJonathan Doman // you may not use this file except in compliance with the License.
594c94bfbSJonathan Doman // You may obtain a copy of the License at
694c94bfbSJonathan Doman //
794c94bfbSJonathan Doman //      http://www.apache.org/licenses/LICENSE-2.0
894c94bfbSJonathan Doman //
994c94bfbSJonathan Doman // Unless required by applicable law or agreed to in writing, software
1094c94bfbSJonathan Doman // distributed under the License is distributed on an "AS IS" BASIS,
1194c94bfbSJonathan Doman // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1294c94bfbSJonathan Doman // See the License for the specific language governing permissions and
1394c94bfbSJonathan Doman // limitations under the License.
1494c94bfbSJonathan Doman #pragma once
1594c94bfbSJonathan Doman 
1616a2ced3SJonathan Doman #include <peci.h>
1716a2ced3SJonathan Doman 
1894c94bfbSJonathan Doman #include <boost/asio/io_context.hpp>
1994c94bfbSJonathan Doman #include <sdbusplus/asio/connection.hpp>
2094c94bfbSJonathan Doman 
2116a2ced3SJonathan Doman #include <bitset>
2216a2ced3SJonathan Doman #include <iostream>
2316a2ced3SJonathan Doman 
2494c94bfbSJonathan Doman namespace cpu_info
2594c94bfbSJonathan Doman {
2694c94bfbSJonathan Doman namespace sst
2794c94bfbSJonathan Doman {
2894c94bfbSJonathan Doman 
2994c94bfbSJonathan Doman /**
3049ea830eSJonathan Doman  * Initialize SST subsystem.
3149ea830eSJonathan Doman  *
3249ea830eSJonathan Doman  * This will schedule work to be done when the host is ready, in order to
3349ea830eSJonathan Doman  * retrieve all SST configuration info for all discoverable CPUs, and publish
3494c94bfbSJonathan Doman  * the info on new D-Bus objects on the given bus connection.
3594c94bfbSJonathan Doman  */
3649ea830eSJonathan Doman void init();
3794c94bfbSJonathan Doman 
3816a2ced3SJonathan Doman class PECIError : public std::runtime_error
3916a2ced3SJonathan Doman {
4016a2ced3SJonathan Doman     using std::runtime_error::runtime_error;
4116a2ced3SJonathan Doman };
4216a2ced3SJonathan Doman 
4316a2ced3SJonathan Doman bool checkPECIStatus(EPECIStatus libStatus, uint8_t completionCode);
4416a2ced3SJonathan Doman 
extendedModel(CPUModel model)4516a2ced3SJonathan Doman constexpr int extendedModel(CPUModel model)
4616a2ced3SJonathan Doman {
4716a2ced3SJonathan Doman     return (model >> 16) & 0xF;
4816a2ced3SJonathan Doman }
4916a2ced3SJonathan Doman 
5016a2ced3SJonathan Doman /**
5116a2ced3SJonathan Doman  * Construct a list of indexes of the set bits in the input value.
5216a2ced3SJonathan Doman  * E.g. fn(0x7A) -> {1,3,4,5,6}
5316a2ced3SJonathan Doman  *
5416a2ced3SJonathan Doman  * @param[in]   mask    Bitmask to convert.
5516a2ced3SJonathan Doman  *
5616a2ced3SJonathan Doman  * @return  List of bit indexes.
5716a2ced3SJonathan Doman  */
5849ea830eSJonathan Doman std::vector<uint32_t> convertMaskToList(std::bitset<64> mask);
5916a2ced3SJonathan Doman 
6016a2ced3SJonathan Doman using TurboEntry = std::tuple<uint32_t, size_t>;
6116a2ced3SJonathan Doman 
6216a2ced3SJonathan Doman /**
6316a2ced3SJonathan Doman  * Abstract interface that must be implemented by backends, allowing discovery
6416a2ced3SJonathan Doman  * and control of a single CPU package.
6516a2ced3SJonathan Doman  */
6616a2ced3SJonathan Doman class SSTInterface
6716a2ced3SJonathan Doman {
6816a2ced3SJonathan Doman   public:
~SSTInterface()69c39d3dfcSPatrick Williams     virtual ~SSTInterface() {}
7016a2ced3SJonathan Doman 
7116a2ced3SJonathan Doman     /**
7216a2ced3SJonathan Doman      * Whether the interface is ready to be used, or we need to wait longer. The
7316a2ced3SJonathan Doman      * backend may need to wait e.g. for the host BIOS to initialize the
7416a2ced3SJonathan Doman      * interface.
7516a2ced3SJonathan Doman      */
7616a2ced3SJonathan Doman     virtual bool ready() = 0;
7716a2ced3SJonathan Doman 
7816a2ced3SJonathan Doman     /** Whether the processor supports the control ("set") functions. */
7916a2ced3SJonathan Doman     virtual bool supportsControl() = 0;
8016a2ced3SJonathan Doman 
8116a2ced3SJonathan Doman     /** Whether SST-PP is enabled on the processor. */
8216a2ced3SJonathan Doman     virtual bool ppEnabled() = 0;
8316a2ced3SJonathan Doman     /** Return the current SST-PP configuration level */
8416a2ced3SJonathan Doman     virtual unsigned int currentLevel() = 0;
8516a2ced3SJonathan Doman     /** Return the maximum valid SST-PP configuration level */
86b4c3bcd7SJonathan Doman     virtual unsigned int maxLevel() = 0;
8716a2ced3SJonathan Doman 
8816a2ced3SJonathan Doman     /**
8916a2ced3SJonathan Doman      * Whether the given level is supported. The level indices may be
9016a2ced3SJonathan Doman      * discontinuous, so this function should be used before querying deeper
9116a2ced3SJonathan Doman      * properties of a level.
9216a2ced3SJonathan Doman      */
9316a2ced3SJonathan Doman     virtual bool levelSupported(unsigned int level) = 0;
9416a2ced3SJonathan Doman     /** Whether SST-BF is supported in a given level. */
9516a2ced3SJonathan Doman     virtual bool bfSupported(unsigned int level) = 0;
9616a2ced3SJonathan Doman     /** Whether SST-TF is supported in a given level. */
9716a2ced3SJonathan Doman     virtual bool tfSupported(unsigned int level) = 0;
9816a2ced3SJonathan Doman     /** Whether SST-BF is enabled in a given level. */
9916a2ced3SJonathan Doman     virtual bool bfEnabled(unsigned int level) = 0;
10016a2ced3SJonathan Doman     /** Whether SST-TF is enabled in a given level. */
10116a2ced3SJonathan Doman     virtual bool tfEnabled(unsigned int level) = 0;
10216a2ced3SJonathan Doman     /** Return the package Thermal Design Power in Watts for a given level. */
10316a2ced3SJonathan Doman     virtual unsigned int tdp(unsigned int level) = 0;
10416a2ced3SJonathan Doman     /** Return the number of cores enabled in a given level. */
10516a2ced3SJonathan Doman     virtual unsigned int coreCount(unsigned int level) = 0;
10616a2ced3SJonathan Doman     /** Return the list of enabled logical core indices for a given level. */
10716a2ced3SJonathan Doman     virtual std::vector<unsigned int> enabledCoreList(unsigned int level) = 0;
10816a2ced3SJonathan Doman     /**
10916a2ced3SJonathan Doman      * Return the list of TurboEntrys which define the SSE turbo profile for a
11016a2ced3SJonathan Doman      * given level.
11116a2ced3SJonathan Doman      */
11216a2ced3SJonathan Doman     virtual std::vector<TurboEntry> sseTurboProfile(unsigned int level) = 0;
11316a2ced3SJonathan Doman     /** Return the base frequency (P1) for a given level. */
11416a2ced3SJonathan Doman     virtual unsigned int p1Freq(unsigned int level) = 0;
11516a2ced3SJonathan Doman     /** Return the maximum single-core frequency (P0) for a given level. */
11616a2ced3SJonathan Doman     virtual unsigned int p0Freq(unsigned int level) = 0;
11716a2ced3SJonathan Doman     /**
11816a2ced3SJonathan Doman      * Return the DTS max or external Prochot temperature in degrees Celsius
11916a2ced3SJonathan Doman      * for a given level.
12016a2ced3SJonathan Doman      */
12116a2ced3SJonathan Doman     virtual unsigned int prochotTemp(unsigned int level) = 0;
12216a2ced3SJonathan Doman     /**
12316a2ced3SJonathan Doman      * Return the list of logical core indices which have high priority when
12416a2ced3SJonathan Doman      * SST-BF is enabled for a given level.
12516a2ced3SJonathan Doman      */
12616a2ced3SJonathan Doman     virtual std::vector<unsigned int>
12716a2ced3SJonathan Doman         bfHighPriorityCoreList(unsigned int level) = 0;
12816a2ced3SJonathan Doman     /** Return the high priority base frequency for a given level. */
12916a2ced3SJonathan Doman     virtual unsigned int bfHighPriorityFreq(unsigned int level) = 0;
13016a2ced3SJonathan Doman     /** Return the low priority base frequency for a given level. */
13116a2ced3SJonathan Doman     virtual unsigned int bfLowPriorityFreq(unsigned int level) = 0;
13216a2ced3SJonathan Doman 
13316a2ced3SJonathan Doman     /** Enable or disable SST-BF for the current configuration. */
13416a2ced3SJonathan Doman     virtual void setBfEnabled(bool enable) = 0;
13516a2ced3SJonathan Doman     /** Enable or disable SST-TF for the current configuration. */
13616a2ced3SJonathan Doman     virtual void setTfEnabled(bool enable) = 0;
13716a2ced3SJonathan Doman     /** Change the current configuration to the given level. */
13816a2ced3SJonathan Doman     virtual void setCurrentLevel(unsigned int level) = 0;
13916a2ced3SJonathan Doman };
14016a2ced3SJonathan Doman 
14116a2ced3SJonathan Doman /**
142*b5d7222fSJonathan Doman  * Policy for whether the SST interface should wake up an idle CPU to complete
143*b5d7222fSJonathan Doman  * requested operations. Waking should be used sparingly to avoid excess CPU
144*b5d7222fSJonathan Doman  * power draw, so the policy depends on the context.
145*b5d7222fSJonathan Doman  */
146*b5d7222fSJonathan Doman enum WakePolicy
147*b5d7222fSJonathan Doman {
148*b5d7222fSJonathan Doman     /**
149*b5d7222fSJonathan Doman      * If CPU rejects the request due to being in a low-power state, enable
150*b5d7222fSJonathan Doman      * wake-on-PECI on the CPU and retry. Wake-on-PECI is disabled for the CPU
151*b5d7222fSJonathan Doman      * when the SST interface is destroyed.
152*b5d7222fSJonathan Doman      */
153*b5d7222fSJonathan Doman     wakeAllowed,
154*b5d7222fSJonathan Doman 
155*b5d7222fSJonathan Doman     /**
156*b5d7222fSJonathan Doman      * If CPU rejects the request due to being in a low-power state, it results
157*b5d7222fSJonathan Doman      * in a PECIError exception.
158*b5d7222fSJonathan Doman      */
159*b5d7222fSJonathan Doman     dontWake
160*b5d7222fSJonathan Doman };
161*b5d7222fSJonathan Doman 
162*b5d7222fSJonathan Doman /**
16316a2ced3SJonathan Doman  * BackendProvider represents a function which may create an SSTInterface given
16416a2ced3SJonathan Doman  * a CPU PECI address, and the CPU Model information. Usually the CPUModel is
16516a2ced3SJonathan Doman  * sufficient to determine if the backend is supported.
16616a2ced3SJonathan Doman  * Backend should return nullptr to indicate it doesn't support a given CPU.
16716a2ced3SJonathan Doman  * The SST upper layer will call the registered backend provider functions in
16816a2ced3SJonathan Doman  * arbitrary order until one of them returns a non-null pointer.
16916a2ced3SJonathan Doman  */
17016a2ced3SJonathan Doman using BackendProvider =
171*b5d7222fSJonathan Doman     std::function<std::unique_ptr<SSTInterface>(uint8_t, CPUModel, WakePolicy)>;
17216a2ced3SJonathan Doman 
17316a2ced3SJonathan Doman /**
17416a2ced3SJonathan Doman  * Backends should use 1 instance of the SSTProviderRegistration macro at file
17516a2ced3SJonathan Doman  * scope to register their provider function. This static struct instance
17616a2ced3SJonathan Doman  * register the backend before main() is run, and prevents the upper layer from
17716a2ced3SJonathan Doman  * having to know about which backends exist.
17816a2ced3SJonathan Doman  */
17916a2ced3SJonathan Doman #define SSTProviderRegistration(fn)                                            \
18016a2ced3SJonathan Doman     struct fn##Register                                                        \
18116a2ced3SJonathan Doman     {                                                                          \
18216a2ced3SJonathan Doman         fn##Register()                                                         \
18316a2ced3SJonathan Doman         {                                                                      \
18416a2ced3SJonathan Doman             std::cerr << "Registering SST Provider " #fn << std::endl;         \
18516a2ced3SJonathan Doman             registerBackend(fn);                                               \
18616a2ced3SJonathan Doman         }                                                                      \
18716a2ced3SJonathan Doman     } fn##Instance;
18816a2ced3SJonathan Doman void registerBackend(BackendProvider);
18916a2ced3SJonathan Doman 
19094c94bfbSJonathan Doman } // namespace sst
19194c94bfbSJonathan Doman } // namespace cpu_info
192