|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] xen/pmstat: introduce CONFIG_PM_OP
commit a16f2b3e066903b59bc05d02d49ca64f84c88640
Author: Penny Zheng <Penny.Zheng@xxxxxxx>
AuthorDate: Wed Jul 9 10:54:58 2025 +0200
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Jul 9 10:54:58 2025 +0200
xen/pmstat: introduce CONFIG_PM_OP
We move the following functions into a new file drivers/acpi/pm-op.c, as
they are all more fitting in performance controling and only called by
do_pm_op():
- get_cpufreq_para()
- set_cpufreq_para()
- set_cpufreq_gov()
- set_cpufreq_cppc()
- cpufreq_driver_getavg()
- cpufreq_update_turbo()
- cpufreq_get_turbo_status()
We introduce a new Kconfig CONFIG_PM_OP to wrap the new file.
Also, although the following helpers are only called by do_pm_op(), they
have
dependency on local variable, we wrap them with CONFIG_PM_OP in place:
- write_userspace_scaling_setspeed()
- write_ondemand_sampling_rate()
- write_ondemand_up_threshold()
- get_cpufreq_ondemand_para()
- cpufreq_driver.update()
- get_hwp_para()
Various style corrections shall be applied at the same time while moving
these
functions, including:
- add extra space before and after bracket of if() and switch()
- fix indentation
- drop all the unnecessary inner figure braces
We shall also provide "# CONFIG_PM_OP is not set" in preset configs for
PV shim on x86.
Signed-off-by: Penny Zheng <Penny.Zheng@xxxxxxx>
Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
---
xen/arch/x86/acpi/cpufreq/hwp.c | 6 +
xen/arch/x86/acpi/cpufreq/powernow.c | 4 +
xen/arch/x86/configs/pvshim_defconfig | 1 +
xen/common/Kconfig | 8 +
xen/common/sysctl.c | 2 +
xen/drivers/acpi/Makefile | 1 +
xen/drivers/acpi/pm-op.c | 395 +++++++++++++++++++++++++++
xen/drivers/acpi/pmstat.c | 355 ------------------------
xen/drivers/cpufreq/cpufreq_misc_governors.c | 2 +
xen/drivers/cpufreq/cpufreq_ondemand.c | 2 +
xen/drivers/cpufreq/utility.c | 41 ---
xen/include/acpi/cpufreq/cpufreq.h | 3 -
12 files changed, 421 insertions(+), 399 deletions(-)
diff --git a/xen/arch/x86/acpi/cpufreq/hwp.c b/xen/arch/x86/acpi/cpufreq/hwp.c
index d5fa3d47ca..e4c09244ab 100644
--- a/xen/arch/x86/acpi/cpufreq/hwp.c
+++ b/xen/arch/x86/acpi/cpufreq/hwp.c
@@ -466,6 +466,7 @@ static int cf_check hwp_cpufreq_cpu_exit(struct
cpufreq_policy *policy)
return 0;
}
+#ifdef CONFIG_PM_OP
/*
* The SDM reads like turbo should be disabled with MSR_IA32_PERF_CTL and
* PERF_CTL_TURBO_DISENGAGE, but that does not seem to actually work, at least
@@ -508,6 +509,7 @@ static int cf_check hwp_cpufreq_update(unsigned int cpu,
struct cpufreq_policy *
return per_cpu(hwp_drv_data, cpu)->ret;
}
+#endif /* CONFIG_PM_OP */
static const struct cpufreq_driver __initconst_cf_clobber
hwp_cpufreq_driver = {
@@ -516,9 +518,12 @@ hwp_cpufreq_driver = {
.target = hwp_cpufreq_target,
.init = hwp_cpufreq_cpu_init,
.exit = hwp_cpufreq_cpu_exit,
+#ifdef CONFIG_PM_OP
.update = hwp_cpufreq_update,
+#endif
};
+#ifdef CONFIG_PM_OP
int get_hwp_para(unsigned int cpu,
struct xen_cppc_para *cppc_para)
{
@@ -639,6 +644,7 @@ int set_hwp_para(struct cpufreq_policy *policy,
return hwp_cpufreq_target(policy, 0, 0);
}
+#endif /* CONFIG_PM_OP */
int __init hwp_register_driver(void)
{
diff --git a/xen/arch/x86/acpi/cpufreq/powernow.c
b/xen/arch/x86/acpi/cpufreq/powernow.c
index 69364e1855..12fca45b45 100644
--- a/xen/arch/x86/acpi/cpufreq/powernow.c
+++ b/xen/arch/x86/acpi/cpufreq/powernow.c
@@ -49,6 +49,7 @@ static void cf_check transition_pstate(void *pstate)
wrmsrl(MSR_PSTATE_CTRL, *(unsigned int *)pstate);
}
+#ifdef CONFIG_PM_OP
static void cf_check update_cpb(void *data)
{
struct cpufreq_policy *policy = data;
@@ -77,6 +78,7 @@ static int cf_check powernow_cpufreq_update(
return 0;
}
+#endif /* CONFIG_PM_OP */
static int cf_check powernow_cpufreq_target(
struct cpufreq_policy *policy,
@@ -324,7 +326,9 @@ powernow_cpufreq_driver = {
.target = powernow_cpufreq_target,
.init = powernow_cpufreq_cpu_init,
.exit = powernow_cpufreq_cpu_exit,
+#ifdef CONFIG_PM_OP
.update = powernow_cpufreq_update
+#endif
};
unsigned int __init powernow_register_driver(void)
diff --git a/xen/arch/x86/configs/pvshim_defconfig
b/xen/arch/x86/configs/pvshim_defconfig
index 2ad27f898e..bacd04c963 100644
--- a/xen/arch/x86/configs/pvshim_defconfig
+++ b/xen/arch/x86/configs/pvshim_defconfig
@@ -26,3 +26,4 @@ CONFIG_EXPERT=y
# CONFIG_INTEL_IOMMU is not set
# CONFIG_DEBUG is not set
# CONFIG_GDBSX is not set
+# CONFIG_PM_OP is not set
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 6d784da839..ed907de268 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -620,4 +620,12 @@ config SYSCTL
endmenu
+config PM_OP
+ bool "Enable Performance Management Operation"
+ depends on ACPI && HAS_CPUFREQ && SYSCTL
+ default y
+ help
+ This option shall enable userspace performance management control
+ to do power/performance analyzing and tuning.
+
endmenu
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index c2d99ae12e..daf57fbe56 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -174,7 +174,9 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t)
u_sysctl)
case XEN_SYSCTL_get_pmstat:
ret = do_get_pm_info(&op->u.get_pmstat);
break;
+#endif
+#ifdef CONFIG_PM_OP
case XEN_SYSCTL_pm_op:
ret = do_pm_op(&op->u.pm_op);
if ( ret == -EAGAIN )
diff --git a/xen/drivers/acpi/Makefile b/xen/drivers/acpi/Makefile
index 2fc5230253..1d811a51a7 100644
--- a/xen/drivers/acpi/Makefile
+++ b/xen/drivers/acpi/Makefile
@@ -6,6 +6,7 @@ obj-bin-y += tables.init.o
obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-y += osl.o
obj-$(CONFIG_HAS_CPUFREQ) += pmstat.o
+obj-$(CONFIG_PM_OP) += pm-op.o
obj-$(CONFIG_X86) += hwregs.o
obj-$(CONFIG_X86) += reboot.o
diff --git a/xen/drivers/acpi/pm-op.c b/xen/drivers/acpi/pm-op.c
new file mode 100644
index 0000000000..a1f3c4193f
--- /dev/null
+++ b/xen/drivers/acpi/pm-op.c
@@ -0,0 +1,395 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <xen/acpi.h>
+#include <xen/domain.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+
+#include <acpi/cpufreq/cpufreq.h>
+#include <public/platform.h>
+#include <public/sysctl.h>
+
+/*
+ * 1. Get PM parameter
+ * 2. Provide user PM control
+ */
+static int cpufreq_update_turbo(unsigned int cpu, int new_state)
+{
+ struct cpufreq_policy *policy;
+ int curr_state;
+ int ret = 0;
+
+ if ( new_state != CPUFREQ_TURBO_ENABLED &&
+ new_state != CPUFREQ_TURBO_DISABLED )
+ return -EINVAL;
+
+ policy = per_cpu(cpufreq_cpu_policy, cpu);
+ if ( !policy )
+ return -EACCES;
+
+ if ( policy->turbo == CPUFREQ_TURBO_UNSUPPORTED )
+ return -EOPNOTSUPP;
+
+ curr_state = policy->turbo;
+ if ( curr_state == new_state )
+ return 0;
+
+ policy->turbo = new_state;
+ if ( cpufreq_driver.update )
+ {
+ ret = alternative_call(cpufreq_driver.update, cpu, policy);
+ if ( ret )
+ policy->turbo = curr_state;
+ }
+
+ return ret;
+}
+
+static int cpufreq_get_turbo_status(unsigned int cpu)
+{
+ struct cpufreq_policy *policy;
+
+ policy = per_cpu(cpufreq_cpu_policy, cpu);
+ return policy && policy->turbo == CPUFREQ_TURBO_ENABLED;
+}
+
+static int read_scaling_available_governors(char *scaling_available_governors,
+ unsigned int size)
+{
+ unsigned int i = 0;
+ struct cpufreq_governor *t;
+
+ if ( !scaling_available_governors )
+ return -EINVAL;
+
+ list_for_each_entry(t, &cpufreq_governor_list, governor_list)
+ {
+ i += scnprintf(&scaling_available_governors[i],
+ CPUFREQ_NAME_LEN, "%s ", t->name);
+ if ( i > size )
+ return -EINVAL;
+ }
+ scaling_available_governors[i-1] = '\0';
+
+ return 0;
+}
+
+static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
+{
+ uint32_t ret = 0;
+ const struct processor_pminfo *pmpt;
+ struct cpufreq_policy *policy;
+ uint32_t gov_num = 0;
+ uint32_t *data;
+ char *scaling_available_governors;
+ struct list_head *pos;
+ unsigned int cpu, i = 0;
+
+ pmpt = processor_pminfo[op->cpuid];
+ policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
+
+ if ( !pmpt || !pmpt->perf.states ||
+ !policy || !policy->governor )
+ return -EINVAL;
+
+ list_for_each(pos, &cpufreq_governor_list)
+ gov_num++;
+
+ if ( (op->u.get_para.cpu_num != cpumask_weight(policy->cpus)) ||
+ (op->u.get_para.freq_num != pmpt->perf.state_count) ||
+ (op->u.get_para.gov_num != gov_num) )
+ {
+ op->u.get_para.cpu_num = cpumask_weight(policy->cpus);
+ op->u.get_para.freq_num = pmpt->perf.state_count;
+ op->u.get_para.gov_num = gov_num;
+ return -EAGAIN;
+ }
+
+ if ( !(data = xzalloc_array(uint32_t,
+ max(op->u.get_para.cpu_num,
+ op->u.get_para.freq_num))) )
+ return -ENOMEM;
+
+ for_each_cpu(cpu, policy->cpus)
+ data[i++] = cpu;
+ ret = copy_to_guest(op->u.get_para.affected_cpus,
+ data, op->u.get_para.cpu_num);
+
+ for ( i = 0; i < op->u.get_para.freq_num; i++ )
+ data[i] = pmpt->perf.states[i].core_frequency * 1000;
+ ret += copy_to_guest(op->u.get_para.scaling_available_frequencies,
+ data, op->u.get_para.freq_num);
+
+ xfree(data);
+ if ( ret )
+ return -EFAULT;
+
+ op->u.get_para.cpuinfo_cur_freq =
+ cpufreq_driver.get ? alternative_call(cpufreq_driver.get, op->cpuid)
+ : policy->cur;
+ op->u.get_para.cpuinfo_max_freq = policy->cpuinfo.max_freq;
+ op->u.get_para.cpuinfo_min_freq = policy->cpuinfo.min_freq;
+ op->u.get_para.turbo_enabled = cpufreq_get_turbo_status(op->cpuid);
+
+ if ( cpufreq_driver.name[0] )
+ strlcpy(op->u.get_para.scaling_driver,
+ cpufreq_driver.name, CPUFREQ_NAME_LEN);
+ else
+ strlcpy(op->u.get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN);
+
+ if ( hwp_active() )
+ ret = get_hwp_para(policy->cpu, &op->u.get_para.u.cppc_para);
+ else
+ {
+ if ( !(scaling_available_governors =
+ xzalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) )
+ return -ENOMEM;
+ if ( (ret = read_scaling_available_governors(
+ scaling_available_governors,
+ (gov_num * CPUFREQ_NAME_LEN *
+ sizeof(*scaling_available_governors)))) )
+ {
+ xfree(scaling_available_governors);
+ return ret;
+ }
+ ret = copy_to_guest(op->u.get_para.scaling_available_governors,
+ scaling_available_governors,
+ gov_num * CPUFREQ_NAME_LEN);
+ xfree(scaling_available_governors);
+ if ( ret )
+ return -EFAULT;
+
+ op->u.get_para.u.s.scaling_cur_freq = policy->cur;
+ op->u.get_para.u.s.scaling_max_freq = policy->max;
+ op->u.get_para.u.s.scaling_min_freq = policy->min;
+
+ if ( policy->governor->name[0] )
+ strlcpy(op->u.get_para.u.s.scaling_governor,
+ policy->governor->name, CPUFREQ_NAME_LEN);
+ else
+ strlcpy(op->u.get_para.u.s.scaling_governor, "Unknown",
+ CPUFREQ_NAME_LEN);
+
+ /* governor specific para */
+ if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
+ "userspace", CPUFREQ_NAME_LEN) )
+ op->u.get_para.u.s.u.userspace.scaling_setspeed = policy->cur;
+
+ if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
+ "ondemand", CPUFREQ_NAME_LEN) )
+ ret = get_cpufreq_ondemand_para(
+ &op->u.get_para.u.s.u.ondemand.sampling_rate_max,
+ &op->u.get_para.u.s.u.ondemand.sampling_rate_min,
+ &op->u.get_para.u.s.u.ondemand.sampling_rate,
+ &op->u.get_para.u.s.u.ondemand.up_threshold);
+ }
+
+ return ret;
+}
+
+static int set_cpufreq_gov(struct xen_sysctl_pm_op *op)
+{
+ struct cpufreq_policy new_policy, *old_policy;
+
+ old_policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
+ if ( !old_policy )
+ return -EINVAL;
+
+ memcpy(&new_policy, old_policy, sizeof(struct cpufreq_policy));
+
+ new_policy.governor = __find_governor(op->u.set_gov.scaling_governor);
+ if ( new_policy.governor == NULL )
+ return -EINVAL;
+
+ return __cpufreq_set_policy(old_policy, &new_policy);
+}
+
+static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
+{
+ int ret = 0;
+ struct cpufreq_policy *policy;
+
+ policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
+
+ if ( !policy || !policy->governor )
+ return -EINVAL;
+
+ if ( hwp_active() )
+ return -EOPNOTSUPP;
+
+ switch( op->u.set_para.ctrl_type )
+ {
+ case SCALING_MAX_FREQ:
+ {
+ struct cpufreq_policy new_policy;
+
+ memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+ new_policy.max = op->u.set_para.ctrl_value;
+ ret = __cpufreq_set_policy(policy, &new_policy);
+
+ break;
+ }
+
+ case SCALING_MIN_FREQ:
+ {
+ struct cpufreq_policy new_policy;
+
+ memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+ new_policy.min = op->u.set_para.ctrl_value;
+ ret = __cpufreq_set_policy(policy, &new_policy);
+
+ break;
+ }
+
+ case SCALING_SETSPEED:
+ {
+ unsigned int freq =op->u.set_para.ctrl_value;
+
+ if ( !strncasecmp(policy->governor->name,
+ "userspace", CPUFREQ_NAME_LEN) )
+ ret = write_userspace_scaling_setspeed(op->cpuid, freq);
+ else
+ ret = -EINVAL;
+
+ break;
+ }
+
+ case SAMPLING_RATE:
+ {
+ unsigned int sampling_rate = op->u.set_para.ctrl_value;
+
+ if ( !strncasecmp(policy->governor->name,
+ "ondemand", CPUFREQ_NAME_LEN) )
+ ret = write_ondemand_sampling_rate(sampling_rate);
+ else
+ ret = -EINVAL;
+
+ break;
+ }
+
+ case UP_THRESHOLD:
+ {
+ unsigned int up_threshold = op->u.set_para.ctrl_value;
+
+ if ( !strncasecmp(policy->governor->name,
+ "ondemand", CPUFREQ_NAME_LEN) )
+ ret = write_ondemand_up_threshold(up_threshold);
+ else
+ ret = -EINVAL;
+
+ break;
+ }
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int set_cpufreq_cppc(struct xen_sysctl_pm_op *op)
+{
+ struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
+
+ if ( !policy || !policy->governor )
+ return -ENOENT;
+
+ if ( !hwp_active() )
+ return -EOPNOTSUPP;
+
+ return set_hwp_para(policy, &op->u.set_cppc);
+}
+
+int do_pm_op(struct xen_sysctl_pm_op *op)
+{
+ int ret = 0;
+ const struct processor_pminfo *pmpt;
+
+ switch ( op->cmd )
+ {
+ case XEN_SYSCTL_pm_op_set_sched_opt_smt:
+ {
+ uint32_t saved_value = sched_smt_power_savings;
+
+ if ( op->cpuid != 0 )
+ return -EINVAL;
+ sched_smt_power_savings = !!op->u.set_sched_opt_smt;
+ op->u.set_sched_opt_smt = saved_value;
+ return 0;
+ }
+
+ case XEN_SYSCTL_pm_op_get_max_cstate:
+ BUILD_BUG_ON(XEN_SYSCTL_CX_UNLIMITED != UINT_MAX);
+ if ( op->cpuid == 0 )
+ op->u.get_max_cstate = acpi_get_cstate_limit();
+ else if ( op->cpuid == 1 )
+ op->u.get_max_cstate = acpi_get_csubstate_limit();
+ else
+ ret = -EINVAL;
+ return ret;
+
+ case XEN_SYSCTL_pm_op_set_max_cstate:
+ if ( op->cpuid == 0 )
+ acpi_set_cstate_limit(op->u.set_max_cstate);
+ else if ( op->cpuid == 1 )
+ acpi_set_csubstate_limit(op->u.set_max_cstate);
+ else
+ ret = -EINVAL;
+ return ret;
+ }
+
+ if ( op->cpuid >= nr_cpu_ids || !cpu_online(op->cpuid) )
+ return -EINVAL;
+ pmpt = processor_pminfo[op->cpuid];
+
+ switch ( op->cmd & PM_PARA_CATEGORY_MASK )
+ {
+ case CPUFREQ_PARA:
+ if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) )
+ return -ENODEV;
+ if ( !pmpt || !(pmpt->init & XEN_PX_INIT) )
+ return -EINVAL;
+ break;
+ }
+
+ switch ( op->cmd )
+ {
+ case GET_CPUFREQ_PARA:
+ ret = get_cpufreq_para(op);
+ break;
+
+ case SET_CPUFREQ_GOV:
+ ret = set_cpufreq_gov(op);
+ break;
+
+ case SET_CPUFREQ_PARA:
+ ret = set_cpufreq_para(op);
+ break;
+
+ case SET_CPUFREQ_CPPC:
+ ret = set_cpufreq_cppc(op);
+ break;
+
+ case GET_CPUFREQ_AVGFREQ:
+ op->u.get_avgfreq = cpufreq_driver_getavg(op->cpuid, USR_GETAVG);
+ break;
+
+ case XEN_SYSCTL_pm_op_enable_turbo:
+ ret = cpufreq_update_turbo(op->cpuid, CPUFREQ_TURBO_ENABLED);
+ break;
+
+ case XEN_SYSCTL_pm_op_disable_turbo:
+ ret = cpufreq_update_turbo(op->cpuid, CPUFREQ_TURBO_DISABLED);
+ break;
+
+ default:
+ printk("not defined sub-hypercall @ do_pm_op\n");
+ ret = -ENOSYS;
+ break;
+ }
+
+ return ret;
+}
diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c
index e276d55c97..da7a1f81e1 100644
--- a/xen/drivers/acpi/pmstat.c
+++ b/xen/drivers/acpi/pmstat.c
@@ -337,358 +337,3 @@ int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
return ret;
}
-
-/*
- * 1. Get PM parameter
- * 2. Provide user PM control
- */
-static int read_scaling_available_governors(char *scaling_available_governors,
- unsigned int size)
-{
- unsigned int i = 0;
- struct cpufreq_governor *t;
-
- if ( !scaling_available_governors )
- return -EINVAL;
-
- list_for_each_entry(t, &cpufreq_governor_list, governor_list)
- {
- i += scnprintf(&scaling_available_governors[i],
- CPUFREQ_NAME_LEN, "%s ", t->name);
- if ( i > size )
- return -EINVAL;
- }
- scaling_available_governors[i-1] = '\0';
-
- return 0;
-}
-
-static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
-{
- uint32_t ret = 0;
- const struct processor_pminfo *pmpt;
- struct cpufreq_policy *policy;
- uint32_t gov_num = 0;
- uint32_t *data;
- char *scaling_available_governors;
- struct list_head *pos;
- unsigned int cpu, i = 0;
-
- pmpt = processor_pminfo[op->cpuid];
- policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
-
- if ( !pmpt || !pmpt->perf.states ||
- !policy || !policy->governor )
- return -EINVAL;
-
- list_for_each(pos, &cpufreq_governor_list)
- gov_num++;
-
- if ( (op->u.get_para.cpu_num != cpumask_weight(policy->cpus)) ||
- (op->u.get_para.freq_num != pmpt->perf.state_count) ||
- (op->u.get_para.gov_num != gov_num) )
- {
- op->u.get_para.cpu_num = cpumask_weight(policy->cpus);
- op->u.get_para.freq_num = pmpt->perf.state_count;
- op->u.get_para.gov_num = gov_num;
- return -EAGAIN;
- }
-
- if ( !(data = xzalloc_array(uint32_t,
- max(op->u.get_para.cpu_num,
- op->u.get_para.freq_num))) )
- return -ENOMEM;
-
- for_each_cpu(cpu, policy->cpus)
- data[i++] = cpu;
- ret = copy_to_guest(op->u.get_para.affected_cpus,
- data, op->u.get_para.cpu_num);
-
- for ( i = 0; i < op->u.get_para.freq_num; i++ )
- data[i] = pmpt->perf.states[i].core_frequency * 1000;
- ret += copy_to_guest(op->u.get_para.scaling_available_frequencies,
- data, op->u.get_para.freq_num);
-
- xfree(data);
- if ( ret )
- return -EFAULT;
-
- op->u.get_para.cpuinfo_cur_freq =
- cpufreq_driver.get ? alternative_call(cpufreq_driver.get, op->cpuid)
- : policy->cur;
- op->u.get_para.cpuinfo_max_freq = policy->cpuinfo.max_freq;
- op->u.get_para.cpuinfo_min_freq = policy->cpuinfo.min_freq;
- op->u.get_para.turbo_enabled = cpufreq_get_turbo_status(op->cpuid);
-
- if ( cpufreq_driver.name[0] )
- strlcpy(op->u.get_para.scaling_driver,
- cpufreq_driver.name, CPUFREQ_NAME_LEN);
- else
- strlcpy(op->u.get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN);
-
- if ( hwp_active() )
- ret = get_hwp_para(policy->cpu, &op->u.get_para.u.cppc_para);
- else
- {
- if ( !(scaling_available_governors =
- xzalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) )
- return -ENOMEM;
- if ( (ret = read_scaling_available_governors(
- scaling_available_governors,
- (gov_num * CPUFREQ_NAME_LEN *
- sizeof(*scaling_available_governors)))) )
- {
- xfree(scaling_available_governors);
- return ret;
- }
- ret = copy_to_guest(op->u.get_para.scaling_available_governors,
- scaling_available_governors,
- gov_num * CPUFREQ_NAME_LEN);
- xfree(scaling_available_governors);
- if ( ret )
- return -EFAULT;
-
- op->u.get_para.u.s.scaling_cur_freq = policy->cur;
- op->u.get_para.u.s.scaling_max_freq = policy->max;
- op->u.get_para.u.s.scaling_min_freq = policy->min;
-
- if ( policy->governor->name[0] )
- strlcpy(op->u.get_para.u.s.scaling_governor,
- policy->governor->name, CPUFREQ_NAME_LEN);
- else
- strlcpy(op->u.get_para.u.s.scaling_governor, "Unknown",
- CPUFREQ_NAME_LEN);
-
- /* governor specific para */
- if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
- "userspace", CPUFREQ_NAME_LEN) )
- op->u.get_para.u.s.u.userspace.scaling_setspeed = policy->cur;
-
- if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
- "ondemand", CPUFREQ_NAME_LEN) )
- ret = get_cpufreq_ondemand_para(
- &op->u.get_para.u.s.u.ondemand.sampling_rate_max,
- &op->u.get_para.u.s.u.ondemand.sampling_rate_min,
- &op->u.get_para.u.s.u.ondemand.sampling_rate,
- &op->u.get_para.u.s.u.ondemand.up_threshold);
- }
-
- return ret;
-}
-
-static int set_cpufreq_gov(struct xen_sysctl_pm_op *op)
-{
- struct cpufreq_policy new_policy, *old_policy;
-
- old_policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
- if ( !old_policy )
- return -EINVAL;
-
- memcpy(&new_policy, old_policy, sizeof(struct cpufreq_policy));
-
- new_policy.governor = __find_governor(op->u.set_gov.scaling_governor);
- if (new_policy.governor == NULL)
- return -EINVAL;
-
- return __cpufreq_set_policy(old_policy, &new_policy);
-}
-
-static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
-{
- int ret = 0;
- struct cpufreq_policy *policy;
-
- policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
-
- if ( !policy || !policy->governor )
- return -EINVAL;
-
- if ( hwp_active() )
- return -EOPNOTSUPP;
-
- switch(op->u.set_para.ctrl_type)
- {
- case SCALING_MAX_FREQ:
- {
- struct cpufreq_policy new_policy;
-
- memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
- new_policy.max = op->u.set_para.ctrl_value;
- ret = __cpufreq_set_policy(policy, &new_policy);
-
- break;
- }
-
- case SCALING_MIN_FREQ:
- {
- struct cpufreq_policy new_policy;
-
- memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
- new_policy.min = op->u.set_para.ctrl_value;
- ret = __cpufreq_set_policy(policy, &new_policy);
-
- break;
- }
-
- case SCALING_SETSPEED:
- {
- unsigned int freq =op->u.set_para.ctrl_value;
-
- if ( !strncasecmp(policy->governor->name,
- "userspace", CPUFREQ_NAME_LEN) )
- ret = write_userspace_scaling_setspeed(op->cpuid, freq);
- else
- ret = -EINVAL;
-
- break;
- }
-
- case SAMPLING_RATE:
- {
- unsigned int sampling_rate = op->u.set_para.ctrl_value;
-
- if ( !strncasecmp(policy->governor->name,
- "ondemand", CPUFREQ_NAME_LEN) )
- ret = write_ondemand_sampling_rate(sampling_rate);
- else
- ret = -EINVAL;
-
- break;
- }
-
- case UP_THRESHOLD:
- {
- unsigned int up_threshold = op->u.set_para.ctrl_value;
-
- if ( !strncasecmp(policy->governor->name,
- "ondemand", CPUFREQ_NAME_LEN) )
- ret = write_ondemand_up_threshold(up_threshold);
- else
- ret = -EINVAL;
-
- break;
- }
-
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static int set_cpufreq_cppc(struct xen_sysctl_pm_op *op)
-{
- struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
-
- if ( !policy || !policy->governor )
- return -ENOENT;
-
- if ( !hwp_active() )
- return -EOPNOTSUPP;
-
- return set_hwp_para(policy, &op->u.set_cppc);
-}
-
-int do_pm_op(struct xen_sysctl_pm_op *op)
-{
- int ret = 0;
- const struct processor_pminfo *pmpt;
-
- switch ( op->cmd )
- {
- case XEN_SYSCTL_pm_op_set_sched_opt_smt:
- {
- uint32_t saved_value = sched_smt_power_savings;
-
- if ( op->cpuid != 0 )
- return -EINVAL;
- sched_smt_power_savings = !!op->u.set_sched_opt_smt;
- op->u.set_sched_opt_smt = saved_value;
- return 0;
- }
-
- case XEN_SYSCTL_pm_op_get_max_cstate:
- BUILD_BUG_ON(XEN_SYSCTL_CX_UNLIMITED != UINT_MAX);
- if ( op->cpuid == 0 )
- op->u.get_max_cstate = acpi_get_cstate_limit();
- else if ( op->cpuid == 1 )
- op->u.get_max_cstate = acpi_get_csubstate_limit();
- else
- ret = -EINVAL;
- return ret;
-
- case XEN_SYSCTL_pm_op_set_max_cstate:
- if ( op->cpuid == 0 )
- acpi_set_cstate_limit(op->u.set_max_cstate);
- else if ( op->cpuid == 1 )
- acpi_set_csubstate_limit(op->u.set_max_cstate);
- else
- ret = -EINVAL;
- return ret;
- }
-
- if ( op->cpuid >= nr_cpu_ids || !cpu_online(op->cpuid) )
- return -EINVAL;
- pmpt = processor_pminfo[op->cpuid];
-
- switch ( op->cmd & PM_PARA_CATEGORY_MASK )
- {
- case CPUFREQ_PARA:
- if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) )
- return -ENODEV;
- if ( !pmpt || !(pmpt->init & XEN_PX_INIT) )
- return -EINVAL;
- break;
- }
-
- switch ( op->cmd )
- {
- case GET_CPUFREQ_PARA:
- {
- ret = get_cpufreq_para(op);
- break;
- }
-
- case SET_CPUFREQ_GOV:
- {
- ret = set_cpufreq_gov(op);
- break;
- }
-
- case SET_CPUFREQ_PARA:
- {
- ret = set_cpufreq_para(op);
- break;
- }
-
- case SET_CPUFREQ_CPPC:
- ret = set_cpufreq_cppc(op);
- break;
-
- case GET_CPUFREQ_AVGFREQ:
- {
- op->u.get_avgfreq = cpufreq_driver_getavg(op->cpuid, USR_GETAVG);
- break;
- }
-
- case XEN_SYSCTL_pm_op_enable_turbo:
- {
- ret = cpufreq_update_turbo(op->cpuid, CPUFREQ_TURBO_ENABLED);
- break;
- }
-
- case XEN_SYSCTL_pm_op_disable_turbo:
- {
- ret = cpufreq_update_turbo(op->cpuid, CPUFREQ_TURBO_DISABLED);
- break;
- }
-
- default:
- printk("not defined sub-hypercall @ do_pm_op\n");
- ret = -ENOSYS;
- break;
- }
-
- return ret;
-}
diff --git a/xen/drivers/cpufreq/cpufreq_misc_governors.c
b/xen/drivers/cpufreq/cpufreq_misc_governors.c
index 0327fad23b..e5cb9ab02f 100644
--- a/xen/drivers/cpufreq/cpufreq_misc_governors.c
+++ b/xen/drivers/cpufreq/cpufreq_misc_governors.c
@@ -64,6 +64,7 @@ static int cf_check cpufreq_governor_userspace(
return ret;
}
+#ifdef CONFIG_PM_OP
int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq)
{
struct cpufreq_policy *policy;
@@ -80,6 +81,7 @@ int write_userspace_scaling_setspeed(unsigned int cpu,
unsigned int freq)
return __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
}
+#endif /* CONFIG_PM_OP */
static bool __init cf_check
cpufreq_userspace_handle_option(const char *name, const char *val)
diff --git a/xen/drivers/cpufreq/cpufreq_ondemand.c
b/xen/drivers/cpufreq/cpufreq_ondemand.c
index 06cfc88d30..0126a3f5d9 100644
--- a/xen/drivers/cpufreq/cpufreq_ondemand.c
+++ b/xen/drivers/cpufreq/cpufreq_ondemand.c
@@ -57,6 +57,7 @@ static struct dbs_tuners {
static DEFINE_PER_CPU(struct timer, dbs_timer);
+#ifdef CONFIG_PM_OP
int write_ondemand_sampling_rate(unsigned int sampling_rate)
{
if ( (sampling_rate > MAX_SAMPLING_RATE / MICROSECS(1)) ||
@@ -93,6 +94,7 @@ int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
return 0;
}
+#endif /* CONFIG_PM_OP */
static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
{
diff --git a/xen/drivers/cpufreq/utility.c b/xen/drivers/cpufreq/utility.c
index 723045b240..987c3b5929 100644
--- a/xen/drivers/cpufreq/utility.c
+++ b/xen/drivers/cpufreq/utility.c
@@ -224,47 +224,6 @@ int cpufreq_driver_getavg(unsigned int cpu, unsigned int
flag)
return policy->cur;
}
-int cpufreq_update_turbo(unsigned int cpu, int new_state)
-{
- struct cpufreq_policy *policy;
- int curr_state;
- int ret = 0;
-
- if (new_state != CPUFREQ_TURBO_ENABLED &&
- new_state != CPUFREQ_TURBO_DISABLED)
- return -EINVAL;
-
- policy = per_cpu(cpufreq_cpu_policy, cpu);
- if (!policy)
- return -EACCES;
-
- if (policy->turbo == CPUFREQ_TURBO_UNSUPPORTED)
- return -EOPNOTSUPP;
-
- curr_state = policy->turbo;
- if (curr_state == new_state)
- return 0;
-
- policy->turbo = new_state;
- if (cpufreq_driver.update)
- {
- ret = alternative_call(cpufreq_driver.update, cpu, policy);
- if (ret)
- policy->turbo = curr_state;
- }
-
- return ret;
-}
-
-
-int cpufreq_get_turbo_status(unsigned int cpu)
-{
- struct cpufreq_policy *policy;
-
- policy = per_cpu(cpufreq_cpu_policy, cpu);
- return policy && policy->turbo == CPUFREQ_TURBO_ENABLED;
-}
-
/*********************************************************************
* POLICY *
*********************************************************************/
diff --git a/xen/include/acpi/cpufreq/cpufreq.h
b/xen/include/acpi/cpufreq/cpufreq.h
index 241117a9af..0742aa9f44 100644
--- a/xen/include/acpi/cpufreq/cpufreq.h
+++ b/xen/include/acpi/cpufreq/cpufreq.h
@@ -143,9 +143,6 @@ extern int cpufreq_driver_getavg(unsigned int cpu, unsigned
int flag);
#define CPUFREQ_TURBO_UNSUPPORTED 0
#define CPUFREQ_TURBO_ENABLED 1
-int cpufreq_update_turbo(unsigned int cpu, int new_state);
-int cpufreq_get_turbo_status(unsigned int cpu);
-
static inline int
__cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
{
--
generated by git-patchbot for /home/xen/git/xen.git#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |