[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 10/20] xen/pmstat: introduce CONFIG_PM_OP



On Mon, 21 Apr 2025, Penny Zheng wrote:
> 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
> 
> Signed-off-by: Penny Zheng <Penny.Zheng@xxxxxxx>

I manually checked the code movement for correctness

Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>



> ---
> v2 -> v3
> - new commit
> ---
>  xen/arch/x86/acpi/cpufreq/hwp.c              |   6 +
>  xen/arch/x86/acpi/cpufreq/powernow.c         |   4 +
>  xen/common/Kconfig                           |   7 +
>  xen/common/sysctl.c                          |   4 +-
>  xen/drivers/acpi/Makefile                    |   1 +
>  xen/drivers/acpi/pm_op.c                     | 409 +++++++++++++++++++
>  xen/drivers/acpi/pmstat.c                    | 357 ----------------
>  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 -
>  11 files changed, 434 insertions(+), 402 deletions(-)
>  create mode 100644 xen/drivers/acpi/pm_op.c
> 
> 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/common/Kconfig b/xen/common/Kconfig
> index 9cccc37232..ca1f692487 100644
> --- a/xen/common/Kconfig
> +++ b/xen/common/Kconfig
> @@ -593,4 +593,11 @@ config SYSCTL
>         to reduce Xen footprint.
>  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 2fe76362b1..4ab827b694 100644
> --- a/xen/common/sysctl.c
> +++ b/xen/common/sysctl.c
> @@ -181,13 +181,15 @@ 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 )
>              copyback = 1;
>          break;
> -#endif
> +#endif /* CONFIG_PM_OP */
>  
>      case XEN_SYSCTL_page_offline_op:
>      {
> diff --git a/xen/drivers/acpi/Makefile b/xen/drivers/acpi/Makefile
> index 2fc5230253..e1f84a4468 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..3123cb9556
> --- /dev/null
> +++ b/xen/drivers/acpi/pm_op.c
> @@ -0,0 +1,409 @@
> +/* 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 ( IS_ENABLED(CONFIG_INTEL) &&
> +         !strncmp(op->u.get_para.scaling_driver, XEN_HWP_DRIVER_NAME,
> +                  CPUFREQ_NAME_LEN) )
> +        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->perf.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 abfdc45cc2..61b60e59a2 100644
> --- a/xen/drivers/acpi/pmstat.c
> +++ b/xen/drivers/acpi/pmstat.c
> @@ -330,360 +330,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 ( IS_ENABLED(CONFIG_INTEL) &&
> -         !strncmp(op->u.get_para.scaling_driver, XEN_HWP_DRIVER_NAME,
> -                  CPUFREQ_NAME_LEN) )
> -        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->perf.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)
>  {
> -- 
> 2.34.1
> 



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.