|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v5 04/18] xen/cpufreq: introduce new sub-hypercall to propagate CPPC data
On 27.05.2025 10:48, Penny Zheng wrote:
> @@ -635,6 +641,124 @@ out:
> return ret;
> }
>
> +static void print_CPPC(const struct xen_processor_cppc *cppc_data)
> +{
> + printk("\t_CPC: highest_perf=%u, lowest_perf=%u, "
> + "nominal_perf=%u, lowest_nonlinear_perf=%u, "
> + "nominal_mhz=%uMHz, lowest_mhz=%uMHz\n",
> + cppc_data->cpc.highest_perf, cppc_data->cpc.lowest_perf,
> + cppc_data->cpc.nominal_perf, cppc_data->cpc.lowest_nonlinear_perf,
> + cppc_data->cpc.nominal_mhz, cppc_data->cpc.lowest_mhz);
> +}
> +
> +int set_cppc_pminfo(unsigned int acpi_id,
> + const struct xen_processor_cppc *cppc_data)
> +{
> + int ret = 0, cpuid;
> + struct processor_pminfo *pm_info;
> +
> + cpuid = get_cpu_id(acpi_id);
> + if ( cpuid < 0 || !cppc_data )
The !cppc_data part isn't really needed, is it?
> + {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + if ( cppc_data->pad[0] || cppc_data->pad[1] || cppc_data->pad[2] )
> + {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + if ( cpufreq_verbose )
> + printk("Set CPU acpi_id(%u) cpuid(%d) CPPC State info:\n",
> + acpi_id, cpuid);
> +
> + pm_info = processor_pminfo[cpuid];
> + if ( !pm_info )
> + {
> + pm_info = xvzalloc(struct processor_pminfo);
> + if ( !pm_info )
> + {
> + ret = -ENOMEM;
> + goto out;
> + }
> + processor_pminfo[cpuid] = pm_info;
> + }
> + pm_info->acpi_id = acpi_id;
> + pm_info->id = cpuid;
> + pm_info->cppc_data = *cppc_data;
> +
> + if ( cppc_data->flags & XEN_CPPC_PSD )
> + {
> + ret = check_psd_pminfo(cppc_data->shared_type);
> + if ( ret )
> + goto out;
> + }
> +
> + if ( cppc_data->flags & XEN_CPPC_CPC )
> + {
> + if ( cppc_data->cpc.highest_perf == 0 ||
> + cppc_data->cpc.highest_perf > UINT8_MAX ||
> + cppc_data->cpc.nominal_perf == 0 ||
> + cppc_data->cpc.nominal_perf > UINT8_MAX ||
> + cppc_data->cpc.lowest_nonlinear_perf == 0 ||
> + cppc_data->cpc.lowest_nonlinear_perf > UINT8_MAX ||
> + cppc_data->cpc.lowest_perf == 0 ||
> + cppc_data->cpc.lowest_perf > UINT8_MAX ||
> + cppc_data->cpc.lowest_perf >
> + cppc_data->cpc.nominal_perf ||
> + cppc_data->cpc.lowest_nonlinear_perf >
> + cppc_data->cpc.nominal_perf ||
> + cppc_data->cpc.nominal_perf > cppc_data->cpc.highest_perf )
> + /*
> + * Right now, Xen doesn't actually use highest_perf/nominal_perf/
> + * lowest_nonlinear_perf/lowest_perf values read from ACPI _CPC
> + * table. Xen reads CPPC capability MSR to get these four values.
> + * So warning is enough.
> + */
> + printk_once(XENLOG_WARNING
> + "Broken CPPC perf values: lowest(%u),
> nonlinear_lowest(%u), nominal(%u), highest(%u)\n",
> + cppc_data->cpc.lowest_perf,
> + cppc_data->cpc.lowest_nonlinear_perf,
> + cppc_data->cpc.nominal_perf,
> + cppc_data->cpc.highest_perf);
> +
> + /* lowest_mhz and nominal_mhz are optional value */
> + if ( cppc_data->cpc.lowest_mhz > cppc_data->cpc.nominal_mhz )
> + {
> + printk_once(XENLOG_WARNING
> + "Broken CPPC freq values: lowest(%u), nominal(%u)\n",
> + cppc_data->cpc.lowest_mhz,
> + cppc_data->cpc.nominal_mhz);
> + /* Re-set with zero values, instead of keeping invalid values */
> + pm_info->cppc_data.cpc.nominal_mhz = 0;
> + pm_info->cppc_data.cpc.lowest_mhz = 0;
> + }
> + }
> +
> + if ( cppc_data->flags == (XEN_CPPC_PSD | XEN_CPPC_CPC) )
> + {
> + if ( cpufreq_verbose )
> + {
> + print_PSD(&pm_info->cppc_data.domain_info);
> + print_CPPC(&pm_info->cppc_data);
> + }
> +
> + pm_info->init = XEN_CPPC_INIT;
> + ret = cpufreq_cpu_init(cpuid);
> +#ifndef NDEBUG
> + if ( ret )
> + dprintk(XENLOG_WARNING,
> + "CPU %u failed to be initialized with amd-cppc mode, and
> users could only reboot and re-define cmdline with \"cpufreq=xen\"",
> + cpuid);
> +#endif
What use if the #ifdef here? The more that NDEBUG controls behavior of ASSERT(),
not that of (debug) logging.
> --- a/xen/include/public/platform.h
> +++ b/xen/include/public/platform.h
> @@ -363,6 +363,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
> #define XEN_PM_PX 1
> #define XEN_PM_TX 2
> #define XEN_PM_PDC 3
> +#define XEN_PM_CPPC 4
>
> /* Px sub info type */
> #define XEN_PX_PCT 1
> @@ -370,6 +371,10 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
> #define XEN_PX_PPC 4
> #define XEN_PX_PSD 8
>
> +/* CPPC sub info type */
> +#define XEN_CPPC_PSD 1
> +#define XEN_CPPC_CPC 2
> +
> struct xen_power_register {
> uint32_t space_id;
> uint32_t bit_width;
> @@ -457,6 +462,30 @@ struct xen_processor_performance {
> typedef struct xen_processor_performance xen_processor_performance_t;
> DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t);
>
> +struct xen_processor_cppc {
> + uint8_t flags; /* flag for CPPC sub info type */
A common way of commenting on such would be /* XEN_CPPC_... */.
In any event, here and ...
> + uint8_t pad[3]; /* padding and must be zero */
... here (and of course anywhere else) - please adhere to designated comment
style.
> + /*
> + * Subset _CPC fields useful for CPPC-compatible cpufreq
> + * driver's initialization
> + */
> + struct {
> + uint32_t highest_perf;
> + uint32_t nominal_perf;
> + uint32_t lowest_nonlinear_perf;
> + uint32_t lowest_perf;
> + uint32_t lowest_mhz;
> + uint32_t nominal_mhz;
> + } cpc;
> + /* Coordination type of this processor */
> +#define XEN_CPUPERF_SHARED_TYPE_HW 1 /* HW does needed coordination */
> +#define XEN_CPUPERF_SHARED_TYPE_ALL 2 /* All dependent CPUs should set freq
> */
> +#define XEN_CPUPERF_SHARED_TYPE_ANY 3 /* Freq can be set from any dependent
> CPU */
What's this? The exact same #define-s already exist in struct
xen_processor_performance, unless I'm missing a hard to notice spelling
difference. You can simply ...
> + uint32_t shared_type;
... use the comment suggestion from above here as well.
> --- a/xen/include/xen/pmstat.h
> +++ b/xen/include/xen/pmstat.h
> @@ -7,8 +7,13 @@
>
> int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf);
> long set_cx_pminfo(uint32_t acpi_id, struct xen_processor_power *power);
> +int set_cppc_pminfo(unsigned int acpi_id,
> + const struct xen_processor_cppc *cppc_data);
Nit: Relative ordering would be nice to be consistent between this group
and ...
> #ifdef CONFIG_COMPAT
> +struct compat_processor_cppc;
> +int compat_set_cppc_pminfo(unsigned int acpi_id,
> + const struct compat_processor_cppc *cppc_data);
> struct compat_processor_performance;
> int compat_set_px_pminfo(uint32_t acpi_id, struct
> compat_processor_performance *perf);
> struct compat_processor_power;
... this one. (Personally I dislike additions at the top of any group,
as this gives the impression that the new stuff is "more important" than
what has been there already. See also how in a number of places we simply
sort alphabetically, to avoid the common "insert at top" and "insert at
bottom" patterns.)
> --- a/xen/include/xlat.lst
> +++ b/xen/include/xlat.lst
> @@ -168,6 +168,7 @@
> ! processor_performance platform.h
> ! processor_power platform.h
> ? processor_px platform.h
> +! processor_cppc platform.h
> ! psd_package platform.h
> ? xenpf_enter_acpi_sleep platform.h
> ? xenpf_pcpu_version platform.h
Please obey to sorting in this file.
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |