Compare commits

...

18 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
cryobry
c99b45f9d4 Merge branch 'master' of https://github.com/erpalma/throttled 2020-02-27 11:10:58 -05:00
erpalma
88216b119a add Comet Lake to the list of supported cpus (fix #150) 2020-02-20 10:30:08 +01:00
erpalma
d5ee6de8eb mention that all undervolt voltage must be negative in config file (fix #171) 2020-02-20 10:14:38 +01:00
erpalma
e897f95385 add logging to indicate that throttled is disabled in config file (fix #173) 2020-02-20 10:10:50 +01:00
Francesco Palmarini
2bd4626d8a Merge pull request #177 from Hyper-KVM/master
Add OpenRC support
2020-02-20 10:05:43 +01:00
Hyper-KVM
8300044558 Add Artix and OpenRC entries 2020-02-20 01:32:47 -05:00
Hyper-KVM
5fc826aac0 Add OpenRC support in install.sh 2020-02-19 20:03:44 -05:00
Hyper-KVM
a88689b8bb really fix init script this time 2020-02-19 18:48:54 -05:00
Hyper-KVM
c0b8c180bf fix init script 2020-02-19 16:40:52 -05:00
Hyper-KVM
422769aafd remove uneeded prepare function in PKGBUILD 2020-02-19 16:22:10 -05:00
Hyper-KVM
9cb8537425 fix PKGBUILD 2020-02-19 16:21:24 -05:00
Hyper-KVM
fbcbbb93c7 add PKGBUILD 2020-02-19 16:15:56 -05:00
Hyper-KVM
232fcc3882 Add OpenRC support testing 2020-02-19 15:57:14 -05:00
cryobry
a6026e8bb4 Development fork for copr 2020-02-18 13:44:46 -05:00
9 changed files with 227 additions and 29 deletions

View File

@@ -7,7 +7,7 @@ On systems where the EC doesn't reset the values (ex: ASUS Zenbook UX430UNR), th
### Tested hardware
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
- 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.
### 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 ;)
@@ -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.
### 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.
### Thermald
@@ -53,11 +62,18 @@ sudo systemctl enable --now lenovo_fix.service
```
Thanks to *felixonmars* for creating and maintaining this package.
### Artix Linux
```
makepkg -si
sudo rc-update add lenovo_fix default
sudo rc-service lenovo_fix start
```
### Debian/Ubuntu
```
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
sudo ./lenovo-throttling-fix/install.sh
git clone https://github.com/erpalma/throttled.git
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/).
@@ -83,8 +99,8 @@ sudo systemctl enable --now throttled
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
git clone https://github.com/erpalma/lenovo-throttling-fix.git
sudo ./lenovo-throttling-fix/install.sh
git clone https://github.com/erpalma/throttled.git
sudo ./throttled/install.sh
```
Feedback about Fedora installation is welcome.
@@ -92,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.
```
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
sudo ./lenovo-throttling-fix/install.sh
git clone https://github.com/erpalma/throttled.git
sudo ./throttled/install.sh
```
### Gentoo
@@ -105,6 +121,14 @@ systemctl enable 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
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`.
@@ -112,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
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
@@ -130,6 +154,12 @@ sv down lenovo_fix
rm /var/service/lenovo_fix
```
If you're using OpenRC instead of systemd:
```
rc-service lenovo_fix stop
rc-update del lenovo_fix default
```
If you also need to remove the tool from the system:
```
rm -rf /opt/lenovo_fix /etc/systemd/system/lenovo_fix.service
@@ -141,10 +171,11 @@ On Arch you should probably use `pacman -R lenovo-throttling-fix-git` instead.
### 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:
```
cd lenovo-throttling-fix
cd throttled
git pull
sudo ./install.sh
sudo systemctl restart lenovo_fix.service
OpenRC: sudo rc-service lenovo_fix restart
```
## Configuration
@@ -267,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
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.

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

@@ -3,6 +3,8 @@
Enabled: True
# SYSFS path for checking if the system is running on AC power
Sysfs_Power_Path: /sys/class/power_supply/AC*/online
# Auto reload config on changes
Autoreload: True
## Settings to apply while connected to Battery power
[BATTERY]
@@ -44,6 +46,7 @@ cTDP: 0
# Disable BDPROCHOT (EXPERIMENTAL)
Disable_BDPROCHOT: False
# All voltage values are expressed in mV and *MUST* be negative (i.e. undervolt)!
[UNDERVOLT.BATTERY]
# CPU core voltage offset (mV)
CORE: 0
@@ -56,6 +59,7 @@ UNCORE: 0
# Analog I/O voltage offset (mV)
ANALOGIO: 0
# All voltage values are expressed in mV and *MUST* be negative (i.e. undervolt)!
[UNDERVOLT.AC]
# CPU core voltage offset (mV)
CORE: 0

View File

@@ -6,6 +6,8 @@ if pidof systemd 2>&1 1>/dev/null; then
systemctl stop lenovo_fix.service >/dev/null 2>&1
elif pidof runit 2>&1 1>/dev/null; then
sv down lenovo_fix >/dev/null 2>&1
elif pidof openrc 2>&1 1>/dev/null; then
rc-service lenovo_fix stop >/dev/null 2>&1
fi
mkdir -p "$INSTALL_DIR" >/dev/null 2>&1
@@ -26,6 +28,10 @@ if pidof systemd 2>&1 1>/dev/null; then
elif pidof runit 2>&1 1>/dev/null; then
echo "Copying runit service file"
cp -R runit/lenovo_fix /etc/sv/
elif pidof openrc-init 2>&1 1>/dev/null; then
echo "Copying OpenRC service file"
cp -R openrc/lenovo_fix /etc/init.d/lenovo_fix
chmod 755 /etc/init.d/lenovo_fix
fi
echo "Building virtualenv..."
@@ -33,6 +39,7 @@ cp -n requirements.txt lenovo_fix.py mmio.py "$INSTALL_DIR"
cd "$INSTALL_DIR"
/usr/bin/python3 -m venv venv
. venv/bin/activate
pip install wheel
pip install -r requirements.txt
if pidof systemd 2>&1 1>/dev/null; then
@@ -44,6 +51,10 @@ elif pidof runit 2>&1 1>/dev/null; then
echo "Enabling and starting runit service..."
ln -sv /etc/sv/lenovo_fix /var/service/
sv up lenovo_fix
elif pidof openrc-init 2>&1 1>/dev/null; then
echo "Enabling and starting OpenRC service..."
rc-update add lenovo_fix default
rc-service lenovo_fix start
fi
echo "All done."

View File

@@ -30,7 +30,8 @@ TRIP_TEMP_RANGE = [40, 97]
UNDERVOLT_KEYS = ('UNDERVOLT', 'UNDERVOLT.AC', 'UNDERVOLT.BATTERY')
ICCMAX_KEYS = ('ICCMAX', 'ICCMAX.AC', 'ICCMAX.BATTERY')
power = {'source': None, 'method': 'polling'}
HWP_VALUE = 0x20
HWP_PERFORMANCE_VALUE = 0x20
HWP_DEFAULT_VALUE = 0x80
HWP_INTERVAL = 60
@@ -77,6 +78,7 @@ supported_cpus = {
'Kaby Lake (R)': (0x8E, 0x9E),
'Coffee Lake': (0x9E,),
'Cannon Lake': (0x66,),
'Comet Lake': (0xA5, 0xA6),
}
@@ -516,22 +518,23 @@ def calc_reg_values(platform_info, config):
return regs
def set_hwp():
def set_hwp(performance_mode):
# set HWP energy performance preference
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)
if args.debug:
read_value = readmsr(0x774, from_bit=24, to_bit=31)[0]
match = OK if HWP_VALUE == read_value else ERR
log('[D] HWP - write "{:#02x}" - read "{:#02x}" - match {}'.format(HWP_VALUE, read_value, match))
match = OK if hwp_mode == read_value else ERR
log('[D] HWP - write "{:#02x}" - read "{:#02x}" - match {}'.format(hwp_mode, read_value, match))
def set_disable_bdprochot():
# Disable BDPROCHOT
cur_val = readmsr(0x1FC,flatten=True)
new_val = (cur_val & 0xFFFFFFFFFFFFFFFE)
cur_val = readmsr(0x1FC, flatten=True)
new_val = cur_val & 0xFFFFFFFFFFFFFFFE
writemsr(0x1FC, new_val)
if args.debug:
@@ -540,6 +543,23 @@ def set_disable_bdprochot():
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):
try:
mchbar_mmio = MMIO(0xFED159A0, 8)
@@ -549,6 +569,8 @@ def power_thread(config, regs, exit_event):
mchbar_mmio = None
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():
# log thermal status
if args.debug:
@@ -557,6 +579,13 @@ def power_thread(config, regs, exit_event):
for key, value in core_thermal_status.items():
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
if power['method'] == 'polling':
power['source'] = 'BATTERY' if is_on_battery(config) else 'AC'
@@ -627,7 +656,7 @@ def power_thread(config, regs, exit_event):
or (power['method'] == 'polling' and not is_on_battery(config))
)
):
set_hwp()
set_hwp(enable_hwp_mode)
next_hwp_write = time() + HWP_INTERVAL
else:
@@ -787,16 +816,18 @@ def main():
regs = calc_reg_values(platform_info, config)
if not config.getboolean('GENERAL', 'Enabled'):
log('[I] Throttled is disabled in config file... Quitting. :(')
return
undervolt(config)
set_icc_max(config)
set_hwp(config.getboolean('AC', 'HWP_Mode', fallback=False))
exit_event = Event()
thread = Thread(target=power_thread, args=(config, regs, exit_event))
thread.daemon = True
thread.start()
undervolt(config)
set_icc_max(config)
# handle dbus events for applying undervolt/IccMax on resume from sleep/hybernate
def handle_sleep_callback(sleeping):
if not sleeping:

5
openrc/lenovo_fix Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/openrc-run
command="env python3 /usr/lib/throttled/lenovo_fix.py"
pidfile=${pidfile-/var/run/lenovo_fix.pid}
description="Stop Intel throttling"
command_background="yes"

31
package/PKGBUILD Executable file
View File

@@ -0,0 +1,31 @@
pkgname=throttled
pkgver=0.6
pkgrel=4
pkgdesc="Workaround for Intel throttling issues in Linux."
arch=('any')
url="https://github.com/erpalma/throttled"
license=('MIT')
depends=('python-dbus' 'python-psutil' 'python-gobject')
conflicts=('lenovo-throttling-fix-git' 'lenovo-throttling-fix')
replaces=('lenovo-throttling-fix')
backup=('etc/lenovo_fix.conf')
source=("git+https://github.com/Hyper-KVM/throttled.git#branch=openrc")
sha256sums=('SKIP')
build() {
cd "${srcdir}/throttled/"
python -m compileall *.py
}
package() {
cd "${srcdir}/throttled/"
install -Dm644 etc/lenovo_fix.conf "$pkgdir"/etc/lenovo_fix.conf
install -Dm644 systemd/lenovo_fix.service "$pkgdir"/usr/lib/systemd/system/lenovo_fix.service
install -Dm755 lenovo_fix.py "$pkgdir"/usr/lib/$pkgname/lenovo_fix.py
install -Dm755 openrc/lenovo_fix "$pkgdir/etc/init.d/lenovo_fix"
install -Dm755 mmio.py "$pkgdir"/usr/lib/$pkgname/mmio.py
cp -a __pycache__ "$pkgdir"/usr/lib/$pkgname/
install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
}

View File

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

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

@@ -3,11 +3,9 @@ Description=Stop Intel throttling
[Service]
Type=simple
ExecStart=/opt/lenovo_fix/venv/bin/python3 /opt/lenovo_fix/lenovo_fix.py
ExecStart=/usr/bin/throttled --conf /etc/throttled.conf
# Setting PYTHONUNBUFFERED is necessary to see the output of this service in the journal
Environment=PYTHONUNBUFFERED=1
StandardOutput=syslog
StandardError=syslog
[Install]
WantedBy=multi-user.target

74
throttled.spec Executable file
View File

@@ -0,0 +1,74 @@
%global _hardened_build 1
%define debug_package %{nil}
Name: throttled
Version: 0.8
Release: 2
Summary: Workaround for Intel throttling issues in Linux
License: MIT
URL: https://github.com/erpalma/throttled
Source0: https://github.com/erpalma/throttled/archive/v%{version}.tar.gz
BuildRequires: python3-devel
BuildRequires: systemd-units
Requires: python3
Requires: python3-gobject
# Requires: python3-configparser # Not available in F33, install using pip instead
Requires: systemd
Conflicts: thermald
%description
This tool was originally developed to fix Linux CPU throttling issues affecting
Lenovo T480 / T480s / X1C6.
The CPU package power limit (PL1/2) is forced to a value of 44 W (29 W on
battery) and the temperature trip point to 95 'C (85 'C on battery) by
overriding default values in MSR and MCHBAR every 5 seconds (30 on battery) to
block the Embedded Controller from resetting these values to default.
%prep
%autosetup
%build
%install
install -D lenovo_fix.py %{buildroot}/%{_bindir}/%{name}
install -D mmio.py %{buildroot}/%{python3_sitelib}/mmio.py
install -D etc/lenovo_fix.conf %{buildroot}/%{_sysconfdir}/%{name}.conf
install -D systemd/lenovo_fix.service %{buildroot}/%{_unitdir}/%{name}.service
%post
%systemd_post %{name}.service
%preun
%systemd_preun %{name}.service
%postun
%systemd_postun_with_restart %{name}.service
%files
%defattr(-,root,root,-)
%attr(755, root, root) %{_bindir}/%{name}
%attr(644, root, root) %{python3_sitelib}/mmio.py
%attr(644, root, root) %{python3_sitelib}/__pycache__/*
%config(noreplace) %attr(640, %{name}, %{name}) %{_sysconfdir}/%{name}.conf
%attr(644, root, root) %{_unitdir}/%{name}.service
%changelog
* Thu May 02 2019 Arun Babu Neelicattu <arun.neelicattu@twyla.ai> - 0.6-1
- Upgrade to 0.6
* Mon Mar 11 2019 Arun Babu Neelicattu <arun.neelicattu@gmail.com> - 0.5-4
- Add conflict for thermald
* Mon Mar 11 2019 Arun Babu Neelicattu <arun.neelicattu@gmail.com> - 0.5-3
- Fix unit file to use configuration
* Mon Mar 11 2019 Arun Babu Neelicattu <arun.neelicattu@gmail.com> - 0.5-2
- Add default configuration file
- Fix file permissions
* Mon Mar 11 2019 Arun Babu Neelicattu <arun.neelicattu@gmail.com> - 0.5-1
- Initial release of version 0.5