Skip to content

Commit

Permalink
smooth temp curve
Browse files Browse the repository at this point in the history
  • Loading branch information
trulyspinach committed Jul 30, 2021
1 parent c5996be commit aece378
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 39 deletions.
2 changes: 1 addition & 1 deletion AMDRyzenCPUPowerManagement/AMDRyzenCPUPMUserClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ IOReturn AMDRyzenCPUPMUserClient::externalMethod(uint32_t selector, IOExternalMe
dataOut[0] = 0;

for(uint32_t i = 0; i < fProvider->totalNumberOfLogicalCores; i++){
dataOut[0] += fProvider->instructionDelta_PerCore[i];
dataOut[0] += fProvider->instructionDelta_perCore[i];
}

break;
Expand Down
78 changes: 54 additions & 24 deletions AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ bool AMDRyzenCPUPowerManagement::getPCIService(){
return true;
}

void AMDRyzenCPUPowerManagement::startWorkLoop() {
void AMDRyzenCPUPowerManagement::initWorkLoop() {
IOLog("AMDCPUSupport::startWorkLoop setting up timer");

timerEventSource = IOTimerEventSource::timerEventSource(this, [](OSObject *object, IOTimerEventSource *sender) {
timerEvent_main = IOTimerEventSource::timerEventSource(this, [](OSObject *object, IOTimerEventSource *sender) {
AMDRyzenCPUPowerManagement *provider = OSDynamicCast(AMDRyzenCPUPowerManagement, object);

//Run initialization
Expand Down Expand Up @@ -157,16 +157,16 @@ void AMDRyzenCPUPowerManagement::startWorkLoop() {
if(!provider->read_msr(kMSR_APERF, &APERF) || !provider->read_msr(kMSR_MPERF, &MPERF))
panic("AMDCPUSupport::startWorkLoop: wtf?");

provider->lastAPERF_PerCore[physical] = APERF;
provider->lastMPERF_PerCore[physical] = MPERF;
provider->lastAPERF_perCore[physical] = APERF;
provider->lastMPERF_perCore[physical] = MPERF;

}, provider);

//Make all cores P0 state by default.
provider->PStateCtl = 0;

provider->serviceInitialized = true;
provider->timerEventSource->setTimeoutMS(1);
provider->timerEvent_main->setTimeoutMS(1);
return;
}

Expand Down Expand Up @@ -200,28 +200,50 @@ void AMDRyzenCPUPowerManagement::startWorkLoop() {
provider->timeOfLastUpdate = now;
provider->updateTimeInterval = min(1200, max(50, newInt));

provider->timerEventSource->setTimeoutMS(provider->updateTimeInterval);
provider->timerEvent_main->setTimeoutMS(provider->updateTimeInterval);

// IOLog("fpp %d %d %.4f.\n", HF_TEMP_SAMPLE_FREQ, HF_TEMP_SAMPLE_PERIOD, (float)HF_TEMP_SAMPLE_REP);

});

// tempSamplePeriod = (int)((1.0f / (float)HF_TEMP_SAMPLE_FREQ) * 1000);
float fillT = getPackageTemp();
tempNextSample = 0;
for (int i = 0; i < HF_TEMP_SAMPLE_LEN; i++) tempSamples[i] = fillT;

timerEvent_tempe = IOTimerEventSource::timerEventSource(this, [](OSObject *object, IOTimerEventSource *sender) {
AMDRyzenCPUPowerManagement *provider = OSDynamicCast(AMDRyzenCPUPowerManagement, object);

int next_samp = provider->tempNextSample;
float t = provider->getPackageTemp();
provider->tempSamples[next_samp] = t;
provider->tempNextSample = (next_samp + 1) % HF_TEMP_SAMPLE_LEN;

sender->setTimeoutMS(HF_TEMP_SAMPLE_PERIOD);
});

registerService();

lastUpdateTime = getCurrentTimeNs();
pwrLastTSC = rdtsc64();
workLoop->addEventSource(timerEventSource);
timerEventSource->setTimeoutMS(1);
workLoop->addEventSource(timerEvent_main);
workLoop->addEventSource(timerEvent_tempe);
timerEvent_main->setTimeoutMS(1);
timerEvent_tempe->setTimeoutMS(HF_TEMP_SAMPLE_PERIOD);
}

void AMDRyzenCPUPowerManagement::stopWorkLoop() {
IOLog("AMDCPUSupport::startWorkLoop stopping timer");
timerEventSource->cancelTimeout();
workLoop->removeEventSource(timerEventSource);
timerEventSource->release();
// IOLog("AMDCPUSupport::startWorkLoop stopping timer");


workLoop->disableAllEventSources();
serviceInitialized = false;
}

void AMDRyzenCPUPowerManagement::resumeWorkLoop() {
workLoop->enableAllEventSources();
}

bool AMDRyzenCPUPowerManagement::start(IOService *provider){

bool success = IOService::start(provider);
Expand Down Expand Up @@ -300,8 +322,8 @@ bool AMDRyzenCPUPowerManagement::start(IOService *provider){

pwrTimeUnit = pow((double)0.5, (double)((rapl >> 16) & 0xf));
pwrEnergyUnit = pow((double)0.5, (double)((rapl >> 8) & 0x1f));
IOLog("a %lld\n", (long long)(pwrTimeUnit * 10000000000));
IOLog("b %lld\n", (long long)(pwrEnergyUnit * 10000000000));
// IOLog("a %lld\n", (long long)(pwrTimeUnit * 10000000000));
// IOLog("b %lld\n", (long long)(pwrEnergyUnit * 10000000000));

fetchOEMBaseBoardInfo();

Expand Down Expand Up @@ -355,7 +377,7 @@ bool AMDRyzenCPUPowerManagement::start(IOService *provider){
totalNumberOfPhysicalCores, totalNumberOfLogicalCores);

workLoop = IOWorkLoop::workLoop();
startWorkLoop();
initWorkLoop();


PMinit();
Expand All @@ -371,6 +393,9 @@ void AMDRyzenCPUPowerManagement::stop(IOService *provider){
IOLog("AMDCPUSupport stopped\n");

stopWorkLoop();
timerEvent_main->cancelTimeout();
workLoop->removeEventSource(timerEvent_main);
timerEvent_main->release();

if(superIO){
for (int i = 0; i < superIO->getNumberOfFans(); i++) {
Expand All @@ -396,7 +421,7 @@ IOReturn AMDRyzenCPUPowerManagement::setPowerState(unsigned long powerStateOrdin
// Waking up
IOLog("AMDCPUSupport::setPowerState preparing for wakeup\n");
wentToSleep = false;
startWorkLoop();
resumeWorkLoop();
}

return kIOPMAckImplied;
Expand Down Expand Up @@ -502,11 +527,11 @@ void AMDRyzenCPUPowerManagement::calculateEffectiveFrequency(uint8_t physical){
uint64_t APERF = APERF_lo | ((uint64_t)APERF_hi << 32);
uint64_t MPERF = MPERF_lo | ((uint64_t)MPERF_hi << 32);;

uint64_t lastAPERF = lastAPERF_PerCore[physical];
uint64_t lastMPERF = lastMPERF_PerCore[physical];
uint64_t lastAPERF = lastAPERF_perCore[physical];
uint64_t lastMPERF = lastMPERF_perCore[physical];

lastAPERF_PerCore[physical] = APERF;
lastMPERF_PerCore[physical] = MPERF;
lastAPERF_perCore[physical] = APERF;
lastMPERF_perCore[physical] = MPERF;
//If an overflow of either the MPERF or APERF register occurs between read of last MPERF and
//read of last APERF, the effective frequency calculated in is invalid.
if(APERF <= lastAPERF || MPERF <= lastMPERF) {
Expand Down Expand Up @@ -535,7 +560,7 @@ void AMDRyzenCPUPowerManagement::updateInstructionDelta(uint8_t cpu_num){
if(lastInstructionDelta_perCore[cpu_num] > insCount) return;

// uint64_t delta = insCount - lastInstructionDelta_perCore[cpu_num];
instructionDelta_PerCore[cpu_num] = insCount - lastInstructionDelta_perCore[cpu_num];
instructionDelta_perCore[cpu_num] = insCount - lastInstructionDelta_perCore[cpu_num];

lastInstructionDelta_perCore[cpu_num] = insCount;

Expand Down Expand Up @@ -589,7 +614,7 @@ bool AMDRyzenCPUPowerManagement::getCPBState(){
return !((hwConfig >> 25) & 0x1);
}

void AMDRyzenCPUPowerManagement::updatePackageTemp(){
inline float AMDRyzenCPUPowerManagement::getPackageTemp() {
IOPCIAddressSpace space;
space.bits = 0x00;

Expand All @@ -607,8 +632,13 @@ void AMDRyzenCPUPowerManagement::updatePackageTemp(){
if (tempOffsetFlag)
t -= 49.0f;


PACKAGE_TEMPERATURE_perPackage[0] = t;
return t;
}

void AMDRyzenCPUPowerManagement::updatePackageTemp(){
float sum = 0;
for (int i = 0; i < HF_TEMP_SAMPLE_LEN; i++) sum += tempSamples[i];
PACKAGE_TEMPERATURE_perPackage[0] = sum * HF_TEMP_SAMPLE_LENREP;
}

void AMDRyzenCPUPowerManagement::updatePackageEnergy(){
Expand Down
27 changes: 19 additions & 8 deletions AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,15 @@ class AMDRyzenCPUPowerManagement : public IOService {
void setCPBState(bool enabled);
bool getCPBState();

#define HF_TEMP_SAMPLE_SECS 3
#define HF_TEMP_SAMPLE_FREQ 2
#define HF_TEMP_SAMPLE_LEN (HF_TEMP_SAMPLE_SECS * HF_TEMP_SAMPLE_FREQ)
#define HF_TEMP_SAMPLE_LENREP (1.0f / (float)HF_TEMP_SAMPLE_LEN)
#define HF_TEMP_SAMPLE_REP (1.0f / (float)HF_TEMP_SAMPLE_FREQ)
#define HF_TEMP_SAMPLE_PERIOD (int)(HF_TEMP_SAMPLE_REP * 1000.0)
inline float getPackageTemp();
void updatePackageTemp();

void updatePackageEnergy();

void registerRequest();
Expand Down Expand Up @@ -192,16 +200,16 @@ class AMDRyzenCPUPowerManagement : public IOService {
float effFreq_perCore[CPUInfo::MaxCpus] {};
float PACKAGE_TEMPERATURE_perPackage[CPUInfo::MaxCpus];

uint64_t lastMPERF_PerCore[CPUInfo::MaxCpus];
uint64_t lastAPERF_PerCore[CPUInfo::MaxCpus];
uint64_t deltaMPERF_PerCore[CPUInfo::MaxCpus];
uint64_t lastMPERF_perCore[CPUInfo::MaxCpus];
uint64_t lastAPERF_perCore[CPUInfo::MaxCpus];
uint64_t deltaMPERF_perCore[CPUInfo::MaxCpus];

// uint64_t lastAPERF_PerCore[CPUInfo::MaxCpus];

uint64_t instructionDelta_PerCore[CPUInfo::MaxCpus];
uint64_t instructionDelta_perCore[CPUInfo::MaxCpus];
uint64_t lastInstructionDelta_perCore[CPUInfo::MaxCpus];

float loadIndex_PerCore[CPUInfo::MaxCpus];
float loadIndex_perCore[CPUInfo::MaxCpus];

float PStateStepUpRatio = 0.36;
float PStateStepDownRatio = 0.05;
Expand Down Expand Up @@ -231,7 +239,8 @@ class AMDRyzenCPUPowerManagement : public IOService {

private:
IOWorkLoop *workLoop;
IOTimerEventSource *timerEventSource;
IOTimerEventSource *timerEvent_main;
IOTimerEventSource *timerEvent_tempe;

bool serviceInitialized = false;

Expand All @@ -241,7 +250,8 @@ class AMDRyzenCPUPowerManagement : public IOService {
uint32_t estimatedRequestTimeInterval = 0;
uint32_t timeOfLastMissedRequest = 0;


int tempNextSample = 0;
float tempSamples[HF_TEMP_SAMPLE_LEN];
float tempOffset = 0;
double pwrTimeUnit = 0;
double pwrEnergyUnit = 0;
Expand All @@ -262,7 +272,8 @@ class AMDRyzenCPUPowerManagement : public IOService {
bool getPCIService();
bool wentToSleep;

void startWorkLoop();
void initWorkLoop();
void stopWorkLoop();
void resumeWorkLoop();
};
#endif
8 changes: 4 additions & 4 deletions SMCAMDProcessor.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@
buildSettings = {
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 0.6.6;
CURRENT_PROJECT_VERSION = 0.7;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
Expand All @@ -731,7 +731,7 @@
INFOPLIST_FILE = AMDRyzenCPUPowerManagement/Info.plist;
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Lilu.kext/Contents/Resources/Library";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.6.6;
MARKETING_VERSION = 0.7;
MODULE_NAME = wtf.spinach.AMDRyzenCPUPowerManagement;
MODULE_START = amdryzencpupm_kern_start;
MODULE_STOP = amdryzencpupm_kern_stop;
Expand Down Expand Up @@ -763,7 +763,7 @@
buildSettings = {
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 0.6.6;
CURRENT_PROJECT_VERSION = 0.7;
GCC_PREPROCESSOR_DEFINITIONS = (
"PRODUCT_NAME=$(PRODUCT_NAME)",
"MODULE_VERSION=$(MODULE_VERSION)",
Expand All @@ -776,7 +776,7 @@
INFOPLIST_FILE = AMDRyzenCPUPowerManagement/Info.plist;
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Lilu.kext/Contents/Resources/Library";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.6.6;
MARKETING_VERSION = 0.7;
MODULE_NAME = wtf.spinach.AMDRyzenCPUPowerManagement;
MODULE_START = amdryzencpupm_kern_start;
MODULE_STOP = amdryzencpupm_kern_stop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<key>AMD Power Gadget.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
<integer>1</integer>
</dict>
<key>AMDRyzenCPUPowerManagement.xcscheme_^#shared#^_</key>
<dict>
Expand All @@ -17,7 +17,7 @@
<key>SMCAMDProcessor.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
<integer>2</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
Expand Down

0 comments on commit aece378

Please sign in to comment.