[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250306110824.1506699-3-Penny.Zheng@amd.com>
Date: Thu, 6 Mar 2025 19:08:21 +0800
From: Penny Zheng <Penny.Zheng@....com>
To: <jbeulich@...e.com>, Juergen Gross <jgross@...e.com>, Stefano Stabellini
<sstabellini@...nel.org>, Oleksandr Tyshchenko
<oleksandr_tyshchenko@...m.com>
CC: Ray Huang <Ray.Huang@....com>, Jason Andryuk <jason.andryuk@....com>,
Penny Zheng <Penny.Zheng@....com>, <xen-devel@...ts.xenproject.org>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH v3 2/5] xen: introduces XEN_PM_PSD sub-hypercall for solely delivery of _PSD info
_PSD(P-State Dependency) provides performance control, no matter legacy
P-state or CPPC, logical processor dependency information.
In order to re-use it for CPPC, this commit extracts the delivery of _PSD
info from push_pxx_to_hypervisor() and wrap it with a new sub-hypercall
XEN_PM_PSD.
Signed-off-by: Penny Zheng <Penny.Zheng@....com>
---
v2 -> v3:
- new commit
---
drivers/xen/xen-acpi-processor.c | 82 ++++++++++++++++++++------------
include/xen/interface/platform.h | 8 ++--
2 files changed, 56 insertions(+), 34 deletions(-)
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index e9f38f171240..8db8631a4b9d 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -157,18 +157,40 @@ xen_copy_pss_data(struct acpi_processor *_pr,
}
return dst_states;
}
-static int xen_copy_psd_data(struct acpi_processor *_pr,
- struct xen_processor_performance *dst)
+static int xen_copy_pct_data(struct acpi_pct_register *pct,
+ struct xen_pct_register *dst_pct)
+{
+ /* It would be nice if you could just do 'memcpy(pct, dst_pct') but
+ * sadly the Xen structure did not have the proper padding so the
+ * descriptor field takes two (dst_pct) bytes instead of one (pct).
+ */
+ dst_pct->descriptor = pct->descriptor;
+ dst_pct->length = pct->length;
+ dst_pct->space_id = pct->space_id;
+ dst_pct->bit_width = pct->bit_width;
+ dst_pct->bit_offset = pct->bit_offset;
+ dst_pct->reserved = pct->reserved;
+ dst_pct->address = pct->address;
+ return 0;
+}
+static int push_psd_to_hypervisor(struct acpi_processor *_pr)
{
+ struct xen_platform_op op = {
+ .cmd = XENPF_set_processor_pminfo,
+ .interface_version = XENPF_INTERFACE_VERSION,
+ .u.set_pminfo.id = _pr->acpi_id,
+ .u.set_pminfo.type = XEN_PM_PSD,
+ };
struct acpi_psd_package *pdomain;
+ int ret = 0;
BUILD_BUG_ON(sizeof(struct xen_psd_package) !=
sizeof(struct acpi_psd_package));
- /* This information is enumerated only if acpi_processor_preregister_performance
- * has been called.
+ /* This information is enumerated only if
+ * acpi_processor_preregister_performance has been called.
*/
- dst->shared_type = _pr->performance->shared_type;
+ op.u.set_pminfo.shared_type = _pr->performance->shared_type;
pdomain = &(_pr->performance->domain_info);
@@ -180,32 +202,30 @@ static int xen_copy_psd_data(struct acpi_processor *_pr,
* running as a PVH dom0.
*/
if (pdomain->num_processors <= 1 ||
- dst->shared_type == CPUFREQ_SHARED_TYPE_NONE) {
+ op.u.set_pminfo.shared_type == CPUFREQ_SHARED_TYPE_NONE) {
if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
- dst->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+ op.u.set_pminfo.shared_type = CPUFREQ_SHARED_TYPE_ALL;
else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
- dst->shared_type = CPUFREQ_SHARED_TYPE_HW;
+ op.u.set_pminfo.shared_type = CPUFREQ_SHARED_TYPE_HW;
else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
- dst->shared_type = CPUFREQ_SHARED_TYPE_ANY;
-
+ op.u.set_pminfo.shared_type = CPUFREQ_SHARED_TYPE_ANY;
}
- memcpy(&(dst->domain_info), pdomain, sizeof(struct acpi_psd_package));
- return 0;
-}
-static int xen_copy_pct_data(struct acpi_pct_register *pct,
- struct xen_pct_register *dst_pct)
-{
- /* It would be nice if you could just do 'memcpy(pct, dst_pct') but
- * sadly the Xen structure did not have the proper padding so the
- * descriptor field takes two (dst_pct) bytes instead of one (pct).
- */
- dst_pct->descriptor = pct->descriptor;
- dst_pct->length = pct->length;
- dst_pct->space_id = pct->space_id;
- dst_pct->bit_width = pct->bit_width;
- dst_pct->bit_offset = pct->bit_offset;
- dst_pct->reserved = pct->reserved;
- dst_pct->address = pct->address;
+
+ memcpy(&(op.u.set_pminfo.domain_info), pdomain,
+ sizeof(struct acpi_psd_package));
+
+ if (!no_hypercall)
+ ret = HYPERVISOR_platform_op(&op);
+
+ if (!ret) {
+ pr_debug("ACPI CPU%u - _PSD uploaded.\n", _pr->acpi_id);
+ } else if ((ret != -EINVAL) && (ret != -ENOSYS))
+ /* EINVAL means the ACPI ID is incorrect - meaning the ACPI
+ * table is referencing a non-existing CPU - which can happen
+ * with broken ACPI tables. */
+ pr_warn("(_PSD): Hypervisor error (%d) for ACPI CPU%u\n",
+ ret, _pr->acpi_id);
+
return 0;
}
static int push_pxx_to_hypervisor(struct acpi_processor *_pr)
@@ -234,10 +254,8 @@ static int push_pxx_to_hypervisor(struct acpi_processor *_pr)
set_xen_guest_handle(dst_perf->states, dst_states);
dst_perf->flags |= XEN_PX_PSS;
}
- if (!xen_copy_psd_data(_pr, dst_perf))
- dst_perf->flags |= XEN_PX_PSD;
- if (dst_perf->flags != (XEN_PX_PSD | XEN_PX_PSS | XEN_PX_PCT | XEN_PX_PPC)) {
+ if (dst_perf->flags != (XEN_PX_PSS | XEN_PX_PCT | XEN_PX_PPC)) {
pr_warn("ACPI CPU%u missing some P-state data (%x), skipping\n",
_pr->acpi_id, dst_perf->flags);
ret = -ENODEV;
@@ -281,6 +299,10 @@ static int upload_pm_data(struct acpi_processor *_pr)
mutex_unlock(&acpi_ids_mutex);
return -EBUSY;
}
+
+ if (_pr->performance && _pr->performance->states)
+ err |= push_psd_to_hypervisor(_pr);
+
if (_pr->flags.power)
err = push_cxx_to_hypervisor(_pr);
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
index 79a443c65ea9..a35e1eb958f3 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -319,11 +319,11 @@ DEFINE_GUEST_HANDLE_STRUCT(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;
@@ -399,8 +399,6 @@ struct xen_processor_performance {
struct xen_pct_register status_register;
uint32_t state_count; /* total available performance states */
GUEST_HANDLE(xen_processor_px) states;
- struct xen_psd_package domain_info;
- uint32_t shared_type; /* coordination type of this processor */
};
DEFINE_GUEST_HANDLE_STRUCT(xen_processor_performance);
@@ -410,9 +408,11 @@ 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 */
+ struct xen_psd_package domain_info; /* _PSD */
+ struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS */
GUEST_HANDLE(uint32_t) pdc;
};
+ uint32_t shared_type; /* coordination type of this processor */
};
DEFINE_GUEST_HANDLE_STRUCT(xenpf_set_processor_pminfo);
--
2.34.1
Powered by blists - more mailing lists