Skip to content

UEFI Application for CPU Voltage/Frquency and Power Management adjustment. Great for undervolting.

License

Notifications You must be signed in to change notification settings

psyq321/PowerMonkey

Repository files navigation

Reduce CPU Power Waste and Gain Performance. Greener and Meaner!

   ______                            ______                 _
  (_____ \                          |  ___ \               | |
   _____) )___   _ _ _   ____   ___ | | _ | |  ___   ____  | |  _  ____  _   _
  |  ____// _ \ | | | | / _  ) / __)| || || | / _ \ |  _ \ | | / )/ _  )| | | |
  | |    | |_| || | | |( (/ / | |   | || || || |_| || | | || |< (( (/ / | |_| |
  |_|     \___/  \____| \____)|_|   |_||_||_| \___/ |_| |_||_| \_)\____) \__  |
                                                                        (____/
  Copyright (C) 2021 Ivan Dimkovic. All rights reserved.
  
  WARNING: This code is a proof of concept for educative purposes. It can
  modify internal computer configuration parameters and cause malfunctions or
  even permanent damage. It has been tested on a limited range of target CPUs
  and has minimal built-in failsafe mechanisms, thus making it unsuitable for
  recommended use by users not skilled in the art. Use it at your own risk.

What is PowerMonkey?

Background

By the 2020s, everybody knows what ‘overclocking’ is: bringing the system to its limits by increasing its working frequency, voltage or both. This process used to be very error-prone but it got perfected in the meantime, with even some big-name systems coming “factory overclocked” out of the box.

However, much fewer people have heard about its cousin: undervolting. Undervolting is, in a way, an opposite process from overclocking: reducing CPU voltage to the point, CPU consumes much less power and generates way less heat.

Intriguingly, doing this to the thermally limited system such as a notebook or SFF (small form factor) PC will both reduce heat AND improve performance! Magic? No, physics! There is only so much heat a notebook cooling system can evacuate, and once this route becomes exhausted, there is no other option but to throttle the CPU to prevent catastrophic failure. Reducing voltage at high frequencies significantly decreases power and heat output thus making the system cooler and faster.

Challenges

Sadly, it has become increasingly difficult to optimize a typical notebook. First, undervolting became mostly locked-by-default by OEMs. This problem can be mitigated by “unlocking” the firmware settings so that excellent applications like ThrottleStop can do their job (unless the platform is fully locked).

But new problems are in sight: Hypervisors such as Microsoft Hyper-V are now used even by end-user applications like WSL2 (Windows Subsystem for Linux). Because Hypervisor does not allow a Virtual Machine to modify most of the host hardware registers, applications like ThrottleStop or Intel’s XTU cannot adjust voltages.

When application attempts to write to a hardware register, Hypervisor traps this attempt and does not perform the actual writing. It is heoretically possible that Hypervisor vendor implements writing, but highly unlikely. This has created new barriers for undervolting and similar types of hardware tweaks.

Nothing above would be a problem if OEMs allowed customers to adjust the settings in the firmware setup. However, most notebooks come with minimal configuration options, locking the owner of being able to adjust their hardware. PowerMonkey POC intends to fix precisely this problem, and this repository is the first “proof-of-concept” showing viability of such an approach.

How does PowerMonkey work?

This proof-of-concept is using ability of UEFI firmwares to execute so-called "applications" before OS bootoader is invoked. At that moment (providing that the firmware did not lock) it is possible to (almost) fully adjust CPU frequency and voltages as well as power management configuration. This is later in the boot process (see below) as opposed to how OEM would do it, but since "advanced setup" is not an option, this is actually the second best place.

Below picture explains where PowerMonkey.efi POC resides:

EfiGood

Enabled Features

NOTE: PowerMonkey is a POC and is not tested on anything other than few CML (10th Gen) systems. At this stage, usage is recommended only to developers and experts under precautions. There are no checks for CPU compatibility so crashes could occur. It can brick computers or cause them to fail in all kinds of ways!

Feature Status
Voltage / Frequency Overrides
Voltage Override for entire VF Curve Enabled
Targetted voltage mode Enabled
Interpolative voltage mode Enabled
Voltage offset Enabled
Voltage adjustment on individual VF Points In Progress
Turbo Bins
Max. Turbo Ratios for different core counts Enabled
Power Limits
Enable/Disable/Lock PL1/PL2/PL3/PL4/PP0/... Enabled
Power and Time Limits adjustment (where possible) Enabled
Package and Platform (PSys) Domains Enabled
MSR and MMIO Control Enabled
Lockdown
Optional Overclocking Lockdown Enabled
Fine-grained Lockdown of different Power registers Enabled

Getting Started

Build the binaries

Because PowerMonkey is in the “proof-of-concept” stage right now. It is also necessary to adjust the CPU voltage/frequency/power override parameters to match your CPU. It is essential to build PowerMonkey from the source code.

  1. Clone PowerMoneky repository (this repository)

  2. Decide if you want to build PowerMonkey.efi using ‘official’ UEFI EDK (TianoCore), or if you wish to handle everything in Visual Studio?

After you have decided how to build PowerMonkey, please take some time to review and understand CONFIGURATION.c file where the entire configuration interface and options reside. Configuration process is exactly the same for both build methods and does not depend on the choice of build toolchain.

Building - "Visual Studio" route:

This route is based on Alex Ionescu’s excellent VisualUEFI project. The advantage of this approach is that you do not need to deal with the EDK2 build system and its config files.

  1. Fetch VisualUEFI from https://github.com/ionescu007/VisualUefi and build its prerequisites (follow the instructions)

  2. Store PowerMonkey directory (and its subdirectories) directly in the root of the VisualUEFI repo:

    VisualUEFI
    ├── debugger/
    ├── EDK-II/
    ├── edk2/
    ├── openssl/
    ├── PowerMonkey/                           <––– Our Workspace
    │   ├── PowerMonkeyApp/                    <--- Source code
    │   │   ├── CONFIGURATION.c                <--- This is where settings are
    │   │   └── ...
    │   ├── LICENSE
    │   ├── PmWorkspace.default.props
    │   ├── PmWorkspace.props
    │   ├── PmWorksspace.sln                   <--- Visual Studio Solution File
    │   └── README.MD
    ├── Samples/
    └── ...
  3. Open PmWorkspace.sln and build the project directly in Visual Studio. This process shall generate no warnings or errors. The result should be an EFI executable /PowerMonkey/x64/Release/PowerMonkey.efi

Building - EDK2 route:

  1. Download EDK2 source from https://github.com/tianocore/edk2 - ideally, the EDK2 version shall match your computer firmware “baseline EDK2 version” in case your UEFI firmware is based on TianoCore.

  2. Store PowerMonkeyApp directory (and its subdirectories) in the /MdeModulePkg/Application subdirectory of EDK2 workspace. The result shall look something like this (there will be more directories):

    EDK
    ├── BaseTools/
    ├── Conf/
    ├── MdeModulePkg/
    │   ├── Application/
    │   │   ├── BootManagerMenuApp/
    │   │   ├── CapsuleApp/
    │   │   ├── PowerMonkeyApp/         <––– Our Project
    │   │   │   ├── CONFIGURATION.c     <--- This is where settings are
    │   │   │   └── ...
    │   │   └── UiApp/
    │   ├── Include/
    │   └── Library/
    ├── UefiCpuPkg/
    ├── edksetup.bat
    └── ...
  3. Edit the /MdeModulePkg/MdeModulePkg.dsc file, and add PowerMonkey project inside:

    [Components]
    MdeModulePkg/Application/PowerMonkeyApp/PowerMonkey.inf
  4. Building process that follows is identical as for any other EDK2 project (edksetup.bat, build, ...).

Testing

In order to prevent reboot-loops it is highly advisable to first test PowerMonkey.efi by loading it from EFI shell or from a separate Booltloader entry (such as GRUB2). This way it is easy to revert back to original settings.

PowerMonkey.efi shall be executed before OS Bootloader. This can be achieved in many ways, the most obvious and least automated would be invocation through EFI shell. Executing PowerMonkey.efi shall result in something like this:

In case of failure, you will probably either see a crash information or a frozen computer. If everything worked, the view from the EFI shell should look like this:

EfiGood

If the computer is still alive and not frozen, you might proceed to your OS of choice to confirm that the settings have been applied. Do not forget to disable Hypervisor first, as one enabled, you will not be able to actually see the voltages from a VM. Settingfs form the CONFIGURATION.c applied to my CPU result in the following (pictures of ThrottleStop and XTU just reading the values from the CPU):

Intel XTU:

EfiGood

ThrottleStop:

EfiGood

This confirms that our settings have been applied including the locks (we locked the configuration so that it cannot be changed until the next reset). Before we go further, we shall check how much of a performance impact this has on our system.

Cinebench R23

Cinebench is one of the quickest showcases of how effective undervolting can be. Its workload is CPU-heavy, solving a real-world problem (rendering) and not some artificial stressor designed solely to waste CPU cycles in a way no actual application would do. As a bonus, Cinebench results immediately show if PowerMonkey settings were applied or not.

Without further ado, the results:

cinebench

TL;DR - By setting few knobs and dropping the voltage by 125 mV, we just made the laptop 23% faster. We did not "overclock" anything (although we did remove boost limits), CPU's own power management circuitry did it for us!

Things become even more interesting if one logs the data and checks what has CPU been doing while running Cinebench benchmark:

DESCRIPTION FACTORY SETTINGS POWERMONKEY -125mV
Cinebench R23 (Multi Core) 8299 10219 (+23.1%)
Avg. all-core clock in test 3.35 GHz 3.99 GHz (+19.1%)
Total energy spent during test 1.35 (Rel) 1.0 (Rel)

So, we gained 0.64 GHz in sustained 100% load, all while becoming 35% more energy efficient! Like like an advertisement, but this IS what is going on*!

(*) OK, it has to be told that -125 mV is considered a very aggressive undervolt for an average Comet Lake H CPU specimen. Mine seems happy, but there is much more to this story that I will cover some other time. For now, let me state that observation has led me to believe that it is something else that makes these settings reported not stable, and that problem already has a fix (albeit just for fully unlocked 'OC' models atm.).

THis particular CML-H model could theoretically sustain 4.2 GHz all-core load, as this is what it has been fused with as maximum. Looking at ThrottleStop logs it shows that now we are thermally limited. This particular laptop does look like it could benefit from re-pasting so maybe sustaining 4.2 GHz is doable.

But... HOW?

Extra 650 MHz and energy saved? Where is the catch?

There is no catch, just laws of physics. Notebook CPU is encased inside the scorching environment that cannot evacuate heat as effectively as, say, a server could.

Just looking at the dimensions of notebook parts (esp. the thermal solution,) it becomes apparent that we will not be pushing out hundreds of watts out of that space. The test system used here can deal with ~100-110W (internal measurements), if you are OK with your computer sounding like a jet engine. So this is our limit, but reasonable people would dial that down to 70-80W if they value their hearing.

CPU usually gets part of that budget (sometimes dynamic), so it would typically get 45-60W. And then, its power management circuit has to stay within these bounds with some well-defined and very short-term exceptions.

If we stayed with the original voltages, the power draw is significantly higher (remember, this is non-linear scaling!). So, the only thing a CPU could do is to dial its frequency down to stay within the power / thermal budget.

Another point is the temperature. When undervolted, the number of times CPU must temporarily freeze its execution to cool down ("throttle") is much lower or even zero. This also significantly boosts real-world speed.

And that is all to it (complications aside): if you manage to drop CPU power draw, its PMC will thank you with higher operating points.

Moving onto Hyper-V

Now that we know undervolting works as intended, we are ready to switch Hyper-V back and see how much (if anything) we would gain in WSL2 tasks. To be continued. For now, please find very preliminary results testing Linux kernel compilation (Linux kernel is WSL2 + extra config flags and modules):

Things become even more interesting if one logs the data and checks what has CPU been doing while running Cinebench benchmark:

DESCRIPTION FACTORY SETTINGS POWERMONKEY -125mV
WSL2 Custom Linux Kernel Build
Total Build Time 18m18.203s 17m21.769s

Differences are less drastic compared to Cinebench, which is to be expected as Linux kernel build is not so CPU-heavy. Still, it is almost a minute faster and, as originally intended: serves to prove that custom CPU settings are active under Hyper-V.

About

UEFI Application for CPU Voltage/Frquency and Power Management adjustment. Great for undervolting.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •