Skip to content
This repository has been archived by the owner on Oct 12, 2018. It is now read-only.

Commit

Permalink
CPUSensors added power sensors for supported CPUs. FakeSMC NVRAM fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
CozmoNate committed Jul 21, 2013
1 parent 11a228a commit c6cd428
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 26 deletions.
95 changes: 88 additions & 7 deletions CPUSensors/CPUSensors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IORegistryEntry.h>

#define kCPUSensorsPackageTemperatureSensor 1000
#include "timer.h"

#define kCPUSensorsTemperatureSensor 1000
#define kCPUSensorsPowerSensor 2000

#define super FakeSMCPlugin
OSDefineMetaClassAndStructors(CPUSensors, FakeSMCPlugin)
Expand All @@ -69,7 +72,7 @@ inline UInt32 get_cpu_number()
return cpu_number() % cpuid_info()->core_count;
}

inline void read_cpu_core_thermal(void* cpu_index)
static void read_cpu_core_thermal(void* cpu_index)
{
UInt8 * cpn = (UInt8 *)cpu_index;

Expand All @@ -81,13 +84,13 @@ inline void read_cpu_core_thermal(void* cpu_index)
}
};

inline void read_cpu_package_thermal(void* magic)
static void read_cpu_package_thermal(void* magic)
{
UInt64 msr = rdmsr64(MSR_IA32_PACKAGE_THERM_STATUS);
cpu_package_thermal = (msr >> 16) & 0x7F;
};

inline void read_cpu_performance(void* cpu_index)
static void read_cpu_performance(void* cpu_index)
{
UInt8 *cpn = (UInt8*)cpu_index;

Expand All @@ -99,6 +102,44 @@ inline void read_cpu_performance(void* cpu_index)
}
};

static void read_cpu_energy(void *multiplier)
{
float energyUnit = *((float*)multiplier);
UInt64 lastEnergy[4];
double lastTime[4];

for (UInt8 sample = 0; sample < 2; sample++) {

for (UInt8 index = 0; index < 4; index++) {

switch (sample) {
case 0: {
lastEnergy[index] = rdmsr64(cpu_energy_msrs[index]);
lastTime[index] = ptimer_read_seconds();

break;
}

case 1: {
UInt64 energy = (double)rdmsr64(cpu_energy_msrs[index]);

if (!energy) continue;

float deltaTime = float(ptimer_read_seconds() - lastTime[index]);

if (deltaTime == 0) continue;

cpu_energy_consumed[index] = (energyUnit * float(energy - lastEnergy[index])) / deltaTime;

break;
}
}
}

IOSleep(70);
}
};

void CPUSensors::readTjmaxFromMSR()
{
for (uint32_t i = 0; i < cpuid_info()->core_count; i++) {
Expand Down Expand Up @@ -134,6 +175,7 @@ IOReturn CPUSensors::loopTimerEvent(void)
mp_rendezvous_no_intrs(read_cpu_performance, &index);
IOSleep(1); // Yield?
cpu_performance[0] = cpu_performance[index];

break;

default:
Expand All @@ -143,6 +185,10 @@ IOReturn CPUSensors::loopTimerEvent(void)
}
break;
}

if (energyUnit) {
/*mp_rendezvous_no_intrs(*/read_cpu_energy(&energyUnit);
}
}

timersource->setTimeoutMS(1000);
Expand Down Expand Up @@ -182,7 +228,7 @@ float CPUSensors::getSensorValue(FakeSMCSensor *sensor)
}
break;

case kCPUSensorsPackageTemperatureSensor:
case kCPUSensorsTemperatureSensor:
thermCounter = 0;
return tjmax[0] - cpu_package_thermal;

Expand All @@ -199,6 +245,14 @@ float CPUSensors::getSensorValue(FakeSMCSensor *sensor)
return calculateMultiplier(sensor->getIndex()) * (float)busClock;
}
break;

case kCPUSensorsPowerSensor: {
if (sensor->getIndex() < 4) {
perfCounter = 0;
return cpu_energy_consumed[sensor->getIndex()];
}
break;
}
}

return 0;
Expand Down Expand Up @@ -481,7 +535,7 @@ bool CPUSensors::start(IOService *provider)

// processor has support for digital thermal sensor at package level
if (cpuid_info()->cpuid_package_thermal_sensor) {
if (!addSensor(KEY_CPU_PACKAGE_TEMPERATURE, TYPE_SP78, TYPE_SPXX_SIZE, kCPUSensorsPackageTemperatureSensor, 0))
if (!addSensor(KEY_CPU_PACKAGE_TEMPERATURE, TYPE_SP78, TYPE_SPXX_SIZE, kCPUSensorsTemperatureSensor, 0))
HWSensorsWarningLog("failed to add cpu package temperature sensor");
}

Expand All @@ -491,12 +545,39 @@ bool CPUSensors::start(IOService *provider)
case CPUFAMILY_INTEL_SANDYBRIDGE:
case CPUFAMILY_INTEL_IVYBRIDGE:
case CPUFAMILY_INTEL_HASWELL:
case CPUFAMILY_INTEL_HASWELL_ULT:
case CPUFAMILY_INTEL_HASWELL_ULT: {
if (!addSensor(KEY_FAKESMC_CPU_PACKAGE_MULTIPLIER, TYPE_FP88, TYPE_FPXX_SIZE, kFakeSMCMultiplierSensor, 0))
HWSensorsWarningLog("failed to add package multiplier sensor");
if (!addSensor(KEY_FAKESMC_CPU_PACKAGE_FREQUENCY, TYPE_UI32, TYPE_UI32_SIZE, kFakeSMCFrequencySensor, 0))
HWSensorsWarningLog("failed to add package frequency sensor");
break;
}

default:
break;
}

switch (cpuid_info()->cpuid_cpufamily) {
case CPUFAMILY_INTEL_SANDYBRIDGE:
case CPUFAMILY_INTEL_IVYBRIDGE:
case CPUFAMILY_INTEL_HASWELL:
case CPUFAMILY_INTEL_HASWELL_ULT: {

UInt64 msr = rdmsr64(MSR_RAPL_POWER_UNIT);
energyUnit = 1.0f / (float)(1 << (int)((msr >> 8) & 0x1FF));

if (energyUnit) {
if (!addSensor(KEY_CPU_PACKAGE_TOTAL_POWER, TYPE_SP78, TYPE_SPXX_SIZE, kCPUSensorsPowerSensor, 0))
HWSensorsWarningLog("failed to add CPU package total power sensor");
if (!addSensor(KEY_CPU_PACKAGE_CORE_POWER, TYPE_SP78, TYPE_SPXX_SIZE, kCPUSensorsPowerSensor, 1))
HWSensorsWarningLog("failed to add CPU package cores power sensor");
if (!addSensor(KEY_CPU_PACKAGE_GFX_POWER, TYPE_SP78, TYPE_SPXX_SIZE, kCPUSensorsPowerSensor, 2))
HWSensorsWarningLog("failed to add CPU package graphics power sensor");
if (!addSensor(KEY_CPU_PACKAGE_DRAM_POWER, TYPE_SP78, TYPE_SPXX_SIZE, kCPUSensorsPowerSensor, 3))
HWSensorsWarningLog("failed to add CPU package DRAM power sensor");
}
break;
}

default:
break;
Expand Down
14 changes: 14 additions & 0 deletions CPUSensors/CPUSensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ static UInt16 cpu_performance[kCPUSensorsMaxCpus];

static UInt8 cpu_package_thermal;

static UInt16 cpu_energy_msrs[] =
{
MSR_PKG_ENERY_STATUS,
MSR_PP0_ENERY_STATUS,
MSR_PP1_ENERY_STATUS,
MSR_DRAM_ENERGY_STATUS
};

//static UInt64 cpu_last_energy_time[4];
//static UInt64 cpu_last_energy_raw[4];
static float cpu_energy_consumed[4];

class CPUSensors : public FakeSMCPlugin
{
OSDeclareDefaultStructors(CPUSensors)
Expand All @@ -91,6 +103,8 @@ class CPUSensors : public FakeSMCPlugin
UInt8 perfCounter;

UInt64 busClock;

float energyUnit;

IOReturn loopTimerEvent(void);
void readTjmaxFromMSR();
Expand Down
6 changes: 3 additions & 3 deletions FakeSMC/FakeSMCDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ uint32_t FakeSMCDevice::applesmc_io_cmd_readb(void *opaque, uint32_t addr1)

void FakeSMCDevice::saveKeyToNVRAM(FakeSMCKey *key)
{
if (nvram) {
if (IORegistryEntry *nvram = OSDynamicCast(IORegistryEntry, fromPath("/options", gIODTPlane))) {
char name[32];

snprintf(name, 32, "%s-%s-%s", kFakeSMCKeyPropertyPrefix, key->getKey(), key->getType());
Expand All @@ -277,9 +277,9 @@ UInt32 FakeSMCDevice::loadKeysFromNVRAM()

// Find driver and load keys from NVRAM
if (OSDictionary *matching = serviceMatching("IODTNVRAM")) {
if ((nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15)))) {
if (IODTNVRAM *nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15))) {

if ((genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", strlen("AppleNVRAM")))))
if ((genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", sizeof("AppleNVRAM")))))
HWSensorsInfoLog("fallback to generic NVRAM methods");

OSSerialize *s = OSSerialize::withCapacity(0); // Workaround for IODTNVRAM->getPropertyTable returns IOKitPersonalities instead of NVRAM properties dictionary
Expand Down
1 change: 0 additions & 1 deletion FakeSMC/FakeSMCDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ class FakeSMCDevice : public IOACPIPlatformDevice
bool trace;
bool debug;

IODTNVRAM *nvram;
bool genericNVRAM;

IORecursiveLock *keysLock;
Expand Down
13 changes: 7 additions & 6 deletions HWMonitor/HWMonitorProfiles.m
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,10 @@ +(NSDictionary *)profiles
[NSArray arrayWithObjects:@"PC:081C", @"CPU Core %X", nil],
[NSArray arrayWithObjects:@"PC:A8AC", @"CPU %X", nil],
[NSArray arrayWithObjects:@"PC0G", @"CPU GFX", nil],
[NSArray arrayWithObjects:@"PCPC", @"CPU Package", nil],
[NSArray arrayWithObjects:@"PCPG", @"CPU Package GFX", nil],
[NSArray arrayWithObjects:@"PCPC", @"CPU Package Cores", nil],
[NSArray arrayWithObjects:@"PCPG", @"CPU Package Graphics", nil],
[NSArray arrayWithObjects:@"PCPT", @"CPU Package Total", nil],
[NSArray arrayWithObjects:@"PCPD", @"CPU Package DRAM", nil],
[NSArray arrayWithObjects:@"PC1R", @"CPU Rail", nil],
[NSArray arrayWithObjects:@"PC5R", @"CPU 1.5V S0 Rail", nil],
[NSArray arrayWithObjects:@"PM0R", @"Memory Rail", nil],
Expand Down Expand Up @@ -207,8 +208,8 @@ +(NSDictionary *)profiles

// Powers
[NSArray arrayWithObjects:@"PC0C", @"CPU Core", nil],
[NSArray arrayWithObjects:@"PCPC", @"CPU Package", nil],
[NSArray arrayWithObjects:@"PCPG", @"CPU Package GFX", nil],
[NSArray arrayWithObjects:@"PCPC", @"CPU Package Cores", nil],
[NSArray arrayWithObjects:@"PCPG", @"CPU Package Graphics", nil],
[NSArray arrayWithObjects:@"PCPT", @"CPU Package Total", nil],
//[NSArray arrayWithObjects:@"PN0C", @" ? ", nil],
//[NSArray arrayWithObjects:@"PHPC", @" ? ", nil],
Expand Down Expand Up @@ -257,8 +258,8 @@ +(NSDictionary *)profiles
// Powers
[NSArray arrayWithObjects:@"PC0C", @"CPU Core", nil],
[NSArray arrayWithObjects:@"PC0M", @"CPU Memory", nil],
[NSArray arrayWithObjects:@"PCPC", @"CPU Package", nil],
[NSArray arrayWithObjects:@"PCPG", @"CPU Package GFX", nil],
[NSArray arrayWithObjects:@"PCPC", @"CPU Package Cores", nil],
[NSArray arrayWithObjects:@"PCPG", @"CPU Package Graphics", nil],
[NSArray arrayWithObjects:@"PCPL", @"CPU Package Total", nil],

[NSArray arrayWithObjects:@"PN1R", @"PCH Rail", nil], // ??
Expand Down
6 changes: 5 additions & 1 deletion HWMonitor/ru.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,11 @@
"CPU Proximity" = "Процессор, Датчик";
"CPU %X Proximity" = "Процессор %X, Датчик";

"CPU Package" = "Упаковка процессора";
"CPU Package" = "Процессор, Упаковка";
"CPU Package Total" = "Процессор, Упаковка";
"CPU Package Cores" = "Процессор, Ядра";
"CPU Package Graphics" = "Процессор, Графика";
"CPU Package DRAM" = "Контроллер памяти";

"PECI CPU" = "PECI Процессор";
"PECI SA" = "PECI SA";
Expand Down
4 changes: 2 additions & 2 deletions SMC Value Decoder/DefaultTestingPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ const SMCKeyInfo SmcKeyInfos[] =
// Power
{"PC%XC", "sp96", 2, "CPU Core %X", kSMCKeyGroupPower, 4, 1, 1}, // ?
{"PC%XC", "sp96", 2, "CPU %X", kSMCKeyGroupPower, 4, 0xA, 0xA}, // ?
{"PCPC", "sp96", 2, "CPU Package Core", kSMCKeyGroupPower, 0, 0, 1}, // ?
{"PCPG", "sp96", 2, "CPU Package GFX", kSMCKeyGroupPower, 0, 0, 1}, // ?
{"PCPC", "sp96", 2, "CPU Package Cores", kSMCKeyGroupPower, 0, 0, 1}, // ?
{"PCPG", "sp96", 2, "CPU Package Graphics", kSMCKeyGroupPower, 0, 0, 1}, // ?
{"PCPT", "sp96", 2, "CPU Package Total", kSMCKeyGroupPower, 0, 0, 1}, // ?
{"PC1R", "sp96", 2, "CPU Rail", kSMCKeyGroupPower, 0, 0, 1}, // ?
{"PC5R", "sp96", 2, "CPU 1.5V S0 Rail", kSMCKeyGroupPower, 0, 0, 1}, // ?
Expand Down
2 changes: 2 additions & 0 deletions Shared/FakeSMCDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
#define KEY_CPU_PACKAGE_CORE_POWER "PCPC" // SNB
#define KEY_CPU_PACKAGE_GFX_POWER "PCPG" // SNB
#define KEY_CPU_PACKAGE_TOTAL_POWER "PCPT" // SNB
#define KEY_CPU_PACKAGE_DRAM_POWER "PCPD" // ??


// FANs
#define KEY_FAN_NUMBER "FNum"
Expand Down
16 changes: 10 additions & 6 deletions Shared/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ static UInt64 ptimer_read()
clock_get_calendar_nanotime(&secs, &nanosecs);

return (UInt64)secs * (UInt64)NSEC_PER_SEC + (UInt64)nanosecs;
// uint64_t uptime, nanoseconds;
//
// clock_get_uptime(&uptime);
// absolutetime_to_nanoseconds(uptime, &nanoseconds);
//
// return nanoseconds;
}

static double ptimer_read_seconds()
{
clock_sec_t secs;
clock_usec_t microsecs;

clock_get_calendar_microtime(&secs, &microsecs);

return (double)secs + (double)microsecs / (double)USEC_PER_SEC;
}

#endif

0 comments on commit c6cd428

Please sign in to comment.