_PSD(P-State Dependency) provides performance control, no matter legacy
P-state or CPPC, logical processor dependency information to OSPM.
In order to re-use it for CPPC, this commit extracts the delivery of _PSD info
from set_px_pminfo() and wrap it with a new sub-hypercall XEN_PM_PSD.
Signed-off-by: Penny Zheng <Penny.Zheng@amd.com>
---
v2 -> v3:
- new commit
---
xen/arch/x86/acpi/cpufreq/acpi.c | 2 +-
xen/arch/x86/acpi/cpufreq/powernow.c | 2 +-
xen/arch/x86/platform_hypercall.c | 11 ++
xen/arch/x86/x86_64/cpufreq.c | 2 +
xen/drivers/cpufreq/cpufreq.c | 122 +++++++++++++---------
xen/drivers/cpufreq/cpufreq_ondemand.c | 2 +-
xen/include/acpi/cpufreq/processor_perf.h | 4 +-
xen/include/public/platform.h | 17 +--
xen/include/xen/pmstat.h | 2 +
xen/include/xlat.lst | 2 +-
10 files changed, 103 insertions(+), 63 deletions(-)
diff --git a/xen/arch/x86/acpi/cpufreq/acpi.c b/xen/arch/x86/acpi/cpufreq/acpi.c
index 0c25376406..0cf94ab2d6 100644
--- a/xen/arch/x86/acpi/cpufreq/acpi.c
+++ b/xen/arch/x86/acpi/cpufreq/acpi.c
@@ -393,7 +393,7 @@ static int cf_check acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
data->acpi_data = &processor_pminfo[cpu]->perf;
perf = data->acpi_data;
- policy->shared_type = perf->shared_type;
+ policy->shared_type = processor_pminfo[cpu]->shared_type;
switch (perf->control_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
diff --git a/xen/arch/x86/acpi/cpufreq/powernow.c b/xen/arch/x86/acpi/cpufreq/powernow.c
index 69364e1855..69ad403fc1 100644
--- a/xen/arch/x86/acpi/cpufreq/powernow.c
+++ b/xen/arch/x86/acpi/cpufreq/powernow.c
@@ -218,7 +218,7 @@ static int cf_check powernow_cpufreq_cpu_init(struct cpufreq_policy *policy)
data->acpi_data = &processor_pminfo[cpu]->perf;
info.perf = perf = data->acpi_data;
- policy->shared_type = perf->shared_type;
+ policy->shared_type = processor_pminfo[cpu]->shared_type;
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index 90abd3197f..b0d98b5840 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -571,6 +571,17 @@ ret_t do_platform_op(
ret = acpi_set_pdc_bits(op->u.set_pminfo.id, pdc);
break;
}
+ case XEN_PM_PSD:
+ if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) )
+ {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ ret = set_psd_pminfo(op->u.set_pminfo.id,
+ op->u.set_pminfo.shared_type,
+ &op->u.set_pminfo.u.domain_info);
+ break;
default:
ret = -EINVAL;
diff --git a/xen/arch/x86/x86_64/cpufreq.c b/xen/arch/x86/x86_64/cpufreq.c
index e4f3d5b436..d1b93b8eef 100644
--- a/xen/arch/x86/x86_64/cpufreq.c
+++ b/xen/arch/x86/x86_64/cpufreq.c
@@ -28,6 +28,8 @@
CHECK_processor_px;
+CHECK_psd_package;
+
DEFINE_XEN_GUEST_HANDLE(compat_processor_px_t);
int compat_set_px_pminfo(uint32_t acpi_id,
diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c
index 4a103c6de9..638476ca15 100644
--- a/xen/drivers/cpufreq/cpufreq.c
+++ b/xen/drivers/cpufreq/cpufreq.c
@@ -36,6 +36,7 @@
#include <xen/string.h>
#include <xen/timer.h>
#include <xen/xmalloc.h>
+#include <xen/xvmalloc.h>
#include <xen/guest_access.h>
#include <xen/domain.h>
#include <xen/cpu.h>
@@ -201,15 +202,15 @@ int cpufreq_add_cpu(unsigned int cpu)
struct cpufreq_dom *cpufreq_dom = NULL;
struct cpufreq_policy new_policy;
struct cpufreq_policy *policy;
- struct processor_performance *perf;
+ struct processor_pminfo *pmpt;
/* to protect the case when Px was not controlled by xen */
if ( !processor_pminfo[cpu] || !cpu_online(cpu) )
return -EINVAL;
- perf = &processor_pminfo[cpu]->perf;
+ pmpt = processor_pminfo[cpu];
- if ( !(perf->init & XEN_PX_INIT) )
+ if ( !(pmpt->perf.init & XEN_PX_INIT) )
return -EINVAL;
if (!cpufreq_driver.init)
@@ -218,10 +219,10 @@ int cpufreq_add_cpu(unsigned int cpu)
if (per_cpu(cpufreq_cpu_policy, cpu))
return 0;
- if (perf->shared_type == CPUFREQ_SHARED_TYPE_HW)
+ if (pmpt->shared_type == CPUFREQ_SHARED_TYPE_HW)
hw_all = 1;
- dom = perf->domain_info.domain;
+ dom = pmpt->domain_info.domain;
list_for_each(pos, &cpufreq_dom_list_head) {
cpufreq_dom = list_entry(pos, struct cpufreq_dom, node);
@@ -246,18 +247,18 @@ int cpufreq_add_cpu(unsigned int cpu)
} else {
/* domain sanity check under whatever coordination type */
firstcpu = cpumask_first(cpufreq_dom->map);
- if ((perf->domain_info.coord_type !=
- processor_pminfo[firstcpu]->perf.domain_info.coord_type) ||
- (perf->domain_info.num_processors !=
- processor_pminfo[firstcpu]->perf.domain_info.num_processors)) {
+ if ((pmpt->domain_info.coord_type !=
+ processor_pminfo[firstcpu]->domain_info.coord_type) ||
+ (pmpt->domain_info.num_processors !=
+ processor_pminfo[firstcpu]->domain_info.num_processors)) {
printk(KERN_WARNING "cpufreq fail to add CPU%d:"
"incorrect _PSD(%"PRIu64":%"PRIu64"), "
"expect(%"PRIu64"/%"PRIu64")\n",
- cpu, perf->domain_info.coord_type,
- perf->domain_info.num_processors,
- processor_pminfo[firstcpu]->perf.domain_info.coord_type,
- processor_pminfo[firstcpu]->perf.domain_info.num_processors
+ cpu, pmpt->domain_info.coord_type,
+ pmpt->domain_info.num_processors,
+ processor_pminfo[firstcpu]->domain_info.coord_type,
+ processor_pminfo[firstcpu]->domain_info.num_processors
);
return -EINVAL;
}
@@ -305,7 +306,7 @@ int cpufreq_add_cpu(unsigned int cpu)
goto err1;
if (hw_all || (cpumask_weight(cpufreq_dom->map) ==
- perf->domain_info.num_processors)) {
+ pmpt->domain_info.num_processors)) {
memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
policy->governor = NULL;
@@ -359,24 +360,24 @@ int cpufreq_del_cpu(unsigned int cpu)
struct list_head *pos;
struct cpufreq_dom *cpufreq_dom = NULL;
struct cpufreq_policy *policy;
- struct processor_performance *perf;
+ struct processor_pminfo *pmpt;
/* to protect the case when Px was not controlled by xen */
if ( !processor_pminfo[cpu] || !cpu_online(cpu) )
return -EINVAL;
- perf = &processor_pminfo[cpu]->perf;
+ pmpt = processor_pminfo[cpu];
- if ( !(perf->init & XEN_PX_INIT) )
+ if ( !(pmpt->perf.init & XEN_PX_INIT) )
return -EINVAL;
if (!per_cpu(cpufreq_cpu_policy, cpu))
return 0;
- if (perf->shared_type == CPUFREQ_SHARED_TYPE_HW)
+ if (pmpt->shared_type == CPUFREQ_SHARED_TYPE_HW)
hw_all = 1;
- dom = perf->domain_info.domain;
+ dom = pmpt->domain_info.domain;
policy = per_cpu(cpufreq_cpu_policy, cpu);
list_for_each(pos, &cpufreq_dom_list_head) {
@@ -393,7 +394,7 @@ int cpufreq_del_cpu(unsigned int cpu)
/* for HW_ALL, stop gov for each core of the _PSD domain */
/* for SW_ALL & SW_ANY, stop gov for the 1st core of the _PSD domain */
if (hw_all || (cpumask_weight(cpufreq_dom->map) ==
- perf->domain_info.num_processors))
+ pmpt->domain_info.num_processors))
__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
cpufreq_statistic_exit(cpu);
@@ -475,19 +476,13 @@ int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf)
acpi_id, cpu);
pmpt = processor_pminfo[cpu];
+ /* Must already allocated in set_psd_pminfo */
if ( !pmpt )
{
- pmpt = xzalloc(struct processor_pminfo);
- if ( !pmpt )
- {
- ret = -ENOMEM;
- goto out;
- }
- processor_pminfo[cpu] = pmpt;
+ ret = -EINVAL;
+ goto out;
}
pxpt = &pmpt->perf;
- pmpt->acpi_id = acpi_id;
- pmpt->id = cpu;
if ( perf->flags & XEN_PX_PCT )
{
@@ -537,25 +532,6 @@ int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf)
print_PSS(pxpt->states,pxpt->state_count);
}
- if ( perf->flags & XEN_PX_PSD )
- {
- /* check domain coordination */
- if ( perf->shared_type != CPUFREQ_SHARED_TYPE_ALL &&
- perf->shared_type != CPUFREQ_SHARED_TYPE_ANY &&
- perf->shared_type != CPUFREQ_SHARED_TYPE_HW )
- {
- ret = -EINVAL;
- goto out;
- }
-
- pxpt->shared_type = perf->shared_type;
- memcpy(&pxpt->domain_info, &perf->domain_info,
- sizeof(struct xen_psd_package));
-
- if ( cpufreq_verbose )
- print_PSD(&pxpt->domain_info);
- }
-
if ( perf->flags & XEN_PX_PPC )
{
pxpt->platform_limit = perf->platform_limit;
@@ -570,7 +546,7 @@ int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf)
}
}
- if ( perf->flags == ( XEN_PX_PCT | XEN_PX_PSS | XEN_PX_PSD | XEN_PX_PPC ) )
+ if ( perf->flags == ( XEN_PX_PCT | XEN_PX_PSS | XEN_PX_PPC ) )
{
pxpt->init = XEN_PX_INIT;
@@ -582,6 +558,54 @@ out:
return ret;
}
+int set_psd_pminfo(uint32_t acpi_id, uint32_t shared_type,
+ const struct xen_psd_package *psd_data)
+{
+ int ret = 0, cpuid;
+ struct processor_pminfo *pm_info;
+
+ cpuid = get_cpu_id(acpi_id);
+ if ( cpuid < 0 || !psd_data )
+ {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* check domain coordination */
+ if ( shared_type != CPUFREQ_SHARED_TYPE_ALL &&
+ shared_type != CPUFREQ_SHARED_TYPE_ANY &&
+ shared_type != CPUFREQ_SHARED_TYPE_HW )
+ {
+ ret = -EINVAL;
+ goto out;
+ }
+ if ( cpufreq_verbose )
+ printk("Set CPU acpi_id(%d) cpuid(%d) _PSD 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->shared_type = shared_type;
+ pm_info->domain_info = *psd_data;
+
+ if ( cpufreq_verbose )
+ print_PSD(&pm_info->domain_info);
+
+ out:
+ return ret;
+}
+
static void cpufreq_cmdline_common_para(struct cpufreq_policy *new_policy)
{
if (usr_max_freq)
diff --git a/xen/drivers/cpufreq/cpufreq_ondemand.c b/xen/drivers/cpufreq/cpufreq_ondemand.c
index 06cfc88d30..5b23daaac1 100644
--- a/xen/drivers/cpufreq/cpufreq_ondemand.c
+++ b/xen/drivers/cpufreq/cpufreq_ondemand.c
@@ -194,7 +194,7 @@ static void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
set_timer(&per_cpu(dbs_timer, dbs_info->cpu), NOW()+dbs_tuners_ins.sampling_rate);
- if ( processor_pminfo[dbs_info->cpu]->perf.shared_type
+ if ( processor_pminfo[dbs_info->cpu]->shared_type
== CPUFREQ_SHARED_TYPE_HW )
{
dbs_info->stoppable = 1;
diff --git a/xen/include/acpi/cpufreq/processor_perf.h b/xen/include/acpi/cpufreq/processor_perf.h
index 301104e16f..19f5de6b08 100644
--- a/xen/include/acpi/cpufreq/processor_perf.h
+++ b/xen/include/acpi/cpufreq/processor_perf.h
@@ -27,8 +27,6 @@ struct processor_performance {
struct xen_pct_register status_register;
uint32_t state_count;
struct xen_processor_px *states;
- struct xen_psd_package domain_info;
- uint32_t shared_type;
uint32_t init;
};
@@ -36,6 +34,8 @@ struct processor_performance {
struct processor_pminfo {
uint32_t acpi_id;
uint32_t id;
+ struct xen_psd_package domain_info;
+ uint32_t shared_type;
struct processor_performance perf;
};
diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h
index 2725b8d104..f5c50380cb 100644
--- a/xen/include/public/platform.h
+++ b/xen/include/public/platform.h
@@ -363,12 +363,12 @@ 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_PSD 4
/* Px sub info type */
#define XEN_PX_PCT 1
#define XEN_PX_PSS 2
#define XEN_PX_PPC 4
-#define XEN_PX_PSD 8
struct xen_power_register {
uint32_t space_id;
@@ -439,6 +439,7 @@ struct xen_psd_package {
uint64_t coord_type;
uint64_t num_processors;
};
+typedef struct xen_psd_package xen_psd_package_t;
struct xen_processor_performance {
uint32_t flags; /* flag for Px sub info type */
@@ -447,12 +448,6 @@ struct xen_processor_performance {
struct xen_pct_register status_register;
uint32_t state_count; /* total available performance states */
XEN_GUEST_HANDLE(xen_processor_px_t) states;
- struct xen_psd_package domain_info;
- /* 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 */
- uint32_t shared_type;
};
typedef struct xen_processor_performance xen_processor_performance_t;
DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t);
@@ -463,9 +458,15 @@ struct xenpf_set_processor_pminfo {
uint32_t type; /* {XEN_PM_CX, XEN_PM_PX} */
union {
struct xen_processor_power power;/* Cx: _CST/_CSD */
- struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */
+ xen_psd_package_t domain_info; /* _PSD */
+ struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/ */
XEN_GUEST_HANDLE(uint32) pdc; /* _PDC */
} u;
+ /* 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 */
+ uint32_t shared_type;
};
typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
diff --git a/xen/include/xen/pmstat.h b/xen/include/xen/pmstat.h
index 8350403e95..fd02316ce9 100644
--- a/xen/include/xen/pmstat.h
+++ b/xen/include/xen/pmstat.h
@@ -5,6 +5,8 @@
#include <public/platform.h> /* for struct xen_processor_power */
#include <public/sysctl.h> /* for struct pm_cx_stat */
+int set_psd_pminfo(uint32_t acpi_id, uint32_t shared_type,
+ const struct xen_psd_package *psd_data);
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);
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index 3c7b6c6830..0d964fe0ce 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -168,7 +168,7 @@
! processor_performance platform.h
! processor_power platform.h
? processor_px platform.h
-! psd_package platform.h
+? psd_package platform.h
? xenpf_enter_acpi_sleep platform.h
? xenpf_pcpu_version platform.h
? xenpf_pcpuinfo platform.h
--
2.34.1
© 2016 - 2025 Red Hat, Inc.