In amd-cppc passive mode, it's Xen governor which is responsible for
performance tuning, so governor and CPPC could co-exist. That is, both
governor-info and CPPC-info need to be printed together via xenpm tool.
If we tried to still put it in "struct xen_get_cpufreq_para" (e.g. just move
out of union), "struct xen_get_cpufreq_para" will enlarge too much to further
make xen_sysctl.u exceed 128 bytes.
So we introduce a new sub-op GET_CPUFREQ_CPPC to specifically print
CPPC-related para.
Signed-off-by: Penny Zheng <Penny.Zheng@amd.com>
---
v4 -> v5:
- new commit
---
v5 -> v6:
- remove the changes for get-cpufreq-para
---
tools/include/xenctrl.h | 2 ++
tools/libs/ctrl/xc_pm.c | 27 +++++++++++++++++++++
tools/misc/xenpm.c | 47 +++++++++++++++++++++++++++++++++++++
xen/drivers/acpi/pm-op.c | 4 ++++
xen/include/public/sysctl.h | 2 ++
5 files changed, 82 insertions(+)
diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
index 965d3b585a..699243c4df 100644
--- a/tools/include/xenctrl.h
+++ b/tools/include/xenctrl.h
@@ -1953,6 +1953,8 @@ int xc_set_cpufreq_para(xc_interface *xch, int cpuid,
int ctrl_type, int ctrl_value);
int xc_set_cpufreq_cppc(xc_interface *xch, int cpuid,
xc_set_cppc_para_t *set_cppc);
+int xc_get_cppc_para(xc_interface *xch, unsigned int cpuid,
+ xc_cppc_para_t *cppc_para);
int xc_get_cpufreq_avgfreq(xc_interface *xch, int cpuid, int *avg_freq);
int xc_set_sched_opt_smt(xc_interface *xch, uint32_t value);
diff --git a/tools/libs/ctrl/xc_pm.c b/tools/libs/ctrl/xc_pm.c
index 6fda973f1f..3f72152617 100644
--- a/tools/libs/ctrl/xc_pm.c
+++ b/tools/libs/ctrl/xc_pm.c
@@ -366,6 +366,33 @@ int xc_set_cpufreq_cppc(xc_interface *xch, int cpuid,
return ret;
}
+int xc_get_cppc_para(xc_interface *xch, unsigned int cpuid,
+ xc_cppc_para_t *cppc_para)
+{
+ int ret;
+ struct xen_sysctl sysctl = {};
+ struct xen_get_cppc_para *sys_cppc_para = &sysctl.u.pm_op.u.get_cppc;
+
+ if ( !xch || !cppc_para )
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sysctl.cmd = XEN_SYSCTL_pm_op;
+ sysctl.u.pm_op.cmd = GET_CPUFREQ_CPPC;
+ sysctl.u.pm_op.cpuid = cpuid;
+
+ ret = xc_sysctl(xch, &sysctl);
+ if ( ret )
+ return ret;
+
+ BUILD_BUG_ON(sizeof(*cppc_para) != sizeof(*sys_cppc_para));
+ memcpy(cppc_para, sys_cppc_para, sizeof(*sys_cppc_para));
+
+ return ret;
+}
+
int xc_get_cpufreq_avgfreq(xc_interface *xch, int cpuid, int *avg_freq)
{
int ret = 0;
diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c
index 120e9eae22..bdc09f468a 100644
--- a/tools/misc/xenpm.c
+++ b/tools/misc/xenpm.c
@@ -69,6 +69,7 @@ void show_help(void)
" set-max-cstate <num>|'unlimited' [<num2>|'unlimited']\n"
" set the C-State limitation (<num> >= 0) and\n"
" optionally the C-sub-state limitation (<num2> >= 0)\n"
+ " get-cpufreq-cppc [cpuid] list cpu cppc parameter of CPU <cpuid> or all\n"
" set-cpufreq-cppc [cpuid] [balance|performance|powersave] <param:val>*\n"
" set Hardware P-State (HWP) parameters\n"
" on CPU <cpuid> or all if omitted.\n"
@@ -996,6 +997,51 @@ void cpufreq_para_func(int argc, char *argv[])
show_cpufreq_para_by_cpuid(xc_handle, cpuid);
}
+/* show cpu cppc parameters information on CPU cpuid */
+static int show_cppc_para_by_cpuid(xc_interface *xc_handle, unsigned int cpuid)
+{
+ int ret;
+ xc_cppc_para_t cppc_para;
+
+ ret = xc_get_cppc_para(xc_handle, cpuid, &cppc_para);
+ if ( !ret )
+ {
+ printf("cpu id : %d\n", cpuid);
+ print_cppc_para(cpuid, &cppc_para);
+ printf("\n");
+ }
+ else if ( errno == ENODEV )
+ {
+ ret = -ENODEV;
+ fprintf(stderr, "CPPC is not available!\n");
+ }
+ else
+ fprintf(stderr, "[CPU%u] failed to get cppc parameter\n", cpuid);
+
+ return ret;
+}
+
+static void cppc_para_func(int argc, char *argv[])
+{
+ int cpuid = -1;
+
+ if ( argc > 0 )
+ parse_cpuid(argv[0], &cpuid);
+
+ if ( cpuid < 0 )
+ {
+ unsigned int i;
+
+ /* show cpu cppc information on all cpus */
+ for ( i = 0; i < max_cpu_nr; i++ )
+ /* Bail out only on unsupported platform */
+ if ( show_cppc_para_by_cpuid(xc_handle, i) == -ENODEV )
+ break;
+ }
+ else
+ show_cppc_para_by_cpuid(xc_handle, cpuid);
+}
+
void scaling_max_freq_func(int argc, char *argv[])
{
int cpuid = -1, freq = -1;
@@ -1576,6 +1622,7 @@ struct {
{ "get-cpufreq-average", cpufreq_func },
{ "start", start_gather_func },
{ "get-cpufreq-para", cpufreq_para_func },
+ { "get-cpufreq-cppc", cppc_para_func },
{ "set-cpufreq-cppc", cppc_set_func },
{ "set-scaling-maxfreq", scaling_max_freq_func },
{ "set-scaling-minfreq", scaling_min_freq_func },
diff --git a/xen/drivers/acpi/pm-op.c b/xen/drivers/acpi/pm-op.c
index acaa33561f..0723cea34c 100644
--- a/xen/drivers/acpi/pm-op.c
+++ b/xen/drivers/acpi/pm-op.c
@@ -390,6 +390,10 @@ int do_pm_op(struct xen_sysctl_pm_op *op)
ret = set_cpufreq_para(op);
break;
+ case GET_CPUFREQ_CPPC:
+ ret = get_cpufreq_cppc(op->cpuid, &op->u.get_cppc);
+ break;
+
case SET_CPUFREQ_CPPC:
ret = set_cpufreq_cppc(op);
break;
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index eb3a23b038..2578a63b01 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -523,6 +523,7 @@ struct xen_sysctl_pm_op {
#define SET_CPUFREQ_PARA (CPUFREQ_PARA | 0x03)
#define GET_CPUFREQ_AVGFREQ (CPUFREQ_PARA | 0x04)
#define SET_CPUFREQ_CPPC (CPUFREQ_PARA | 0x05)
+ #define GET_CPUFREQ_CPPC (CPUFREQ_PARA | 0x06)
/* set/reset scheduler power saving option */
#define XEN_SYSCTL_pm_op_set_sched_opt_smt 0x21
@@ -547,6 +548,7 @@ struct xen_sysctl_pm_op {
uint32_t cpuid;
union {
struct xen_get_cpufreq_para get_para;
+ struct xen_get_cppc_para get_cppc;
struct xen_set_cpufreq_gov set_gov;
struct xen_set_cpufreq_para set_para;
struct xen_set_cppc_para set_cppc;
--
2.34.1
On 11.07.2025 05:51, Penny Zheng wrote:
> In amd-cppc passive mode, it's Xen governor which is responsible for
> performance tuning, so governor and CPPC could co-exist. That is, both
> governor-info and CPPC-info need to be printed together via xenpm tool.
>
> If we tried to still put it in "struct xen_get_cpufreq_para" (e.g. just move
> out of union), "struct xen_get_cpufreq_para" will enlarge too much to further
> make xen_sysctl.u exceed 128 bytes.
> So we introduce a new sub-op GET_CPUFREQ_CPPC to specifically print
> CPPC-related para.
>
> Signed-off-by: Penny Zheng <Penny.Zheng@amd.com>
> ---
> v4 -> v5:
> - new commit
> ---
> v5 -> v6:
> - remove the changes for get-cpufreq-para
> ---
> tools/include/xenctrl.h | 2 ++
> tools/libs/ctrl/xc_pm.c | 27 +++++++++++++++++++++
> tools/misc/xenpm.c | 47 +++++++++++++++++++++++++++++++++++++
> xen/drivers/acpi/pm-op.c | 4 ++++
> xen/include/public/sysctl.h | 2 ++
> 5 files changed, 82 insertions(+)
>
> diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
> index 965d3b585a..699243c4df 100644
> --- a/tools/include/xenctrl.h
> +++ b/tools/include/xenctrl.h
> @@ -1953,6 +1953,8 @@ int xc_set_cpufreq_para(xc_interface *xch, int cpuid,
> int ctrl_type, int ctrl_value);
> int xc_set_cpufreq_cppc(xc_interface *xch, int cpuid,
> xc_set_cppc_para_t *set_cppc);
> +int xc_get_cppc_para(xc_interface *xch, unsigned int cpuid,
> + xc_cppc_para_t *cppc_para);
> int xc_get_cpufreq_avgfreq(xc_interface *xch, int cpuid, int *avg_freq);
>
> int xc_set_sched_opt_smt(xc_interface *xch, uint32_t value);
> diff --git a/tools/libs/ctrl/xc_pm.c b/tools/libs/ctrl/xc_pm.c
> index 6fda973f1f..3f72152617 100644
> --- a/tools/libs/ctrl/xc_pm.c
> +++ b/tools/libs/ctrl/xc_pm.c
> @@ -366,6 +366,33 @@ int xc_set_cpufreq_cppc(xc_interface *xch, int cpuid,
> return ret;
> }
>
> +int xc_get_cppc_para(xc_interface *xch, unsigned int cpuid,
> + xc_cppc_para_t *cppc_para)
> +{
> + int ret;
> + struct xen_sysctl sysctl = {};
> + struct xen_get_cppc_para *sys_cppc_para = &sysctl.u.pm_op.u.get_cppc;
> +
> + if ( !xch || !cppc_para )
> + {
> + errno = EINVAL;
> + return -1;
> + }
> +
> + sysctl.cmd = XEN_SYSCTL_pm_op;
> + sysctl.u.pm_op.cmd = GET_CPUFREQ_CPPC;
> + sysctl.u.pm_op.cpuid = cpuid;
> +
> + ret = xc_sysctl(xch, &sysctl);
> + if ( ret )
> + return ret;
> +
> + BUILD_BUG_ON(sizeof(*cppc_para) != sizeof(*sys_cppc_para));
> + memcpy(cppc_para, sys_cppc_para, sizeof(*sys_cppc_para));
> +
> + return ret;
> +}
> +
> int xc_get_cpufreq_avgfreq(xc_interface *xch, int cpuid, int *avg_freq)
> {
> int ret = 0;
> diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c
> index 120e9eae22..bdc09f468a 100644
> --- a/tools/misc/xenpm.c
> +++ b/tools/misc/xenpm.c
> @@ -69,6 +69,7 @@ void show_help(void)
> " set-max-cstate <num>|'unlimited' [<num2>|'unlimited']\n"
> " set the C-State limitation (<num> >= 0) and\n"
> " optionally the C-sub-state limitation (<num2> >= 0)\n"
> + " get-cpufreq-cppc [cpuid] list cpu cppc parameter of CPU <cpuid> or all\n"
> " set-cpufreq-cppc [cpuid] [balance|performance|powersave] <param:val>*\n"
> " set Hardware P-State (HWP) parameters\n"
> " on CPU <cpuid> or all if omitted.\n"
> @@ -996,6 +997,51 @@ void cpufreq_para_func(int argc, char *argv[])
> show_cpufreq_para_by_cpuid(xc_handle, cpuid);
> }
>
> +/* show cpu cppc parameters information on CPU cpuid */
> +static int show_cppc_para_by_cpuid(xc_interface *xc_handle, unsigned int cpuid)
> +{
> + int ret;
> + xc_cppc_para_t cppc_para;
> +
> + ret = xc_get_cppc_para(xc_handle, cpuid, &cppc_para);
> + if ( !ret )
> + {
> + printf("cpu id : %d\n", cpuid);
> + print_cppc_para(cpuid, &cppc_para);
> + printf("\n");
> + }
> + else if ( errno == ENODEV )
> + {
> + ret = -ENODEV;
> + fprintf(stderr, "CPPC is not available!\n");
> + }
> + else
> + fprintf(stderr, "[CPU%u] failed to get cppc parameter\n", cpuid);
> +
> + return ret;
> +}
> +
> +static void cppc_para_func(int argc, char *argv[])
> +{
> + int cpuid = -1;
> +
> + if ( argc > 0 )
> + parse_cpuid(argv[0], &cpuid);
> +
> + if ( cpuid < 0 )
> + {
> + unsigned int i;
> +
> + /* show cpu cppc information on all cpus */
> + for ( i = 0; i < max_cpu_nr; i++ )
> + /* Bail out only on unsupported platform */
> + if ( show_cppc_para_by_cpuid(xc_handle, i) == -ENODEV )
> + break;
> + }
> + else
> + show_cppc_para_by_cpuid(xc_handle, cpuid);
> +}
> +
> void scaling_max_freq_func(int argc, char *argv[])
> {
> int cpuid = -1, freq = -1;
> @@ -1576,6 +1622,7 @@ struct {
> { "get-cpufreq-average", cpufreq_func },
> { "start", start_gather_func },
> { "get-cpufreq-para", cpufreq_para_func },
> + { "get-cpufreq-cppc", cppc_para_func },
Didn't Jason also suggest that we would better not introduce a new command, but
rather make get-cpufreq-para invoke GET_CPUFREQ_CPPC as needed? Considering that
as per patch 15 the same information is already printed, I think I'm a little
lost with the need for this separate operation (and command), and then also with
the need for patch 15.
Jan
On 2025-07-24 09:31, Jan Beulich wrote:
> On 11.07.2025 05:51, Penny Zheng wrote:
>> In amd-cppc passive mode, it's Xen governor which is responsible for
>> performance tuning, so governor and CPPC could co-exist. That is, both
>> governor-info and CPPC-info need to be printed together via xenpm tool.
>>
>> If we tried to still put it in "struct xen_get_cpufreq_para" (e.g. just move
>> out of union), "struct xen_get_cpufreq_para" will enlarge too much to further
>> make xen_sysctl.u exceed 128 bytes.
>> So we introduce a new sub-op GET_CPUFREQ_CPPC to specifically print
>> CPPC-related para.
>>
>> Signed-off-by: Penny Zheng <Penny.Zheng@amd.com>
>> void scaling_max_freq_func(int argc, char *argv[])
>> {
>> int cpuid = -1, freq = -1;
>> @@ -1576,6 +1622,7 @@ struct {
>> { "get-cpufreq-average", cpufreq_func },
>> { "start", start_gather_func },
>> { "get-cpufreq-para", cpufreq_para_func },
>> + { "get-cpufreq-cppc", cppc_para_func },
>
> Didn't Jason also suggest that we would better not introduce a new command, but
> rather make get-cpufreq-para invoke GET_CPUFREQ_CPPC as needed? Considering that
> as per patch 15 the same information is already printed, I think I'm a little
> lost with the need for this separate operation (and command), and then also with
> the need for patch 15.
Yes, but I thought I was repeating your suggestion, Jan :)
xenpm's show_cpufreq_para_by_cpuid() would do something like:
show_cpufreq_para_by_cpuid() {
xc_get_cpufreq_para()
hw_auto = HWP || CPPC
if ( hw_auto ) {
xc_get_cppc_para()
print_cppc_para()
} else
print_cpufreq_para()
}
Would that work?
That way the single `xenpm get-cpufreq-para` would return the current
cpufreq data without the user needed to know what is running.
Regards,
Jason
[Public]
> -----Original Message-----
> From: Jason Andryuk <jason.andryuk@amd.com>
> Sent: Thursday, July 24, 2025 10:17 PM
> To: Jan Beulich <jbeulich@suse.com>; Penny, Zheng <penny.zheng@amd.com>
> Cc: Huang, Ray <Ray.Huang@amd.com>; Anthony PERARD
> <anthony.perard@vates.tech>; Juergen Gross <jgross@suse.com>; Andrew
> Cooper <andrew.cooper3@citrix.com>; Orzel, Michal <Michal.Orzel@amd.com>;
> Julien Grall <julien@xen.org>; Roger Pau Monné <roger.pau@citrix.com>;
> Stefano Stabellini <sstabellini@kernel.org>; xen-devel@lists.xenproject.org
> Subject: Re: [PATCH v6 16/19] xen/cpufreq: introduce GET_CPUFREQ_CPPC
> sub-op
>
> On 2025-07-24 09:31, Jan Beulich wrote:
> > On 11.07.2025 05:51, Penny Zheng wrote:
> >> In amd-cppc passive mode, it's Xen governor which is responsible for
> >> performance tuning, so governor and CPPC could co-exist. That is,
> >> both governor-info and CPPC-info need to be printed together via xenpm tool.
> >>
> >> If we tried to still put it in "struct xen_get_cpufreq_para" (e.g.
> >> just move out of union), "struct xen_get_cpufreq_para" will enlarge
> >> too much to further make xen_sysctl.u exceed 128 bytes.
> >> So we introduce a new sub-op GET_CPUFREQ_CPPC to specifically print
> >> CPPC-related para.
> >>
> >> Signed-off-by: Penny Zheng <Penny.Zheng@amd.com>
>
> >> void scaling_max_freq_func(int argc, char *argv[])
> >> {
> >> int cpuid = -1, freq = -1;
> >> @@ -1576,6 +1622,7 @@ struct {
> >> { "get-cpufreq-average", cpufreq_func },
> >> { "start", start_gather_func },
> >> { "get-cpufreq-para", cpufreq_para_func },
> >> + { "get-cpufreq-cppc", cppc_para_func },
> >
> > Didn't Jason also suggest that we would better not introduce a new
> > command, but rather make get-cpufreq-para invoke GET_CPUFREQ_CPPC as
> > needed? Considering that as per patch 15 the same information is
> > already printed, I think I'm a little lost with the need for this
> > separate operation (and command), and then also with the need for patch 15.
>
> Yes, but I thought I was repeating your suggestion, Jan :)
>
> xenpm's show_cpufreq_para_by_cpuid() would do something like:
>
> show_cpufreq_para_by_cpuid() {
> xc_get_cpufreq_para()
> hw_auto = HWP || CPPC
> if ( hw_auto ) {
> xc_get_cppc_para()
> print_cppc_para()
> } else
> print_cpufreq_para()
> }
>
> Would that work?
>
Understood, I will re-write as you suggests, thx
> That way the single `xenpm get-cpufreq-para` would return the current cpufreq
> data without the user needed to know what is running.
>
> Regards,
> Jason
On 24.07.2025 16:17, Jason Andryuk wrote:
> On 2025-07-24 09:31, Jan Beulich wrote:
>> On 11.07.2025 05:51, Penny Zheng wrote:
>>> In amd-cppc passive mode, it's Xen governor which is responsible for
>>> performance tuning, so governor and CPPC could co-exist. That is, both
>>> governor-info and CPPC-info need to be printed together via xenpm tool.
>>>
>>> If we tried to still put it in "struct xen_get_cpufreq_para" (e.g. just move
>>> out of union), "struct xen_get_cpufreq_para" will enlarge too much to further
>>> make xen_sysctl.u exceed 128 bytes.
>>> So we introduce a new sub-op GET_CPUFREQ_CPPC to specifically print
>>> CPPC-related para.
>>>
>>> Signed-off-by: Penny Zheng <Penny.Zheng@amd.com>
>
>>> void scaling_max_freq_func(int argc, char *argv[])
>>> {
>>> int cpuid = -1, freq = -1;
>>> @@ -1576,6 +1622,7 @@ struct {
>>> { "get-cpufreq-average", cpufreq_func },
>>> { "start", start_gather_func },
>>> { "get-cpufreq-para", cpufreq_para_func },
>>> + { "get-cpufreq-cppc", cppc_para_func },
>>
>> Didn't Jason also suggest that we would better not introduce a new command, but
>> rather make get-cpufreq-para invoke GET_CPUFREQ_CPPC as needed? Considering that
>> as per patch 15 the same information is already printed, I think I'm a little
>> lost with the need for this separate operation (and command), and then also with
>> the need for patch 15.
>
> Yes, but I thought I was repeating your suggestion, Jan :)
That's what I tried to express using "also" ;-)
Jan
© 2016 - 2025 Red Hat, Inc.