DisableTurboBoost.kext icon indicating copy to clipboard operation
DisableTurboBoost.kext copied to clipboard

Seems to be reset after sleep / hibernation

Open llange opened this issue 12 years ago • 4 comments

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.

llange avatar Sep 30 '13 10:09 llange

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 avatar Dec 27 '13 22:12 sieren

@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!

krackers avatar Apr 23 '22 08:04 krackers

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.

krackers avatar Apr 23 '22 08:04 krackers

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

krackers avatar Jun 14 '22 22:06 krackers