Seems to be reset after sleep / hibernation
Hello,
It seems that after a sleep of the computer (MBP), the bit is reset to a default value (which is : Turbo Boost Enabled). As from the current implementation of the Kext, changes are only done on load and unload of the Kext. There is no monitoring of the value of the bit.
Perhaps one solution would be to catch the sleep / wake events and act accordingly, but then we don't know when the bit is reset - before, or after such event is caught.
Another option would be to monitor from time to time the bit ; and reset it to "Disabled" when we detect a change.
I have to join in on this one. Just noticed the same and wondered if its possible to implement one of the 2 solutions proposed before. I think it's easiest to just re-set the bit upon wake.
It seems implementation might actually be easy (I just went on and dug a bit through the documentaries as I'm personally not experienced with kext programming): https://developer.apple.com/library/mac/documentation/darwin/conceptual/kernelprogramming/services/services.html
Might give it a shot in the next few days...
@sieren Thanks so much for that pointer! I was thinking I'd have to do some weird IOKit stuff for state changes in IOPowerdomain (like this example, but your method is so much simpler and takes care of all the messy iokit stuff for you.
Here's basically the full code. I used Vegard's fork as a starting point since it was a bit cleaner to my eyes.
//
// DisableTurboBoost
// Copyright (C) 2020 Vegard Løkken
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <mach/mach_types.h>
#include <libkern/libkern.h>
#include <i386/proc_reg.h>
#include <IOKit/IOLib.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/IOService.h>
#include <IOKit/IONotifier.h>
// Execute action on all CPUs
extern "C" void mp_rendezvous_no_intrs(void (*action_func)(void *), void *arg);
IONotifier *notifier;
const uint64_t disableTurboBoost = ((uint64_t)1) << 38;
extern "C" {
void disable_tb(__unused void *param_not_used) {
wrmsr64(MSR_IA32_MISC_ENABLE,
rdmsr64(MSR_IA32_MISC_ENABLE) | disableTurboBoost);
}
void enable_tb(__unused void *param_not_used) {
wrmsr64(MSR_IA32_MISC_ENABLE,
rdmsr64(MSR_IA32_MISC_ENABLE) & ~disableTurboBoost);
}
IOReturn mySleepHandler(void *target, void *refCon, UInt32 messageType,
IOService *provider, void *messageArgument,
vm_size_t argSize) {
IOLog("Got sleep/wake notice. Message type was %d\n", messageType);
if (messageType == kIOMessageSystemHasPoweredOn) {
mp_rendezvous_no_intrs(disable_tb, NULL);
IOLog("Disabled Turbo Boost\n");
}
return 0;
}
}
extern "C" {
kern_return_t DisableTurboBoost_start(kmod_info_t *ki, void *d) {
/* uint64_t prev = rdmsr64(MSR_IA32_MISC_ENABLE); */
mp_rendezvous_no_intrs(disable_tb, NULL);
IOLog("Disabled Turbo Boost\n");
void *myself =
NULL; // Would pass the self pointer here if in a class instance
notifier = registerPrioritySleepWakeInterest(&mySleepHandler, myself, NULL);
return KERN_SUCCESS;
}
kern_return_t DisableTurboBoost_stop(kmod_info_t *ki, void *d) {
/* uint64_t prev = rdmsr64(MSR_IA32_MISC_ENABLE); */
mp_rendezvous_no_intrs(enable_tb, NULL);
IOLog("Re-enabled Turbo Boost\n");
if (notifier) {
notifier->remove();
}
return KERN_SUCCESS;
}
}
Be sure to include com.apple.kpi.iokit in OSBundleLibraries, but other than that it just works!
Also I'll add that if you want you can persist change for power envelope (PL1 and PL2) using a similar method also. I like this approach much more than using something like voltageshift since everything is self-contained and you don't need helper app running.
It's also interesting that unlike one of the other commenters mentioned I'm not seeing disabling turboboost impact speedstep in anyway. It still opportunistically downclocks to 1Ghz even though the base locked frequency would be 2.5GHz.
For completeness, I'll note here than an alternate approach to achieve the same thing is by creating an IOKit driver instead, and having two power states on/off which will be called by iokit in sleep transitions. See
https://github.com/riverai/DisableTurboBoost/blob/master/DisableTurboBoost/DisableTurboBoost.cpp
https://github.com/arter97/SimpleMSR