-
Notifications
You must be signed in to change notification settings - Fork 180
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #590 from sgruszka/intel_uncore_plugin_v2
Add intel uncore plugin
- Loading branch information
Showing
1 changed file
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
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 _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 value 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 value 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, remove): | ||
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, remove): | ||
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 |