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);
 
