Browse Source

Merge upstream

cryobry 4 years 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
 #  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

+ 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
 ### 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
-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/).
 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
-sudo ./lenovo-throttling-fix/install.sh
+git clone https://github.com/erpalma/throttled.git
+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
-sudo ./lenovo-throttling-fix/install.sh
+git clone https://github.com/erpalma/throttled.git
+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 - 0
etc/lenovo_fix.conf

@@ -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]

+ 1 - 0
install.sh

@@ -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

+ 39 - 10
lenovo_fix.py

@@ -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
-        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():
 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 - 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]
 [Unit]
-Description=Stop Intel throttling
+Description=Stop Intel throttling 
 
 
 [Service]
 [Service]
 Type=simple
 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
 # 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

+ 1 - 1
throttled.spec

@@ -2,7 +2,7 @@
 %define debug_package %{nil}
 %define debug_package %{nil}
 
 
 Name:     throttled
 Name:     throttled
-Version:  0.7
+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