From 7ac6c775a6d61b574a8a0ba6685300a95fc8482d Mon Sep 17 00:00:00 2001 From: cryobry <38270216+cryobry@users.noreply.github.com> Date: Mon, 9 Nov 2020 10:48:40 -0500 Subject: [PATCH] Merge upstream --- .gitignore | 2 +- README.md | 54 +++++++++++++++++++++++++++++--------- etc/lenovo_fix.conf | 2 ++ install.sh | 1 + lenovo_fix.py | 49 +++++++++++++++++++++++++++------- openrc/lenovo_fix | 0 package/PKGBUILD | 0 requirements.txt | 6 ++--- systemd/lenovo_fix.service | 6 ++--- throttled.spec | 2 +- 10 files changed, 91 insertions(+), 31 deletions(-) mode change 100644 => 100755 etc/lenovo_fix.conf mode change 100644 => 100755 openrc/lenovo_fix mode change 100644 => 100755 package/PKGBUILD mode change 100644 => 100755 systemd/lenovo_fix.service mode change 100644 => 100755 throttled.spec diff --git a/.gitignore b/.gitignore index ff135c4..7bbc71c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,7 @@ wheels/ # 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. *.manifest -#*.spec +*.spec # Installer logs pip-log.txt diff --git a/README.md b/README.md index 4d5a718..a2784c8 100644 --- a/README.md +++ b/README.md @@ -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 @@ -63,8 +72,8 @@ 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/). @@ -90,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. @@ -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. ``` 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 @@ -112,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`. @@ -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 -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 @@ -154,7 +171,7 @@ 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 @@ -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 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. diff --git a/etc/lenovo_fix.conf b/etc/lenovo_fix.conf old mode 100644 new mode 100755 index 9082579..6821fa0 --- a/etc/lenovo_fix.conf +++ b/etc/lenovo_fix.conf @@ -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] diff --git a/install.sh b/install.sh index 871d903..dccd8ec 100755 --- a/install.sh +++ b/install.sh @@ -39,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 diff --git a/lenovo_fix.py b/lenovo_fix.py index 6b2a896..abab16c 100755 --- a/lenovo_fix.py +++ b/lenovo_fix.py @@ -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,7 +78,7 @@ supported_cpus = { 'Kaby Lake (R)': (0x8E, 0x9E), 'Coffee Lake': (0x9E,), 'Cannon Lake': (0x66,), - 'Comet Lake': (0xA6,), + 'Comet Lake': (0xA5, 0xA6), } @@ -517,16 +518,17 @@ 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(): @@ -541,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) @@ -550,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: @@ -558,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' @@ -628,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: @@ -791,14 +819,15 @@ def main(): 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: diff --git a/openrc/lenovo_fix b/openrc/lenovo_fix old mode 100644 new mode 100755 diff --git a/package/PKGBUILD b/package/PKGBUILD old mode 100644 new mode 100755 diff --git a/requirements.txt b/requirements.txt index 045510f..50f17d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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 diff --git a/systemd/lenovo_fix.service b/systemd/lenovo_fix.service old mode 100644 new mode 100755 index 5ec0fdb..28b8a47 --- a/systemd/lenovo_fix.service +++ b/systemd/lenovo_fix.service @@ -1,13 +1,11 @@ [Unit] -Description=Stop Intel throttling +Description=Stop Intel throttling [Service] Type=simple -ExecStart=/usr/bin/throttled --conf /etc/throttled.conf +ExecStart=/opt/lenovo_fix/venv/bin/python3 /opt/lenovo_fix/lenovo_fix.py # 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 diff --git a/throttled.spec b/throttled.spec old mode 100644 new mode 100755 index 3b2078f..adedbbb --- a/throttled.spec +++ b/throttled.spec @@ -2,7 +2,7 @@ %define debug_package %{nil} Name: throttled -Version: 0.7 +Version: 0.8 Release: 2 Summary: Workaround for Intel throttling issues in Linux License: MIT