Add intel uncore plugin
Add simplistic intel uncore plugin to so that uncore maximum and minimum frequency can be set. For example lowering uncore maximum frequency can have significant impact on the total power consummation of SoC. Refer to the following link to get details: https://docs.kernel.org/admin-guide/pm/intel_uncore_frequency_scaling.html When system with TPMI (Topology Aware Register and PM Capsule Interface) is detected only devices configured via TPMI are used, since configuring via deprecated (package/die) interface create conflict on new systems. Plugin allow to configure frequency per individual uncore units, example profile config options can look like this: [intel_uncore_all0] # power save type=intel_uncore devices=uncore0* max_freq_khz=2000000 [intel_uncore_10] # performance type=intel_uncore devices=uncore10 min_freq_khz=4000000 [intel_uncore] # for all others save power with little performance cost max_freq_khz=4600000 For systems where maximum/minimum configured frequency is above/below the system limits, values are capped to the limit. Wrong configuration i.e. maximum frequency below minimum frequency is skipped and errors are logged. TODO: - Create matching functions in (tuned/profiles/functions) to allow to identify cpus belongs to uncore unit as well uncore TPMI unit based on power domain/package/die. - Add uncore frequency configuration to basics or specialistic profiles. Signed-off-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
This commit is contained in:
parent
95be4c0d68
commit
2055284ba0
1 changed files with 174 additions and 0 deletions
174
tuned/plugins/plugin_intel_uncore.py
Normal file
174
tuned/plugins/plugin_intel_uncore.py
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
from . import hotplug
|
||||
from .decorators import *
|
||||
import tuned.logs
|
||||
from tuned.utils.commands import commands
|
||||
|
||||
import os
|
||||
import fnmatch
|
||||
|
||||
log = tuned.logs.get()
|
||||
cmd = commands()
|
||||
|
||||
SYSFS_DIR = "/sys/devices/system/cpu/intel_uncore_frequency/"
|
||||
|
||||
IS_MIN = 0
|
||||
IS_MAX = 1
|
||||
|
||||
class IntelUncorePlugin(hotplug.Plugin):
|
||||
"""
|
||||
`intel_uncore`::
|
||||
|
||||
`max_freq_khz, min_freq_khz`:::
|
||||
Limit the maximum and minumum uncore frequency.
|
||||
====
|
||||
----
|
||||
[intel_uncore]
|
||||
max_freq_khz=4000000
|
||||
----
|
||||
Using this options *TuneD* will limit maximum frequency of all uncore units
|
||||
in the system to 4 GHz
|
||||
====
|
||||
"""
|
||||
|
||||
def _init_devices(self):
|
||||
self._devices_supported = True
|
||||
self._assigned_devices = set()
|
||||
self._free_devices = set()
|
||||
self._is_tpmi = False
|
||||
|
||||
try:
|
||||
devices = os.listdir(SYSFS_DIR)
|
||||
except OSError:
|
||||
return
|
||||
|
||||
# For new TPMI interface use only uncore devices
|
||||
tpmi_devices = fnmatch.filter(devices, 'uncore*')
|
||||
if len(tpmi_devices) > 0:
|
||||
self._is_tpmi = True # Not used at present but can be usefull in future
|
||||
devices = tpmi_devices
|
||||
|
||||
for d in devices:
|
||||
self._free_devices.add(d)
|
||||
|
||||
log.debug("devices: %s", str(self._free_devices))
|
||||
|
||||
def _instance_init(self, instance):
|
||||
instance._has_static_tuning = True
|
||||
instance._has_dynamic_tuning = False
|
||||
|
||||
def _instance_cleanup(self, instance):
|
||||
pass
|
||||
|
||||
def _device_module_name(self, device):
|
||||
return "intel_uncore_frequency"
|
||||
|
||||
def _get(self, dev_dir, file):
|
||||
sysfs_file = SYSFS_DIR + dev_dir + "/" + file
|
||||
value = cmd.read_file(sysfs_file)
|
||||
if len(value) > 0:
|
||||
return int(value)
|
||||
return None
|
||||
|
||||
def _set(self, dev_dir, file, value):
|
||||
sysfs_file = SYSFS_DIR + dev_dir + "/" + file
|
||||
if cmd.write_to_file(sysfs_file, "%u" % value):
|
||||
return value
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _get_config_options(cls):
|
||||
return {
|
||||
"max_freq_khz": None,
|
||||
"min_freq_khz": None,
|
||||
}
|
||||
|
||||
def _validate_value(self, device, min_or_max, value):
|
||||
try:
|
||||
freq_khz = int(value)
|
||||
except ValueError:
|
||||
log.error("value '%s' is not integer" % value)
|
||||
return None
|
||||
|
||||
try:
|
||||
initial_max_freq_khz = self._get(device, "initial_max_freq_khz")
|
||||
initial_min_freq_khz = self._get(device, "initial_min_freq_khz")
|
||||
max_freq_khz = self._get(device, "max_freq_khz")
|
||||
min_freq_khz = self._get(device, "min_freq_khz")
|
||||
except (OSError, IOError):
|
||||
log.error("fail to read inital uncore frequency values")
|
||||
return None
|
||||
|
||||
if min_or_max == IS_MAX:
|
||||
if freq_khz < min_freq_khz:
|
||||
log.error("%s max_freq_khz %d value below min_freq_khz %d" % (device, freq_khz, min_freq_khz))
|
||||
return None
|
||||
|
||||
if freq_khz > initial_max_freq_khz:
|
||||
log.info("%s: max_freq_khz %d above initial_max_freq_khz - capped to %d" % (device, freq_khz, initial_max_freq_khz))
|
||||
freq_khz = initial_max_freq_khz
|
||||
|
||||
elif min_or_max == IS_MIN:
|
||||
if freq_khz > max_freq_khz:
|
||||
log.error("%s: min_freq_khz %d value above max_freq_khz %d" % (device, freq_khz, max_freq_khz))
|
||||
return None
|
||||
|
||||
if freq_khz < initial_min_freq_khz:
|
||||
log.info("%s: min_freq_khz %d below initial_max_freq_khz - capped to %d" % (device, freq_khz, initial_min_freq_khz))
|
||||
freq_khz = initial_min_freq_khz
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
return freq_khz
|
||||
|
||||
@command_set("max_freq_khz", per_device = True)
|
||||
def _set_max_freq_khz(self, value, device, sim):
|
||||
max_freq_khz = self._validate_value(device, IS_MAX, value)
|
||||
if max_freq_khz is None:
|
||||
return None
|
||||
|
||||
if sim:
|
||||
return max_freq_khz
|
||||
|
||||
log.debug("%s: set max_freq_khz %d" % (device, max_freq_khz))
|
||||
return self._set(device, "max_freq_khz", max_freq_khz)
|
||||
|
||||
@command_get("max_freq_khz")
|
||||
def _get_max_freq_khz(self, device, ignore_missing=False):
|
||||
if ignore_missing and not os.path.isdir(SYSFS_DIR):
|
||||
return None
|
||||
|
||||
try:
|
||||
max_freq_khz = self._get(device, "max_freq_khz")
|
||||
except (OSError, IOError):
|
||||
log.error("fail to read uncore frequency values")
|
||||
return None
|
||||
|
||||
log.debug("%s: get max_freq_khz %d" % (device, max_freq_khz))
|
||||
return max_freq_khz
|
||||
|
||||
@command_set("min_freq_khz", per_device = True)
|
||||
def _set_min_freq_khz(self, value, device, sim):
|
||||
min_freq_khz = self._validate_value(device, IS_MIN, value)
|
||||
if min_freq_khz is None:
|
||||
return None
|
||||
|
||||
if sim:
|
||||
return min_freq_khz
|
||||
|
||||
log.debug("%s: set min_freq_khz %d" % (device, min_freq_khz))
|
||||
return self._set(device, "min_freq_khz", min_freq_khz)
|
||||
|
||||
@command_get("min_freq_khz")
|
||||
def _get_min_freq_khz(self, device, ignore_missing=False):
|
||||
if ignore_missing and not os.path.isdir(SYSFS_DIR):
|
||||
return None
|
||||
|
||||
try:
|
||||
min_freq_khz = self._get(device, "min_freq_khz")
|
||||
except (OSError, IOError):
|
||||
log.error("fail to read uncore frequency values")
|
||||
return None
|
||||
|
||||
log.debug("%s: get min_freq_khz %d" % (device, min_freq_khz))
|
||||
return min_freq_khz
|
||||
Loading…
Reference in a new issue