diff --git a/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.cpp b/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.cpp index 7f9b67e..310434f 100644 --- a/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.cpp +++ b/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.cpp @@ -39,20 +39,20 @@ bool AMDRyzenCPUPowerManagement::init(OSDictionary *dictionary){ IOLog("AMDCPUSupport v%s, init\n", xStringify(MODULE_VERSION)); IOLog("AMDCPUSupport::enter dlinking..\n"); - + pmRyzen_symtable_ready = 0; - + retry: find_mach_header_addr(getKernelVersion() >= KernelVersion::BigSur); pmRyzen_symtable._wrmsr_carefully = lookup_symbol("_wrmsr_carefully"); - + if(!pmRyzen_symtable._wrmsr_carefully){ kextloadAlerts++; IOSleep(2); goto retry; } - - + + pmRyzen_symtable._KUNCUserNotificationDisplayAlert = lookup_symbol("_KUNCUserNotificationDisplayAlert"); pmRyzen_symtable._cpu_to_processor = lookup_symbol("_cpu_to_processor"); pmRyzen_symtable._tscFreq = lookup_symbol("_tscFreq"); @@ -145,7 +145,7 @@ void AMDRyzenCPUPowerManagement::startWorkLoop() { //Read PStateDef generated by EFI. if(pmRyzen_cpu_is_master(cpu_num)) - provider->dumpPstate(); + provider->dumpPstate(nullptr); if(!pmRyzen_cpu_primary_in_core(cpu_num)) return; @@ -320,11 +320,11 @@ bool AMDRyzenCPUPowerManagement::start(IOService *provider){ IOLog("AMDCPUSupport::start no PCI support found, failing...\n"); return false; } - + // while (!pmRyzen_symtable_ready) { // IOSleep(200); // } - + void *safe_wrmsr = pmRyzen_symtable._wrmsr_carefully; if(!safe_wrmsr){ IOLog("AMDCPUSupport::start WARN: Can't find _wrmsr_carefully, proceeding with unsafe wrmsr\n"); @@ -390,12 +390,17 @@ IOReturn AMDRyzenCPUPowerManagement::setPowerState(unsigned long powerStateOrdin if (0 == powerStateOrdinal) { // Going to sleep IOLog("AMDCPUSupport::setPowerState preparing for sleep\n"); - wentToSleep = true; + sleepState.sleep = true; + sleepState.cpb = getCPBState(); + //dumpPstate(sleepState.pstate); + stopWorkLoop(); - } else if (1 == powerStateOrdinal && wentToSleep) { + } else if (1 == powerStateOrdinal && sleepState.sleep) { // Waking up IOLog("AMDCPUSupport::setPowerState preparing for wakeup\n"); - wentToSleep = false; + sleepState.sleep = false; + setCPBState(sleepState.cpb); + //writePstate(sleepState.pstate); startWorkLoop(); } @@ -510,18 +515,20 @@ void AMDRyzenCPUPowerManagement::calculateEffectiveFrequency(uint8_t physical){ //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) { -// IOLog("AMDCPUSupport::calculateEffectiveFrequency: frequency is invalid!!!"); + IOLog("AMDCPUSupport::calculateEffectiveFrequency: frequency is invalid for %u", physical); + lastAPERF_PerCore[physical] = APERF; + lastMPERF_PerCore[physical] = MPERF; return; } float freqP0 = PStateDefClock_perCore[0]; uint64_t deltaAPERF = APERF - lastAPERF; - float effFreq = ((float)deltaAPERF / (float)(MPERF - lastMPERF)) * freqP0; - - effFreq_perCore[physical] = effFreq; - - + uint64_t deltaMPERF = MPERF - lastMPERF; + if (deltaMPERF != 0) { + float effFreq = ((float)deltaAPERF / (float)(deltaMPERF)) * freqP0; + effFreq_perCore[physical] = effFreq; + } } void AMDRyzenCPUPowerManagement::updateInstructionDelta(uint8_t cpu_num){ @@ -633,9 +640,8 @@ void AMDRyzenCPUPowerManagement::updatePackageEnergy(){ pwrLastTSC = rdtsc64(); } -void AMDRyzenCPUPowerManagement::dumpPstate(){ +void AMDRyzenCPUPowerManagement::dumpPstate(uint64_t buf[8]){ - uint8_t len = 0; for (uint32_t i = 0; i < kMSR_PSTATE_LEN; i++) { uint64_t msr_value_buf = 0; bool err = !read_msr(kMSR_PSTATE_0 + i, &msr_value_buf); @@ -654,17 +660,12 @@ void AMDRyzenCPUPowerManagement::dumpPstate(){ PStateDef_perCore[i] = msr_value_buf; PStateDefClock_perCore[i] = clock; - if(msr_value_buf & ((uint64_t)1 << 63)) len++; - // IOLog("a: %llu", msr_value_buf); - } - - PStateEnabledLen = max(PStateEnabledLen, len); + if(buf != nullptr) buf[i] = msr_value_buf; + }; } void AMDRyzenCPUPowerManagement::writePstate(const uint64_t *buf){ - PStateEnabledLen = 0; - //A bit hacky but at least works for now. void* args[] = {this, (void*)buf}; @@ -687,7 +688,7 @@ void AMDRyzenCPUPowerManagement::writePstate(const uint64_t *buf){ if(!pmRyzen_cpu_is_master(cpu_number())) return; - provider->dumpPstate(); + provider->dumpPstate(nullptr); }, nullptr, args); @@ -725,7 +726,7 @@ EXPORT extern "C" kern_return_t amdryzencpupm_kern_start(kmod_info_t *, void *) // This works better and increases boot speed in some cases. PE_parse_boot_argn("liludelay", &ADDPR(debugPrintDelay), sizeof(ADDPR(debugPrintDelay))); ADDPR(debugEnabled) = checkKernelArgument("-amdpdbg"); - + // IOLog("AMDCPUSupport::enter dlinking..\n"); // // pmRyzen_symtable_ready = 0; @@ -741,7 +742,7 @@ EXPORT extern "C" kern_return_t amdryzencpupm_kern_start(kmod_info_t *, void *) // pmRyzen_symtable._i386_cpu_IPI = lookup_symbol("_i386_cpu_IPI"); // pmRyzen_symtable_ready = 1; // IOLog("AMDCPUSupport::enter link finished.\n"); - + return KERN_SUCCESS; } diff --git a/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.hpp b/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.hpp index 109319f..29d7ad9 100644 --- a/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.hpp +++ b/AMDRyzenCPUPowerManagement/AMDRyzenCPUPowerManagement.hpp @@ -78,6 +78,12 @@ typedef struct tctl_offset { int offset; } TempOffset; +typedef struct sleep_state { + bool sleep; + bool cpb; + uint64_t pstate[8]; +} SleepState; + static IOPMPowerState powerStates[kNrOfPowerStates] = { {1, kIOPMPowerOff, kIOPMPowerOff, kIOPMPowerOff, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -159,7 +165,7 @@ class AMDRyzenCPUPowerManagement : public IOService { void registerRequest(); - void dumpPstate(); + void dumpPstate(uint64_t buf[8]); void writePstate(const uint64_t *buf); bool initSuperIO(uint16_t* chipIntel); @@ -209,7 +215,6 @@ class AMDRyzenCPUPowerManagement : public IOService { uint8_t PStateCur_perCore[CPUInfo::MaxCpus]; uint8_t PStateCtl = 0; uint64_t PStateDef_perCore[8]; - uint8_t PStateEnabledLen = 0; float PStateDefClock_perCore[8]; bool cpbSupported; @@ -260,7 +265,8 @@ class AMDRyzenCPUPowerManagement : public IOService { KernelPatcher *liluKernelPatcher; bool getPCIService(); - bool wentToSleep; + + SleepState sleepState; void startWorkLoop(); void stopWorkLoop();