0

[power_sampler] Add sampling of CPU temperature via SMC.

Bug: 1254332
Change-Id: I182e694672048cf8d4fa78f40baebd47dd8ec2ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3312177
Reviewed-by: Etienne Pierre-Doray <etiennep@chromium.org>
Commit-Queue: Francois Pierre Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/main@{#947662}
This commit is contained in:
Francois Doray
2021-12-02 22:04:50 +00:00
committed by Chromium LUCI CQ
parent 46a1f0a64e
commit 04f941779f
6 changed files with 100 additions and 104 deletions
chrome/browser/metrics/power
components/power_metrics
tools/mac/power/power_sampler

@ -9,12 +9,17 @@
#include <stdint.h>
// List of known SMC key identifiers.
//
// This is a good reference: https://logi.wiki/index.php/SMC_Sensor_Codes
// Additional keys can be discovered with
// https://github.com/theopolis/smc-fuzzer
enum class SMCKeyIdentifier : uint32_t {
TotalPower = 'PSTR', // Power: System Total Rail (watts)
CPUPower = 'PCPC', // Power: CPU Package CPU (watts)
iGPUPower = 'PCPG', // Power: CPU Package GPU (watts)
GPU0Power = 'PG0R', // Power: GPU 0 Rail (watts)
GPU1Power = 'PG1R', // Power: GPU 1 Rail (watts)
TotalPower = 'PSTR', // Power: System Total Rail (watts)
CPUPower = 'PCPC', // Power: CPU Package CPU (watts)
iGPUPower = 'PCPG', // Power: CPU Package GPU (watts)
GPU0Power = 'PG0R', // Power: GPU 0 Rail (watts)
GPU1Power = 'PG1R', // Power: GPU 1 Rail (watts)
CPUTemperature = 'TC0F', // Temperature: CPU Die PECI (Celsius)
};
// Types from PowerManagement/pmconfigd/PrivateLib.c

@ -13,6 +13,7 @@
#include <memory>
#include "base/containers/flat_map.h"
#include "base/mac/scoped_ioobject.h"
#include "components/power_metrics/smc_internal_types_mac.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@ -26,13 +27,9 @@ class SMCReader {
virtual ~SMCReader();
// Returns the power consumption of various hardware components in watts.
// Returns the value of a key, or nullopt if not available.
// Virtual for testing.
virtual absl::optional<double> ReadTotalPowerW();
virtual absl::optional<double> ReadCPUPackageCPUPowerW();
virtual absl::optional<double> ReadCPUPackageGPUPowerW();
virtual absl::optional<double> ReadGPU0PowerW();
virtual absl::optional<double> ReadGPU1PowerW();
virtual absl::optional<double> ReadKey(SMCKeyIdentifier identifier);
protected:
explicit SMCReader(base::mac::ScopedIOObject<io_object_t> connect);
@ -42,6 +39,8 @@ class SMCReader {
public:
SMCKey(base::mac::ScopedIOObject<io_object_t> connect,
SMCKeyIdentifier key_identifier);
SMCKey(SMCKey&&);
SMCKey& operator=(SMCKey&&);
~SMCKey();
bool Exists() const;
@ -51,15 +50,12 @@ class SMCReader {
bool CallSMCFunction(uint8_t function, SMCParamStruct* out);
base::mac::ScopedIOObject<io_object_t> connect_;
const SMCKeyIdentifier key_identifier_;
SMCKeyIdentifier key_identifier_;
SMCKeyInfoData key_info_;
};
SMCKey total_power_key_;
SMCKey cpu_package_cpu_power_key_;
SMCKey cpu_package_gpu_power_key_;
SMCKey gpu0_power_key_;
SMCKey gpu1_power_key_;
base::mac::ScopedIOObject<io_object_t> connect_;
base::flat_map<SMCKeyIdentifier, SMCKey> keys_;
};
} // namespace power_metrics

@ -35,24 +35,14 @@ std::unique_ptr<SMCReader> SMCReader::Create() {
SMCReader::~SMCReader() = default;
absl::optional<double> SMCReader::ReadTotalPowerW() {
return total_power_key_.Read();
}
absl::optional<double> SMCReader::ReadKey(SMCKeyIdentifier identifier) {
auto it = keys_.find(identifier);
if (it == keys_.end()) {
auto result = keys_.emplace(identifier, SMCKey(connect_, identifier));
it = result.first;
}
absl::optional<double> SMCReader::ReadCPUPackageCPUPowerW() {
return cpu_package_cpu_power_key_.Read();
}
absl::optional<double> SMCReader::ReadCPUPackageGPUPowerW() {
return cpu_package_gpu_power_key_.Read();
}
absl::optional<double> SMCReader::ReadGPU0PowerW() {
return gpu0_power_key_.Read();
}
absl::optional<double> SMCReader::ReadGPU1PowerW() {
return gpu1_power_key_.Read();
return it->second.Read();
}
SMCReader::SMCKey::SMCKey(base::mac::ScopedIOObject<io_object_t> connect,
@ -64,6 +54,9 @@ SMCReader::SMCKey::SMCKey(base::mac::ScopedIOObject<io_object_t> connect,
key_info_ = out.keyInfo;
}
SMCReader::SMCKey::SMCKey(SMCKey&&) = default;
SMCReader::SMCKey& SMCReader::SMCKey::operator=(SMCKey&&) = default;
SMCReader::SMCKey::~SMCKey() = default;
bool SMCReader::SMCKey::Exists() const {
@ -125,10 +118,6 @@ bool SMCReader::SMCKey::CallSMCFunction(uint8_t function, SMCParamStruct* out) {
}
SMCReader::SMCReader(base::mac::ScopedIOObject<io_object_t> connect)
: total_power_key_(connect, SMCKeyIdentifier::TotalPower),
cpu_package_cpu_power_key_(connect, SMCKeyIdentifier::CPUPower),
cpu_package_gpu_power_key_(connect, SMCKeyIdentifier::iGPUPower),
gpu0_power_key_(connect, SMCKeyIdentifier::GPU0Power),
gpu1_power_key_(connect, SMCKeyIdentifier::GPU1Power) {}
: connect_(std::move(connect)) {}
} // namespace power_metrics