From 9b72d697df1a482193e6d1a949365c923ca53a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= Date: Thu, 23 Nov 2023 15:42:53 +0100 Subject: [PATCH] Add an ACPI plugin Resolves: RHEL-16966 At this point, the plugin supports setting a single sysfs attribute, platform_profile. The 3 basic ACPI platform profiles are low-power, balanced, and performance. These are mapped to the generic powersave, balanced, and *-performance TuneD profiles. --- .../ref_available-tuned-plug-ins.adoc | 24 ++++++ profiles/accelerator-performance/tuned.conf | 3 + profiles/balanced/tuned.conf | 3 + profiles/latency-performance/tuned.conf | 3 + profiles/powersave/tuned.conf | 3 + profiles/throughput-performance/tuned.conf | 3 + tuned/consts.py | 3 + tuned/plugins/plugin_acpi.py | 81 +++++++++++++++++++ 8 files changed, 123 insertions(+) create mode 100644 tuned/plugins/plugin_acpi.py diff --git a/doc/manual/modules/performance/ref_available-tuned-plug-ins.adoc b/doc/manual/modules/performance/ref_available-tuned-plug-ins.adoc index 22def92..b24f544 100644 --- a/doc/manual/modules/performance/ref_available-tuned-plug-ins.adoc +++ b/doc/manual/modules/performance/ref_available-tuned-plug-ins.adoc @@ -215,3 +215,27 @@ cmdline=isolcpus=2 ==== -- + +`acpi`:: + +Configures the ACPI driver. ++ +The only currently supported option is +[option]`platform_profile`, which sets the ACPI +platform profile sysfs attribute, +a generic power/performance preference API for other drivers. +Multiple profiles can be specified, separated by `|`. +The first available profile is selected. ++ +-- +.Selecting a platform profile +==== +---- +[acpi] +platform_profile=low-power|quiet +---- +Using this option, *TuneD* will try to set the platform profile +to `low-power`. If that fails (e.g, because the system does not +support the profile), it will try to set it to `quiet`. +==== +-- diff --git a/profiles/accelerator-performance/tuned.conf b/profiles/accelerator-performance/tuned.conf index 518831e..696a1dd 100644 --- a/profiles/accelerator-performance/tuned.conf +++ b/profiles/accelerator-performance/tuned.conf @@ -11,6 +11,9 @@ energy_perf_bias=performance min_perf_pct=100 force_latency=99 +[acpi] +platform_profile=performance + [disk] readahead=>4096 diff --git a/profiles/balanced/tuned.conf b/profiles/balanced/tuned.conf index 306ba14..1dda2f3 100644 --- a/profiles/balanced/tuned.conf +++ b/profiles/balanced/tuned.conf @@ -14,6 +14,9 @@ governor=conservative|powersave energy_perf_bias=normal energy_performance_preference=balance_performance +[acpi] +platform_profile=balanced + [audio] timeout=10 diff --git a/profiles/latency-performance/tuned.conf b/profiles/latency-performance/tuned.conf index d200b5c..1dec690 100644 --- a/profiles/latency-performance/tuned.conf +++ b/profiles/latency-performance/tuned.conf @@ -11,6 +11,9 @@ governor=performance energy_perf_bias=performance min_perf_pct=100 +[acpi] +platform_profile=performance + [sysctl] # If a workload mostly uses anonymous memory and it hits this limit, the entire # working set is buffered for I/O, and any more write buffering would require diff --git a/profiles/powersave/tuned.conf b/profiles/powersave/tuned.conf index 5e9f6a7..c593a80 100644 --- a/profiles/powersave/tuned.conf +++ b/profiles/powersave/tuned.conf @@ -10,6 +10,9 @@ governor=ondemand|powersave energy_perf_bias=powersave|power energy_performance_preference=power +[acpi] +platform_profile=low-power|quiet + [eeepc_she] [vm] diff --git a/profiles/throughput-performance/tuned.conf b/profiles/throughput-performance/tuned.conf index ced3e49..e4e832f 100644 --- a/profiles/throughput-performance/tuned.conf +++ b/profiles/throughput-performance/tuned.conf @@ -15,6 +15,9 @@ energy_perf_bias=performance min_perf_pct=100 energy_performance_preference=performance +[acpi] +platform_profile=performance + # Marvell ThunderX [vm.thunderx] type=vm diff --git a/tuned/consts.py b/tuned/consts.py index b7fb215..aacb099 100644 --- a/tuned/consts.py +++ b/tuned/consts.py @@ -66,6 +66,9 @@ SYSTEMD_CPUAFFINITY_VAR = "CPUAffinity" # irqbalance plugin configuration IRQBALANCE_SYSCONFIG_FILE = "/etc/sysconfig/irqbalance" +# acpi plugin configuration +ACPI_DIR = "/sys/firmware/acpi" + # built-in functions configuration SYSFS_CPUS_PATH = "/sys/devices/system/cpu" diff --git a/tuned/plugins/plugin_acpi.py b/tuned/plugins/plugin_acpi.py new file mode 100644 index 0000000..38eca68 --- /dev/null +++ b/tuned/plugins/plugin_acpi.py @@ -0,0 +1,81 @@ +from . import base +from .decorators import * +import os +import errno +import tuned.logs +from tuned.consts import ACPI_DIR + +log = tuned.logs.get() + + +class ACPIPlugin(base.Plugin): + """ + `acpi`:: + + Configures the ACPI driver. + + + The only currently supported option is + [option]`platform_profile`, which sets the ACPI + platform profile sysfs attribute, + a generic power/performance preference API for other drivers. + Multiple profiles can be specified, separated by `|`. + The first available profile is selected. + + + -- + .Selecting a platform profile + ==== + ---- + [acpi] + platform_profile=balanced|low-power + ---- + Using this option, *TuneD* will try to set the platform profile + to `balanced`. If that fails, it will try to set it to `low-power`. + ==== + -- + """ + def __init__(self, *args, **kwargs): + super(ACPIPlugin, self).__init__(*args, **kwargs) + + @classmethod + def _get_config_options(cls): + return {"platform_profile": None} + + def _instance_init(self, instance): + instance._has_static_tuning = True + instance._has_dynamic_tuning = False + + def _instance_cleanup(self, instance): + pass + + @classmethod + def _platform_profile_choices_path(cls): + return os.path.join(ACPI_DIR, "platform_profile_choices") + + @classmethod + def _platform_profile_path(cls): + return os.path.join(ACPI_DIR, "platform_profile") + + @command_set("platform_profile") + def _set_platform_profile(self, profiles, sim, remove): + if not os.path.isfile(self._platform_profile_path()): + log.debug("ACPI platform_profile is not supported on this system") + return None + profiles = [profile.strip() for profile in profiles.split('|')] + avail_profiles = set(self._cmd.read_file(self._platform_profile_choices_path()).split()) + for profile in profiles: + if profile in avail_profiles: + if not sim: + log.info("Setting platform_profile to '%s'" % profile) + self._cmd.write_to_file(self._platform_profile_path(), profile, \ + no_error=[errno.ENOENT] if remove else False) + return profile + log.warn("Requested platform_profile '%s' unavailable" % profile) + log.error("Failed to set platform_profile. Is the value in the profile correct?") + return None + + @command_get("platform_profile") + def _get_platform_profile(self, ignore_missing=False): + if not os.path.isfile(self._platform_profile_path()): + log.debug("ACPI platform_profile is not supported on this system") + return None + return self._cmd.read_file(self._platform_profile_path()).strip()