NVDAGPUWakeHandler: Disabling the NVIDIA graphics card on a MacBook Pro 10,1 (2012 retina)

On Friday my laptop stopped turning on normally, leaving me stuck with a black screen. The machine was still booting up (I could hear the chimes and the keyboard backlight worked), but no screen image or backlight whatsoever.

After taking it to the Apple Store, where they told me it was a Logic board failure, I learned that this is a known issue with this generation of MacBooks from 2011-2013. It stemms from the use of a lead-free solder that results in premature failure of the discrete graphics chips. Unfortunately, the replacement period ended in 2016.

However, laptops from this period also contain an integrated GPU as part of the Intel Core i5/i7 processor. This GPU is used during normal workloads to improve battery life, and the discrete NVIDIA GeForce 650M is powered down by a controller chip called the gmux. This made me to hope that by forcing the NVIDIA GPU to power down I could regain use of my laptop with only the integrated GPU. To do this, I adapted a macOS kernel extension derived from the source code for the Linux gmux driver. It’s available on Github as NVDAGPUWakeHandler.

Modifications to only use the Integrated GPU

Prefer Intel GPU on boot with NVRAM parameter

The MacBook boots with EFI, and hackers have found the following NVRAM parameter can be used to “prefer” the integrated GPU during startup:

sudo nvram fa4ce28d-b62f-4c99-9cc3-6815686e30f9:gpu-power-prefs=%01%00%00%00

For me, this restored the ability to boot up normally.

Disable NVIDIA GPU in BIOS

It is possible to power down the gpu during boot using a custom bootloader.

NOTE: The instructions for this need to be modified for the Retina MBP. The GRUB config for High Sierra / Mojave should be:

set timeout=10
menuentry "macOS" {
  outb 0x7c2 1
  outb 0x7d4 0x28
  outb 0x7c2 2
  outb 0x7d4 0x10
  outb 0x7c2 2
  outb 0x7d4 0x40

  outb 0x7c2 1
  outb 0x7d4 0x50
  outb 0x7c2 0
  outb 0x7d4 0x50
  exit
}

(Adapted from this post.)

After booting, I could see that only the integrated GPU was present in System Profiler:

One GPU

Disable NVIDIA GPU after waking from sleep

The same sequence of signals can be executed from a Kernel Extension (kext) to keep the GPU disabled after waking from sleep. I forked AMDGPUWakeHandler and modified it to execute the appropriate sequence for the Retina MBP.

My fork is available on GitHub. To install the kernel extension, you’ll need to either sign it with your own Apple developer account or disable SIP by booting into Recovery mode (CMD+R during boot) and running:

$ csrutil disable

You can verify that SIP is disabled by running csrutil status.

Enable backlight after waking from sleep in High Sierra (10.13) / Mojave (10.14)

This is sufficient to get the Mac to boot; however, in High Sierra something has changed such that the screen backlight controller no longer turns on after waking from sleep. If you hold up a flashlight, you can see that the screen is on, but with no backlight it appears nearly black. You can also see that macOS no longer thinks there is any backlight control for this display:

No backlight

Fortunately the Linux driver for the GMUX controller in the MBP contains code to support modifying the backlight setting. I adapted it for use in NVDAGPUWakeHandler to set the backlight to a usable level after waking from sleep. Note that it’s currently hard-coded in the Kext, so if you prefer a different brightness setting, you’ll have to adjust it as necessary.

Update: TankTheFrank on Github has contributed a patch that allows brightness to be controlled using the standard brightness keys! See NativeDisplayBrightness.

Conclusions

After installing the kernel extension, wake from sleep seems to be working correctly and I haven’t had any issues. The biggest insight for me was to see the amazing work that the Linux kernel devs have put in to reverse engineer and implement drivers for the rather unique MBP hardware. Despite having no experience with Linux kernel development the C code for apple-gmux.c was incredibly well-documented and easy to follow, making it easy to adapt and use in macOS.

References

[1] https://dhavaldalal.wordpress.com/2018/05/29/how-to-disable-failed-discrete-gpu-nvidia-geforce-gt-650m-for-macbook-pro-101-mid-2012-on-high-sierra-10-13-4/

[2] https://gist.github.com/blackgate/17ac402e35d2f7e0f1c9708db3dc7a44

[3] https://github.com/blackgate/AMDGPUWakeHandler

[4] https://forums.macrumors.com/threads/disable-a-failed-amd-gpu-on-a-2011-macbook-pro-grub-solution.2087527/page-7

[5] https://forums.macrumors.com/threads/force-2011-macbook-pro-8-2-with-failed-amd-gpu-to-always-use-intel-integrated-gpu-efi-variable-fix.2037591/page-81

[6] https://wiki.archlinux.org/index.php/MacBookPro10,x#Graphics_2


© 2018. All rights reserved.

Powered by Hydejack v8.1.1