[PATCH v3 01/15] xen/cpufreq: introduces XEN_PM_PSD for solely delivery of _PSD

Penny Zheng posted 15 patches 3 days, 13 hours ago
[PATCH v3 01/15] xen/cpufreq: introduces XEN_PM_PSD for solely delivery of _PSD
Posted by Penny Zheng 3 days, 13 hours ago
_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