Browse Source

Merge upstream

cryobry 1 year ago
parent
commit
7ac6c775a6
10 changed files with 91 additions and 31 deletions
  1. 1 1
      .gitignore
  2. 42 12
      README.md
  3. 2 0
      etc/lenovo_fix.conf
  4. 1 0
      install.sh
  5. 39 10
      lenovo_fix.py
  6. 0 0
      openrc/lenovo_fix
  7. 0 0
      package/PKGBUILD
  8. 3 3
      requirements.txt
  9. 2 4
      systemd/lenovo_fix.service
  10. 1 1
      throttled.spec

+ 1 - 1
.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

+ 42 - 12
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.

+ 2 - 0
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]

+ 1 - 0
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

+ 39 - 10
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:

+ 0 - 0
openrc/lenovo_fix


+ 0 - 0
package/PKGBUILD


+ 3 - 3
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

+ 2 - 4
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

+ 1 - 1
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