/*
    * CpuPower.hpp
    * Intel CPU power management: HWP frequency scaling, C1E promotion,
    * and the package thermal governor.
    * Copyright (c) 2026 Daniel Hammer
*/

#pragma once
#include <cstdint>

namespace Hal {
    namespace CpuPower {

        // Snapshot of the power/thermal state for SYS_POWERINFO and logging.
        struct Snapshot {
            bool     HwpActive;
            bool     Throttling;
            uint8_t  TempC;          // package temperature (0 = unknown)
            uint8_t  TjMaxC;         // hardware throttle temperature
            uint8_t  HighestPerf;    // HWP performance range (ratio units)
            uint8_t  LowestPerf;
            uint8_t  CurMaxPerf;     // governor's current performance ceiling
            uint8_t  Epp;            // energy/performance preference in effect
            uint32_t BaseMHz;        // CPUID base frequency (0 = unknown)
            uint32_t MaxMHz;         // CPUID max turbo frequency
            uint32_t EffMHz;         // measured average active frequency (BSP)
        };

        // BSP: detect features, enable HWP with a balanced energy preference,
        // enable C1E promotion, and prime the thermal governor. Must run
        // before the APs boot so they can pick up the shared policy.
        void InitializeBsp();

        // AP: per-CPU MSR setup (C1E promotion + initial HWP request).
        void InitializeAp();

        // Re-apply the HWP request on the calling CPU if the governor changed
        // the performance ceiling since this CPU last applied it. Cheap (one
        // relaxed atomic compare when nothing changed) - safe in tick paths.
        void ApplyPolicyIfChanged();

        // Thermal governor step. BSP-only; rate-limited internally, so it can
        // be called from every maintenance pass.
        void ThermalTick(uint64_t nowMs);

        // Redo the BSP MSR setup after S3 wake (HWP enable and POWER_CTL do
        // not survive suspend).
        void ReapplyAfterWake();

        // Fill a snapshot for SYS_POWERINFO. Returns false when the CPU
        // exposes none of the relevant features (e.g. under QEMU).
        bool GetSnapshot(Snapshot& out);
    };
};
