[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v5 18/18] xen/cpufreq: Adapt SET/GET_CPUFREQ_CPPC xen_sysctl_pm_op for amd-cppc driver
Introduce helper set_amd_cppc_para() and get_amd_cppc_para() to SET/GET CPPC-related para for amd-cppc/amd-cppc-epp driver. In get_cpufreq_cppc()/set_cpufreq_cppc(), we use "processor_pminfo[cpuid]->init & XEN_CPPC_INIT" to identify cpufreq driver is amd-cppc/amd-cppc-epp. Furthermore, using whether ->setpolicy isn't null to tell whether amd-cppc in active mode. Also, a new field "policy" has also been added in "struct xen_cppc_para" to describe performance policy in active mode. It gets printed with other cppc paras. A set of public macro XEN_CPUFREQ_POLICY_xxx is introduced to be sync with internal ones CPUFREQ_POLICY_xxx. A new policy XEN_CPUFREQ_POLICY_BALANCE is introduced, and could be achieved only via xenpm XEN_SYSCTL_CPPC_SET_PRESET_BALANCE preset. Signed-off-by: Penny Zheng <Penny.Zheng@xxxxxxx> --- v1 -> v2: - Give the variable des_perf an initializer of 0 - Use the strncmp()s directly in the if() --- v3 -> v4 - refactor comments - remove double blank lines - replace amd_cppc_in_use flag with XEN_PROCESSOR_PM_CPPC --- - add new field "policy" in "struct xen_cppc_para" - add new performamce policy XEN_CPUFREQ_POLICY_BALANCE - drop string comparisons with "processor_pminfo[cpuid]->init & XEN_CPPC_INIT" and "cpufreq.setpolicy == NULL" - Blank line ahead of the main "return" of a function - refactor comments, commit message and title --- tools/misc/xenpm.c | 10 +++ xen/arch/x86/acpi/cpufreq/amd-cppc.c | 129 +++++++++++++++++++++++++++ xen/drivers/acpi/pmstat.c | 13 ++- xen/include/acpi/cpufreq/cpufreq.h | 12 ++- xen/include/public/sysctl.h | 5 ++ 5 files changed, 163 insertions(+), 6 deletions(-) diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c index 2864506da4..2e5975cae4 100644 --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -38,6 +38,13 @@ static xc_interface *xc_handle; static unsigned int max_cpu_nr; +static const char cpufreq_policy_str[][12] = { + [XEN_CPUFREQ_POLICY_UNKNOWN] = "none", + [XEN_CPUFREQ_POLICY_POWERSAVE] = "powersave", + [XEN_CPUFREQ_POLICY_PERFORMANCE] = "performance", + [XEN_CPUFREQ_POLICY_BALANCE] = "balance", +}; + /* help message */ void show_help(void) { @@ -984,6 +991,9 @@ static void print_cppc_para(unsigned int cpuid, printf(" : desired [%"PRIu32"%s]\n", cppc->desired, cppc->desired ? "" : " hw autonomous"); + + printf(" performance policy : %s\n", + cpufreq_policy_str[cppc->policy]); printf("\n"); } diff --git a/xen/arch/x86/acpi/cpufreq/amd-cppc.c b/xen/arch/x86/acpi/cpufreq/amd-cppc.c index 5f15e86dc4..490446018c 100644 --- a/xen/arch/x86/acpi/cpufreq/amd-cppc.c +++ b/xen/arch/x86/acpi/cpufreq/amd-cppc.c @@ -506,6 +506,135 @@ static int cf_check amd_cppc_epp_set_policy(struct cpufreq_policy *policy) return 0; } +int get_amd_cppc_para(const struct cpufreq_policy *policy, + struct xen_cppc_para *cppc_para) +{ + const struct amd_cppc_drv_data *data = per_cpu(amd_cppc_drv_data, + policy->cpu); + + if ( data == NULL ) + return -ENODATA; + + cppc_para->policy = policy->policy; + cppc_para->lowest = data->caps.lowest_perf; + cppc_para->lowest_nonlinear = data->caps.lowest_nonlinear_perf; + cppc_para->nominal = data->caps.nominal_perf; + cppc_para->highest = data->caps.highest_perf; + cppc_para->minimum = data->req.min_perf; + cppc_para->maximum = data->req.max_perf; + cppc_para->desired = data->req.des_perf; + cppc_para->energy_perf = data->req.epp; + + return 0; +} + +int set_amd_cppc_para(struct cpufreq_policy *policy, + const struct xen_set_cppc_para *set_cppc) +{ + unsigned int cpu = policy->cpu; + struct amd_cppc_drv_data *data = per_cpu(amd_cppc_drv_data, cpu); + uint8_t max_perf, min_perf, des_perf = 0, epp; + + if ( data == NULL ) + return -ENOENT; + + /* Validate all parameters */ + if ( set_cppc->minimum > UINT8_MAX || set_cppc->maximum > UINT8_MAX || + set_cppc->desired > UINT8_MAX || set_cppc->energy_perf > UINT8_MAX ) + return -EINVAL; + + /* Only allow values if params bit is set. */ + if ( (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED) && + set_cppc->desired) || + (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MINIMUM) && + set_cppc->minimum) || + (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MAXIMUM) && + set_cppc->maximum) || + (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_ENERGY_PERF) && + set_cppc->energy_perf) ) + return -EINVAL; + + /* Activity window not supported in MSR */ + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_ACT_WINDOW ) + return -EOPNOTSUPP; + + /* Return if there is nothing to do. */ + if ( set_cppc->set_params == 0 ) + return 0; + + epp = per_cpu(epp_init, cpu); + /* + * Apply presets: + * XEN_SYSCTL_CPPC_SET_DESIRED reflects whether desired perf is set, which + * is also the flag to distinguish between passive mode and active mode. + * When it is set, CPPC in passive mode, only + * XEN_SYSCTL_CPPC_SET_PRESET_NONE could be chosen. + * when it is not set, CPPC in active mode, three different profile + * XEN_SYSCTL_CPPC_SET_PRESET_POWERSAVE/PERFORMANCE/BALANCE are provided, + */ + switch ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_PRESET_MASK ) + { + case XEN_SYSCTL_CPPC_SET_PRESET_POWERSAVE: + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED ) + return -EINVAL; + policy->policy = CPUFREQ_POLICY_POWERSAVE; + min_perf = data->caps.lowest_perf; + /* Lower max frequency to lowest */ + max_perf = data->caps.lowest_perf; + epp = CPPC_ENERGY_PERF_MAX_POWERSAVE; + break; + + case XEN_SYSCTL_CPPC_SET_PRESET_PERFORMANCE: + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED ) + return -EINVAL; + /* Increase idle frequency to highest */ + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + min_perf = data->caps.highest_perf; + max_perf = data->caps.highest_perf; + epp = CPPC_ENERGY_PERF_MAX_PERFORMANCE; + break; + + case XEN_SYSCTL_CPPC_SET_PRESET_BALANCE: + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED ) + return -EINVAL; + policy->policy = CPUFREQ_POLICY_BALANCE; + min_perf = data->caps.lowest_perf; + max_perf = data->caps.highest_perf; + epp = CPPC_ENERGY_PERF_BALANCE; + break; + + case XEN_SYSCTL_CPPC_SET_PRESET_NONE: + /* + * In paasive mode, Xen governor is responsible for perfomance tuning. + * we shall set lowest_perf with "lowest_nonlinear_perf" to ensure + * governoring performance in P-states range. + */ + min_perf = data->caps.lowest_nonlinear_perf; + max_perf = data->caps.highest_perf; + break; + + default: + return -EINVAL; + } + + /* Further customize presets if needed */ + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MINIMUM ) + min_perf = set_cppc->minimum; + + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MAXIMUM ) + max_perf = set_cppc->maximum; + + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_ENERGY_PERF ) + epp = set_cppc->energy_perf; + + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED ) + des_perf = set_cppc->desired; + + amd_cppc_write_request(cpu, min_perf, des_perf, max_perf, epp); + + return 0; +} + static const struct cpufreq_driver __initconst_cf_clobber amd_cppc_cpufreq_driver = { diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c index e5f375921a..9e1ed29a0a 100644 --- a/xen/drivers/acpi/pmstat.c +++ b/xen/drivers/acpi/pmstat.c @@ -334,6 +334,10 @@ static int get_cpufreq_cppc(struct xen_sysctl_pm_op *op) if ( hwp_active() ) ret = get_hwp_para(op->cpuid, &op->u.cppc_para); + if ( processor_pminfo[op->cpuid]->init & XEN_CPPC_INIT ) + ret = get_amd_cppc_para(per_cpu(cpufreq_cpu_policy, op->cpuid), + &op->u.cppc_para); + return ret; } @@ -429,10 +433,13 @@ static int set_cpufreq_cppc(struct xen_sysctl_pm_op *op) if ( !policy || !policy->governor ) return -ENOENT; - if ( !hwp_active() ) - return -EOPNOTSUPP; + if ( hwp_active() ) + return set_hwp_para(policy, &op->u.set_cppc); + + if ( processor_pminfo[op->cpuid]->init & XEN_CPPC_INIT ) + return set_amd_cppc_para(policy, &op->u.set_cppc); - return set_hwp_para(policy, &op->u.set_cppc); + return -EOPNOTSUPP; } int do_pm_op(struct xen_sysctl_pm_op *op) diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index 6f31009e82..c542a6e633 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -134,14 +134,16 @@ extern int cpufreq_register_governor(struct cpufreq_governor *governor); extern struct cpufreq_governor *__find_governor(const char *governor); #define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs -#define CPUFREQ_POLICY_UNKNOWN 0 +#define CPUFREQ_POLICY_UNKNOWN XEN_CPUFREQ_POLICY_UNKNOWN /* * If cpufreq_driver->target() exists, the ->governor decides what frequency * within the limits is used. If cpufreq_driver->setpolicy() exists, these * two generic policies are available: */ -#define CPUFREQ_POLICY_POWERSAVE 1 -#define CPUFREQ_POLICY_PERFORMANCE 2 +#define CPUFREQ_POLICY_POWERSAVE XEN_CPUFREQ_POLICY_POWERSAVE +#define CPUFREQ_POLICY_PERFORMANCE XEN_CPUFREQ_POLICY_PERFORMANCE +/* Achieved only via xenpm XEN_SYSCTL_CPPC_SET_PRESET_BALANCE preset */ +#define CPUFREQ_POLICY_BALANCE XEN_CPUFREQ_POLICY_BALANCE unsigned int cpufreq_policy_from_governor(const struct cpufreq_governor *gov); @@ -292,5 +294,9 @@ int acpi_cpufreq_register(void); int amd_cppc_cmdline_parse(const char *s, const char *e); int amd_cppc_register_driver(void); +int get_amd_cppc_para(const struct cpufreq_policy *policy, + struct xen_cppc_para *cppc_para); +int set_amd_cppc_para(struct cpufreq_policy *policy, + const struct xen_set_cppc_para *set_cppc); #endif /* __XEN_CPUFREQ_PM_H__ */ diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 29872fe508..18c38744ae 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -308,6 +308,11 @@ struct xen_ondemand { struct xen_cppc_para { /* OUT */ +#define XEN_CPUFREQ_POLICY_UNKNOWN 0 +#define XEN_CPUFREQ_POLICY_POWERSAVE 1 +#define XEN_CPUFREQ_POLICY_PERFORMANCE 2 +#define XEN_CPUFREQ_POLICY_BALANCE 4 + uint32_t policy; /* activity_window supported if set */ #define XEN_SYSCTL_CPPC_FEAT_ACT_WINDOW (1 << 0) uint32_t features; /* bit flags for features */ -- 2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |