SRCS-$(CONFIG_RTE_LIBRTE_POWER) += power_kvm_vm.c guest_channel.c
SRCS-$(CONFIG_RTE_LIBRTE_POWER) += rte_power_empty_poll.c
SRCS-$(CONFIG_RTE_LIBRTE_POWER) += power_pstate_cpufreq.c
+SRCS-$(CONFIG_RTE_LIBRTE_POWER) += power_common.c
# install this header file
SYMLINK-$(CONFIG_RTE_LIBRTE_POWER)-include := rte_power.h rte_power_empty_poll.h
* Copyright(c) 2010-2014 Intel Corporation
*/
+#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int global_fds[RTE_MAX_LCORE] = { [0 ... RTE_MAX_LCORE-1] = -1 };
+int
+guest_channel_host_check_exists(const char *path)
+{
+ char glob_path[PATH_MAX];
+ glob_t g;
+ int ret;
+
+ /* we cannot know in advance which cores have VM channels, so glob */
+ snprintf(glob_path, PATH_MAX, "%s.*", path);
+
+ ret = glob(glob_path, GLOB_NOSORT, NULL, &g);
+ if (ret != 0) {
+ /* couldn't read anything */
+ ret = 0;
+ goto out;
+ }
+
+ /* do we have at least one match? */
+ ret = g.gl_pathc > 0;
+
+out:
+ globfree(&g);
+ return ret;
+}
+
int
guest_channel_host_connect(const char *path, unsigned int lcore_id)
{
#include <channel_commands.h>
+/**
+ * Check if any Virtio-Serial VM end-points exist in path.
+ *
+ * @param path
+ * The path to the serial device on the filesystem
+ *
+ * @return
+ * - 1 if at least one potential end-point found.
+ * - 0 if no end-points found.
+ */
+int guest_channel_host_check_exists(const char *path);
+
/**
* Connect to the Virtio-Serial VM end-point located in path. It is
* thread safe for unique lcore_ids. This function must be only called once from
sources = files('rte_power.c', 'power_acpi_cpufreq.c',
'power_kvm_vm.c', 'guest_channel.c',
'rte_power_empty_poll.c',
- 'power_pstate_cpufreq.c')
+ 'power_pstate_cpufreq.c',
+ 'power_common.c')
headers = files('rte_power.h','rte_power_empty_poll.h')
deps += ['timer']
"/sys/devices/system/cpu/cpu%u/cpufreq/scaling_available_frequencies"
#define POWER_SYSFILE_SETSPEED \
"/sys/devices/system/cpu/cpu%u/cpufreq/scaling_setspeed"
+#define POWER_ACPI_DRIVER "acpi-cpufreq"
/*
* MSR related
return -1;
}
+int
+power_acpi_cpufreq_check_supported(void)
+{
+ return cpufreq_check_scaling_driver(POWER_ACPI_DRIVER);
+}
+
int
power_acpi_cpufreq_init(unsigned int lcore_id)
{
extern "C" {
#endif
+/**
+ * Check if ACPI power management is supported.
+ *
+ * @return
+ * - 1 if supported
+ * - 0 if unsupported
+ * - -1 if error, with rte_errno indicating reason for error.
+ */
+int power_acpi_cpufreq_check_supported(void);
+
/**
* Initialize power management for a specific lcore. It will check and set the
* governor to userspace for the lcore, get the available frequencies, and
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "power_common.h"
+
+#define POWER_SYSFILE_SCALING_DRIVER \
+ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_driver"
+
+int
+cpufreq_check_scaling_driver(const char *driver_name)
+{
+ unsigned int lcore_id = 0; /* always check core 0 */
+ char fullpath[PATH_MAX];
+ char readbuf[PATH_MAX];
+ char *s;
+ FILE *f;
+
+ /*
+ * Check if scaling driver matches what we expect.
+ */
+ snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SCALING_DRIVER,
+ lcore_id);
+ f = fopen(fullpath, "r");
+
+ /* if there's no driver at all, bail out */
+ if (f == NULL)
+ return 0;
+
+ s = fgets(readbuf, sizeof(readbuf), f);
+ /* don't need it any more */
+ fclose(f);
+
+ /* if we can't read it, consider unsupported */
+ if (s == NULL)
+ return 0;
+
+ /* does the driver name match? */
+ if (strncmp(readbuf, driver_name, sizeof(readbuf)) != 0)
+ return 0;
+
+ /*
+ * We might have a situation where the driver is supported, but we don't
+ * have permissions to do frequency scaling. This error should not be
+ * handled here, so consider the system to support scaling for now.
+ */
+ return 1;
+}
#define RTE_POWER_INVALID_FREQ_INDEX (~0)
+/* check if scaling driver matches one we want */
+int cpufreq_check_scaling_driver(const char *driver);
+
#endif /* _POWER_COMMON_H_ */
static struct channel_packet pkt[RTE_MAX_LCORE];
+int
+power_kvm_vm_check_supported(void)
+{
+ return guest_channel_host_check_exists(FD_PATH);
+}
int
power_kvm_vm_init(unsigned int lcore_id)
extern "C" {
#endif
+/**
+ * Check if KVM power management is supported.
+ *
+ * @return
+ * - 1 if supported
+ * - 0 if unsupported
+ * - -1 if error, with rte_errno indicating reason for error.
+ */
+int power_kvm_vm_check_supported(void);
+
/**
* Initialize power management for a specific lcore.
*
"/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_min_freq"
#define POWER_SYSFILE_BASE_FREQ \
"/sys/devices/system/cpu/cpu%u/cpufreq/base_frequency"
+#define POWER_PSTATE_DRIVER "intel_pstate"
#define POWER_MSR_PATH "/dev/cpu/%u/msr"
/*
return ret;
}
+int
+power_pstate_cpufreq_check_supported(void)
+{
+ return cpufreq_check_scaling_driver(POWER_PSTATE_DRIVER);
+}
+
int
power_pstate_cpufreq_init(unsigned int lcore_id)
{
extern "C" {
#endif
+/**
+ * Check if pstate power management is supported.
+ *
+ * @return
+ * - 1 if supported
+ * - 0 if unsupported
+ * - -1 if error, with rte_errno indicating reason for error.
+ */
+int power_pstate_cpufreq_check_supported(void);
+
/**
* Initialize power management for a specific lcore. It will check and set the
* governor to performance for the lcore, get the available frequencies, and
* Copyright(c) 2010-2014 Intel Corporation
*/
+#include <rte_errno.h>
#include <rte_spinlock.h>
#include "rte_power.h"
rte_power_get_capabilities = NULL;
}
+int
+rte_power_check_env_supported(enum power_management_env env)
+{
+ switch (env) {
+ case PM_ENV_ACPI_CPUFREQ:
+ return power_acpi_cpufreq_check_supported();
+ case PM_ENV_PSTATE_CPUFREQ:
+ return power_pstate_cpufreq_check_supported();
+ case PM_ENV_KVM_VM:
+ return power_kvm_vm_check_supported();
+ default:
+ rte_errno = EINVAL;
+ return -1;
+ }
+}
+
int
rte_power_set_env(enum power_management_env env)
{
enum power_management_env {PM_ENV_NOT_SET, PM_ENV_ACPI_CPUFREQ, PM_ENV_KVM_VM,
PM_ENV_PSTATE_CPUFREQ};
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Check if a specific power management environment type is supported on a
+ * currently running system.
+ *
+ * @param env
+ * The environment type to check support for.
+ *
+ * @return
+ * - 1 if supported
+ * - 0 if unsupported
+ * - -1 if error, with rte_errno indicating reason for error.
+ */
+__rte_experimental
+int rte_power_check_env_supported(enum power_management_env env);
+
/**
* Set the default power management implementation. If this is not called prior
* to rte_power_init(), then auto-detect of the environment will take place.
global:
rte_empty_poll_detection;
+ rte_power_check_env_supported;
rte_power_empty_poll_stat_fetch;
rte_power_empty_poll_stat_free;
rte_power_empty_poll_stat_init;