Compare commits

..

4 Commits

Author SHA1 Message Date
cryobry
d214954a98 Point systemd service at correct script location 2020-11-09 12:15:19 -05:00
cryobry
804820f273 Remove python3-configparser dependency, use pip instead 2020-11-09 11:22:29 -05:00
cryobry
7ac6c775a6 Merge upstream 2020-11-09 10:48:40 -05:00
cryobry
302702efe3 Update throttled.spec version to supersede upstream 2020-02-27 11:12:40 -05:00
10 changed files with 91 additions and 31 deletions

2
.gitignore vendored
View File

@@ -29,7 +29,7 @@ wheels/
# Usually these files are written by a python script from a template # Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it. # before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest *.manifest
#*.spec *.spec
# Installer logs # Installer logs
pip-log.txt pip-log.txt

View File

@@ -7,7 +7,7 @@ On systems where the EC doesn't reset the values (ex: ASUS Zenbook UX430UNR), th
### Tested hardware ### Tested hardware
Other users have confirmed that the tool is also working for these laptops: Other users have confirmed that the tool is also working for these laptops:
- Lenovo T480, T480s, X1C5, X1C6, T580, L480, T470, X280, ThinkPad Anniversary Edition 25, E590 w/ RX 550X, P43s, E480, E580 - Lenovo T480, T480s, X1C5, X1C6, T580, L490, L480, T470, X280, ThinkPad Anniversary Edition 25, E590 w/ RX 550X, P43s, E480, E580
- Dell XPS 9365, 9370, Latitude 7390 2-in-1 - Dell XPS 9365, 9370, Latitude 7390 2-in-1
- Microsoft Surface Book 2 - Microsoft Surface Book 2
@@ -24,7 +24,7 @@ The tool supports **undervolting** the CPU by configuring voltage offsets for CP
The tool now supports overriding the **IccMax** by configuring the maximum allowed current for CPU, cache and GPU planes. The tool will re-apply IccMax on resume from standby and hibernate. You can now either use the `ICCMAX` key in config to set global values or the `ICCMAX.AC` and `ICCMAX.BATTERY` keys to selectively set current values for the two power profiles. **NOTE:** the values specified in the config file are the actual current limit of your system, so those are not a offset from the default values as for the undervolt. As such, you should first find your system default values with the `--monitor` command. The tool now supports overriding the **IccMax** by configuring the maximum allowed current for CPU, cache and GPU planes. The tool will re-apply IccMax on resume from standby and hibernate. You can now either use the `ICCMAX` key in config to set global values or the `ICCMAX.AC` and `ICCMAX.BATTERY` keys to selectively set current values for the two power profiles. **NOTE:** the values specified in the config file are the actual current limit of your system, so those are not a offset from the default values as for the undervolt. As such, you should first find your system default values with the `--monitor` command.
### HWP override (EXPERIMENTAL) ### HWP override (EXPERIMENTAL)
I have found that under load my CPU was not always hitting max turbo frequency, in particular when using one/two cores only. For instance, when running [prime95](https://www.mersenne.org/download/) (1 core, test #1) my CPU is limited to about 3500 MHz over the theoretical 4000 MHz maximum. The reason is the value for the HWP energy performance [hints](http://manpages.ubuntu.com/manpages/artful/man8/x86_energy_perf_policy.8.html). By default TLP sets this value to `balance_performance` on AC in order to reduce the power consumption/heat in idle. By setting this value to `performance` I was able to reach 3900 MHz in the prime95 single core test, achieving a +400 MHz boost. Since this value forces the CPU to full speed even during idle, a new experimental feature allows to automatically set HWP to performance under load and revert it to balanced when idle. This feature can be enabled (in AC mode *only*) by setting to `True` the `HWP_Mode` parameter in the lenovo_fix config file : https://github.com/erpalma/throttled/blob/master/etc/lenovo_fix.conf#L39 . I have found that under load my CPU was not always hitting max turbo frequency, in particular when using one/two cores only. For instance, when running [prime95](https://www.mersenne.org/download/) (1 core, test #1) my CPU is limited to about 3500 MHz over the theoretical 4000 MHz maximum. The reason is the value for the HWP energy performance [hints](http://manpages.ubuntu.com/manpages/artful/man8/x86_energy_perf_policy.8.html). By default TLP sets this value to `balance_performance` on AC in order to reduce the power consumption/heat in idle. By setting this value to `performance` I was able to reach 3900 MHz in the prime95 single core test, achieving a +400 MHz boost. Since this value forces the CPU to full speed even during idle, a new experimental feature allows to automatically set HWP to performance under load and revert it to balanced when idle. This feature can be enabled (in AC mode *only*) by setting to `True` the `HWP_Mode` parameter in the lenovo_fix config file : https://github.com/erpalma/throttled/blob/master/etc/lenovo_fix.conf#L41 .
I have run **[Geekbench 4](https://browser.geekbench.com/v4/cpu/8656840)** and now I can get a score of 5391/17265! On `balance_performance` I can reach only 4672/16129, so **15% improvement** in single core and 7% in multicore, not bad ;) I have run **[Geekbench 4](https://browser.geekbench.com/v4/cpu/8656840)** and now I can get a score of 5391/17265! On `balance_performance` I can reach only 4672/16129, so **15% improvement** in single core and 7% in multicore, not bad ;)
@@ -35,7 +35,16 @@ On a lot of modern CPUs from Intel one can configure the TDP up or down based on
A stripped down version of the python module `python-periphery` is now built-in and it is used for accessing the MCHBAR register by memory mapped I/O. You also need `dbus` and `gobject` python bindings for listening to dbus signals on resume from sleep/hibernate. A stripped down version of the python module `python-periphery` is now built-in and it is used for accessing the MCHBAR register by memory mapped I/O. You also need `dbus` and `gobject` python bindings for listening to dbus signals on resume from sleep/hibernate.
### Writing to MSR and PCI BAR ### Writing to MSR and PCI BAR
Right now it is mandatory to **disable Secure Boot** (in BIOS) in order to avoid [Kernel Lockdown](https://lwn.net/Articles/706637/). In particular Lockdown restricts access to MSR and PCI BAR (via /dev/mem) which are required by this tool. Some time ago a feature called [Kernel Lockdown](https://lwn.net/Articles/706637/) was added to Linux. Kernel Lockdown automatically enables some security measures when Secure Boot is enabled, among them restricted access to MSR and PCI BAR via /dev/mem, which this tool requires. There are two ways to get around this: You can either disable Secure Boot in your firmware settings, or disable the Kernel Lockdown LSM.
The LSM can be disabled this way: Check the contents of the file `/sys/kernel/security/lsm` (example contents: `capability,lockdown,yama`). Take the contents of the file, remove `lockdown` and add the rest as a kernel parameter, like this: `lsm=capability,yama`. Reboot and Kernel Lockdown will be disabled!
As of Linux 5.9, kernel messages will be logged whenever the script writes to MSR registers. These aren't a problem for now, but there's some indication that future kernels may restrict MSR writes from userspace by default. This is being tracked by issue #215. The messages will look something like:
```
[ 324.833543] msr: Write to unrecognized MSR 0x1a2 by python3
Please report to x86@kernel.org
```
Note that some kernels (e.g. [linux-hardened](https://www.archlinux.org/packages/extra/x86_64/linux-hardened/)) will prevent from writing to `/dev/mem` too. Specifically, you need a kernel with `CONFIG_DEVMEM` and `CONFIG_X86_MSR` set. Note that some kernels (e.g. [linux-hardened](https://www.archlinux.org/packages/extra/x86_64/linux-hardened/)) will prevent from writing to `/dev/mem` too. Specifically, you need a kernel with `CONFIG_DEVMEM` and `CONFIG_X86_MSR` set.
### Thermald ### Thermald
@@ -63,8 +72,8 @@ sudo rc-service lenovo_fix start
### Debian/Ubuntu ### Debian/Ubuntu
``` ```
sudo apt install git build-essential python3-dev libdbus-glib-1-dev libgirepository1.0-dev libcairo2-dev python3-venv python3-wheel sudo apt install git build-essential python3-dev libdbus-glib-1-dev libgirepository1.0-dev libcairo2-dev python3-venv python3-wheel
git clone https://github.com/erpalma/lenovo-throttling-fix.git git clone https://github.com/erpalma/throttled.git
sudo ./lenovo-throttling-fix/install.sh sudo ./throttled/install.sh
``` ```
If you own a X1C6 you can also check a tutorial for Ubuntu 18.04 [here](https://mensfeld.pl/2018/05/lenovo-thinkpad-x1-carbon-6th-gen-2018-ubuntu-18-04-tweaks/). If you own a X1C6 you can also check a tutorial for Ubuntu 18.04 [here](https://mensfeld.pl/2018/05/lenovo-thinkpad-x1-carbon-6th-gen-2018-ubuntu-18-04-tweaks/).
@@ -90,8 +99,8 @@ sudo systemctl enable --now throttled
If you prefer to install from source, you can use the following commands. If you prefer to install from source, you can use the following commands.
``` ```
sudo dnf install python3-cairo-devel cairo-gobject-devel gobject-introspection-devel dbus-glib-devel python3-devel make libX11-devel sudo dnf install python3-cairo-devel cairo-gobject-devel gobject-introspection-devel dbus-glib-devel python3-devel make libX11-devel
git clone https://github.com/erpalma/lenovo-throttling-fix.git git clone https://github.com/erpalma/throttled.git
sudo ./lenovo-throttling-fix/install.sh sudo ./throttled/install.sh
``` ```
Feedback about Fedora installation is welcome. Feedback about Fedora installation is welcome.
@@ -99,8 +108,8 @@ Feedback about Fedora installation is welcome.
User *brycecordill* reported that the following dependencies are required for installing in openSUSE, tested on openSUSE 15.0 Leap. User *brycecordill* reported that the following dependencies are required for installing in openSUSE, tested on openSUSE 15.0 Leap.
``` ```
sudo zypper install gcc make python3-devel dbus-1-glib-devel python3-cairo-devel cairo-devel python3-gobject-cairo gobject-introspection-devel sudo zypper install gcc make python3-devel dbus-1-glib-devel python3-cairo-devel cairo-devel python3-gobject-cairo gobject-introspection-devel
git clone https://github.com/erpalma/lenovo-throttling-fix.git git clone https://github.com/erpalma/throttled.git
sudo ./lenovo-throttling-fix/install.sh sudo ./throttled/install.sh
``` ```
### Gentoo ### Gentoo
@@ -112,6 +121,14 @@ systemctl enable throttled.service
systemctl start throttled.service systemctl start throttled.service
``` ```
### Solus
```
sudo eopkg it -c system.devel
sudo eopkg it git python3-devel dbus-glib-devel python3-cairo-devel libcairo-devel python3-gobject-devel
git clone https://github.com/erpalma/throttled.git
sudo ./throttled/install.sh
```
### Void ### Void
The installation itself will create a runit service as lenovo_fix, enable it and start it. Before installation, make sure dbus is running `sv up dbus`. The installation itself will create a runit service as lenovo_fix, enable it and start it. Before installation, make sure dbus is running `sv up dbus`.
@@ -119,9 +136,9 @@ The installation itself will create a runit service as lenovo_fix, enable it and
``` ```
sudo xbps-install -Sy gcc git python3-devel dbus-glib-devel libgirepository-devel cairo-devel python3-wheel pkg-config make sudo xbps-install -Sy gcc git python3-devel dbus-glib-devel libgirepository-devel cairo-devel python3-wheel pkg-config make
git clone https://github.com/erpalma/lenovo-throttling-fix.git git clone https://github.com/erpalma/throttled.git
sudo ./lenovo-throttling-fix/install.sh sudo ./throttled/install.sh
``` ```
### Uninstall ### Uninstall
@@ -154,7 +171,7 @@ On Arch you should probably use `pacman -R lenovo-throttling-fix-git` instead.
### Update ### Update
If you update the tool you should manually check your config file for changes or additional features and modify it accordingly. The update process is then as simple as: If you update the tool you should manually check your config file for changes or additional features and modify it accordingly. The update process is then as simple as:
``` ```
cd lenovo-throttling-fix cd throttled
git pull git pull
sudo ./install.sh sudo ./install.sh
sudo systemctl restart lenovo_fix.service sudo systemctl restart lenovo_fix.service
@@ -281,5 +298,18 @@ This is an example output:
..... .....
``` ```
## Autoreload
Auto reload config on changes (unless it's deleted) can be enabled/disabled in the config
```
[General]
Autoreload = True
```
## A word about manufacturer provided tooling
Tools provided by your notebook manufacturer like [Dell Power Manager](https://www.dell.com/support/contents/us/en/04/article/product-support/self-support-knowledgebase/software-and-downloads/dell-power-manager) tend to persist their settings to the system board. If you ever had it running under Windows and activated a cool/quiet/silent/saving profile, this setting will still be active when running linux, throttling your system.
> On my Dell Latitude 5591, not even a BIOS reset to manufacturar default killed the active `Quiet` profile
## Disclaimer ## Disclaimer
This script overrides the default values set by Lenovo. I'm using it without any problem, but it is still experimental so use it at your own risk. This script overrides the default values set by Lenovo. I'm using it without any problem, but it is still experimental so use it at your own risk.

2
etc/lenovo_fix.conf Normal file → Executable file
View File

@@ -3,6 +3,8 @@
Enabled: True Enabled: True
# SYSFS path for checking if the system is running on AC power # SYSFS path for checking if the system is running on AC power
Sysfs_Power_Path: /sys/class/power_supply/AC*/online Sysfs_Power_Path: /sys/class/power_supply/AC*/online
# Auto reload config on changes
Autoreload: True
## Settings to apply while connected to Battery power ## Settings to apply while connected to Battery power
[BATTERY] [BATTERY]

View File

@@ -39,6 +39,7 @@ cp -n requirements.txt lenovo_fix.py mmio.py "$INSTALL_DIR"
cd "$INSTALL_DIR" cd "$INSTALL_DIR"
/usr/bin/python3 -m venv venv /usr/bin/python3 -m venv venv
. venv/bin/activate . venv/bin/activate
pip install wheel
pip install -r requirements.txt pip install -r requirements.txt
if pidof systemd 2>&1 1>/dev/null; then if pidof systemd 2>&1 1>/dev/null; then

View File

@@ -30,7 +30,8 @@ TRIP_TEMP_RANGE = [40, 97]
UNDERVOLT_KEYS = ('UNDERVOLT', 'UNDERVOLT.AC', 'UNDERVOLT.BATTERY') UNDERVOLT_KEYS = ('UNDERVOLT', 'UNDERVOLT.AC', 'UNDERVOLT.BATTERY')
ICCMAX_KEYS = ('ICCMAX', 'ICCMAX.AC', 'ICCMAX.BATTERY') ICCMAX_KEYS = ('ICCMAX', 'ICCMAX.AC', 'ICCMAX.BATTERY')
power = {'source': None, 'method': 'polling'} power = {'source': None, 'method': 'polling'}
HWP_VALUE = 0x20 HWP_PERFORMANCE_VALUE = 0x20
HWP_DEFAULT_VALUE = 0x80
HWP_INTERVAL = 60 HWP_INTERVAL = 60
@@ -77,7 +78,7 @@ supported_cpus = {
'Kaby Lake (R)': (0x8E, 0x9E), 'Kaby Lake (R)': (0x8E, 0x9E),
'Coffee Lake': (0x9E,), 'Coffee Lake': (0x9E,),
'Cannon Lake': (0x66,), 'Cannon Lake': (0x66,),
'Comet Lake': (0xA6,), 'Comet Lake': (0xA5, 0xA6),
} }
@@ -517,16 +518,17 @@ def calc_reg_values(platform_info, config):
return regs return regs
def set_hwp(): def set_hwp(performance_mode):
# set HWP energy performance preference # set HWP energy performance preference
cur_val = readmsr(0x774, cpu=0) cur_val = readmsr(0x774, cpu=0)
new_val = (cur_val & 0xFFFFFFFF00FFFFFF) | (HWP_VALUE << 24) hwp_mode = HWP_PERFORMANCE_VALUE if performance_mode else HWP_DEFAULT_VALUE
new_val = (cur_val & 0xFFFFFFFF00FFFFFF) | (hwp_mode << 24)
writemsr(0x774, new_val) writemsr(0x774, new_val)
if args.debug: if args.debug:
read_value = readmsr(0x774, from_bit=24, to_bit=31)[0] read_value = readmsr(0x774, from_bit=24, to_bit=31)[0]
match = OK if HWP_VALUE == read_value else ERR match = OK if hwp_mode == read_value else ERR
log('[D] HWP - write "{:#02x}" - read "{:#02x}" - match {}'.format(HWP_VALUE, read_value, match)) log('[D] HWP - write "{:#02x}" - read "{:#02x}" - match {}'.format(hwp_mode, read_value, match))
def set_disable_bdprochot(): def set_disable_bdprochot():
@@ -541,6 +543,23 @@ def set_disable_bdprochot():
log('[D] BDPROCHOT - write "{:#02x}" - read "{:#02x}" - match {}'.format(0, read_value, match)) log('[D] BDPROCHOT - write "{:#02x}" - read "{:#02x}" - match {}'.format(0, read_value, match))
def get_config_write_time():
try:
return os.stat(args.config).st_mtime
except FileNotFoundError:
return None
def reload_config():
config = load_config()
regs = calc_reg_values(get_cpu_platform_info(), config)
undervolt(config)
set_icc_max(config)
set_hwp(config.getboolean('AC', 'HWP_Mode', fallback=False))
log('[I] Reloading changes.')
return config, regs
def power_thread(config, regs, exit_event): def power_thread(config, regs, exit_event):
try: try:
mchbar_mmio = MMIO(0xFED159A0, 8) mchbar_mmio = MMIO(0xFED159A0, 8)
@@ -550,6 +569,8 @@ def power_thread(config, regs, exit_event):
mchbar_mmio = None mchbar_mmio = None
next_hwp_write = 0 next_hwp_write = 0
last_config_write_time = get_config_write_time() \
if config.getboolean('GENERAL', 'Autoreload', fallback=False) else None
while not exit_event.is_set(): while not exit_event.is_set():
# log thermal status # log thermal status
if args.debug: if args.debug:
@@ -558,6 +579,13 @@ def power_thread(config, regs, exit_event):
for key, value in core_thermal_status.items(): for key, value in core_thermal_status.items():
log('[D] core {} thermal status: {} = {}'.format(index, key.replace("_", " "), value)) log('[D] core {} thermal status: {} = {}'.format(index, key.replace("_", " "), value))
# Reload config on changes (unless it's deleted)
if config.getboolean('GENERAL', 'Autoreload', fallback=False):
config_write_time = get_config_write_time()
if config_write_time and last_config_write_time != config_write_time:
last_config_write_time = config_write_time
config, regs = reload_config()
# switch back to sysfs polling # switch back to sysfs polling
if power['method'] == 'polling': if power['method'] == 'polling':
power['source'] = 'BATTERY' if is_on_battery(config) else 'AC' power['source'] = 'BATTERY' if is_on_battery(config) else 'AC'
@@ -628,7 +656,7 @@ def power_thread(config, regs, exit_event):
or (power['method'] == 'polling' and not is_on_battery(config)) or (power['method'] == 'polling' and not is_on_battery(config))
) )
): ):
set_hwp() set_hwp(enable_hwp_mode)
next_hwp_write = time() + HWP_INTERVAL next_hwp_write = time() + HWP_INTERVAL
else: else:
@@ -791,14 +819,15 @@ def main():
log('[I] Throttled is disabled in config file... Quitting. :(') log('[I] Throttled is disabled in config file... Quitting. :(')
return return
undervolt(config)
set_icc_max(config)
set_hwp(config.getboolean('AC', 'HWP_Mode', fallback=False))
exit_event = Event() exit_event = Event()
thread = Thread(target=power_thread, args=(config, regs, exit_event)) thread = Thread(target=power_thread, args=(config, regs, exit_event))
thread.daemon = True thread.daemon = True
thread.start() thread.start()
undervolt(config)
set_icc_max(config)
# handle dbus events for applying undervolt/IccMax on resume from sleep/hybernate # handle dbus events for applying undervolt/IccMax on resume from sleep/hybernate
def handle_sleep_callback(sleeping): def handle_sleep_callback(sleeping):
if not sleeping: if not sleeping:

0
openrc/lenovo_fix Normal file → Executable file
View File

0
package/PKGBUILD Normal file → Executable file
View File

View File

@@ -1,3 +1,3 @@
configparser==3.8.1 configparser==5.0.0
dbus-python==1.2.8 dbus-python==1.2.16
PyGObject==3.32.2 PyGObject==3.38.0

2
systemd/lenovo_fix.service Normal file → Executable file
View File

@@ -6,8 +6,6 @@ Type=simple
ExecStart=/usr/bin/throttled --conf /etc/throttled.conf ExecStart=/usr/bin/throttled --conf /etc/throttled.conf
# Setting PYTHONUNBUFFERED is necessary to see the output of this service in the journal # Setting PYTHONUNBUFFERED is necessary to see the output of this service in the journal
Environment=PYTHONUNBUFFERED=1 Environment=PYTHONUNBUFFERED=1
StandardOutput=syslog
StandardError=syslog
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

4
throttled.spec Normal file → Executable file
View File

@@ -2,7 +2,7 @@
%define debug_package %{nil} %define debug_package %{nil}
Name: throttled Name: throttled
Version: 0.6 Version: 0.8
Release: 2 Release: 2
Summary: Workaround for Intel throttling issues in Linux Summary: Workaround for Intel throttling issues in Linux
License: MIT License: MIT
@@ -14,7 +14,7 @@ BuildRequires: systemd-units
Requires: python3 Requires: python3
Requires: python3-gobject Requires: python3-gobject
Requires: python3-configparser # Requires: python3-configparser # Not available in F33, install using pip instead
Requires: systemd Requires: systemd
Conflicts: thermald Conflicts: thermald