[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH][pvops_dom0][3/4] Xen implementation of the external control operation interface



Xen implementation of the external control operation interface

From: Yu Ke <ke.yu@xxxxxxxxx>

This patch implements the Xen version of the external control operation 
interface.

Signed-off-by: Yu Ke <ke.yu@xxxxxxxxx>
Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx>
---

 drivers/xen/Kconfig             |    5 +
 drivers/xen/Makefile            |    1 
 drivers/xen/processor_extcntl.c |  246 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 252 insertions(+), 0 deletions(-)
 create mode 100644 drivers/xen/processor_extcntl.c


diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index d1b2642..c0370b6 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -98,3 +98,8 @@ config XEN_GNTDEV
 config XEN_S3
        def_bool y
        depends on XEN_DOM0 && ACPI
+
+config XEN_PROCESSOR_EXTERNAL_CONTROL
+       def_bool y
+       depends on XEN_DOM0 && PROCESSOR_EXTERNAL_CONTROL
+
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index e680033..3a1a54b 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_NETDEV_BACKEND)      += netback/
 obj-$(CONFIG_XENFS)                    += xenfs/
 obj-$(CONFIG_XEN_SYS_HYPERVISOR)       += sys-hypervisor.o
 obj-$(CONFIG_XEN_S3)                   += acpi.o
+obj-$(CONFIG_XEN_PROCESSOR_EXTERNAL_CONTROL) += processor_extcntl.o
diff --git a/drivers/xen/processor_extcntl.c b/drivers/xen/processor_extcntl.c
new file mode 100644
index 0000000..b5b5d62
--- /dev/null
+++ b/drivers/xen/processor_extcntl.c
@@ -0,0 +1,246 @@
+/*
+ * processor_extcntl.c - interface to notify Xen
+ *
+ *  Copyright (C) 2008, Intel corporation
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include <linux/pm.h>
+#include <linux/cpu.h>
+
+#include <linux/cpufreq.h>
+#include <acpi/processor.h>
+#include <xen/acpi.h>
+
+#include <asm/xen/hypercall.h>
+#include <asm/xen/hypervisor.h>
+
+static inline void xen_convert_pct_reg(struct xen_pct_register *xpct,
+       struct acpi_pct_register *apct)
+{
+       xpct->descriptor = apct->descriptor;
+       xpct->length     = apct->length;
+       xpct->space_id   = apct->space_id;
+       xpct->bit_width  = apct->bit_width;
+       xpct->bit_offset = apct->bit_offset;
+       xpct->reserved   = apct->reserved;
+       xpct->address    = apct->address;
+}
+
+static inline void xen_convert_pss_states(struct xen_processor_px *xpss,
+       struct acpi_processor_px *apss, int state_count)
+{
+       int i;
+       for(i=0; i<state_count; i++) {
+               xpss->core_frequency     = apss->core_frequency;
+               xpss->power              = apss->power;
+               xpss->transition_latency = apss->transition_latency;
+               xpss->bus_master_latency = apss->bus_master_latency;
+               xpss->control            = apss->control;
+               xpss->status             = apss->status;
+               xpss++;
+               apss++;
+       }
+}
+
+static inline void xen_convert_psd_pack(struct xen_psd_package *xpsd,
+       struct acpi_psd_package *apsd)
+{
+       xpsd->num_entries    = apsd->num_entries;
+       xpsd->revision       = apsd->revision;
+       xpsd->domain         = apsd->domain;
+       xpsd->coord_type     = apsd->coord_type;
+       xpsd->num_processors = apsd->num_processors;
+}
+
+static int xen_cx_notifier(struct acpi_processor *pr, int action)
+{
+       int ret, count = 0, i;
+       xen_platform_op_t op = {
+               .cmd                    = XENPF_set_processor_pminfo,
+               .interface_version      = XENPF_INTERFACE_VERSION,
+               .u.set_pminfo.id        = pr->acpi_id,
+               .u.set_pminfo.type      = XEN_PM_CX,
+       };
+       struct xen_processor_cx *data, *buf;
+       struct acpi_processor_cx *cx;
+
+       if (action == PROCESSOR_PM_CHANGE)
+               return -EINVAL;
+
+       /* Convert to Xen defined structure and hypercall */
+       buf = kzalloc(pr->power.count * sizeof(struct xen_processor_cx),
+                       GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       data = buf;
+       for (i = 1; i <= pr->power.count; i++) {
+               cx = &pr->power.states[i];
+               /* Skip invalid cstate entry */
+               if (!cx->valid)
+                       continue;
+
+               data->type = cx->type;
+               data->latency = cx->latency;
+               data->power = cx->power;
+               data->reg.space_id = cx->reg.space_id;
+               data->reg.bit_width = cx->reg.bit_width;
+               data->reg.bit_offset = cx->reg.bit_offset;
+               data->reg.access_size = cx->reg.reserved;
+               data->reg.address = cx->reg.address;
+
+               /* Get dependency relationships, _CSD is not supported yet */
+               data->dpcnt = 0;
+               set_xen_guest_handle(data->dp, NULL);
+
+               data++;
+               count++;
+       }
+
+       if (!count) {
+               printk("No available Cx info for cpu %d\n", pr->acpi_id);
+               kfree(buf);
+               return -EINVAL;
+       }
+
+       op.u.set_pminfo.power.count = count;
+       op.u.set_pminfo.power.flags.bm_control = pr->flags.bm_control;
+       op.u.set_pminfo.power.flags.bm_check = pr->flags.bm_check;
+       op.u.set_pminfo.power.flags.has_cst = pr->flags.has_cst;
+       op.u.set_pminfo.power.flags.power_setup_done = 
pr->flags.power_setup_done;
+
+       set_xen_guest_handle(op.u.set_pminfo.power.states, buf);
+       ret = HYPERVISOR_dom0_op(&op);
+       kfree(buf);
+       return ret;
+}
+
+static int xen_px_notifier(struct acpi_processor *pr, int action)
+{
+       int ret = -EINVAL;
+       xen_platform_op_t op = {
+               .cmd                    = XENPF_set_processor_pminfo,
+               .interface_version      = XENPF_INTERFACE_VERSION,
+               .u.set_pminfo.id        = pr->acpi_id,
+               .u.set_pminfo.type      = XEN_PM_PX,
+       };
+       struct xen_processor_performance *perf;
+       struct xen_processor_px *states = NULL;
+       struct acpi_processor_performance *px;
+       struct acpi_psd_package *pdomain;
+
+       if (!pr)
+               return -EINVAL;
+
+       perf = &op.u.set_pminfo.perf;
+       px = pr->performance;
+
+       switch(action) {
+       case PROCESSOR_PM_CHANGE:
+               /* ppc dynamic handle */
+               perf->flags = XEN_PX_PPC;
+               perf->platform_limit = pr->performance_platform_limit;
+
+               ret = HYPERVISOR_dom0_op(&op);
+               break;
+
+       case PROCESSOR_PM_INIT:
+               /* px normal init */
+               perf->flags = XEN_PX_PPC |
+                             XEN_PX_PCT |
+                             XEN_PX_PSS |
+                             XEN_PX_PSD;
+
+               /* ppc */
+               perf->platform_limit = pr->performance_platform_limit;
+
+               /* pct */
+               xen_convert_pct_reg(&perf->control_register, 
&px->control_register);
+               xen_convert_pct_reg(&perf->status_register, 
&px->status_register);
+
+               /* pss */
+               perf->state_count = px->state_count;
+               states = 
kzalloc(px->state_count*sizeof(xen_processor_px_t),GFP_KERNEL);
+               if (!states)
+                       return -ENOMEM;
+               xen_convert_pss_states(states, px->states, px->state_count);
+               set_xen_guest_handle(perf->states, states);
+
+               /* psd */
+               pdomain = &px->domain_info;
+               xen_convert_psd_pack(&perf->domain_info, pdomain);
+               if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
+                       perf->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+               else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
+                       perf->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+               else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
+                       perf->shared_type = CPUFREQ_SHARED_TYPE_HW;
+               else {
+                       ret = -ENODEV;
+                       kfree(states);
+                       break;
+               }
+
+               ret = HYPERVISOR_dom0_op(&op);
+               kfree(states);
+               break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static int xen_tx_notifier(struct acpi_processor *pr, int action)
+{
+       return -EINVAL;
+}
+static int xen_hotplug_notifier(struct acpi_processor *pr, int event)
+{
+       return -EINVAL;
+}
+
+static struct processor_extcntl_ops xen_extcntl_ops = {
+       .hotplug                = xen_hotplug_notifier,
+};
+
+static int __init xen_acpi_processor_extcntl_init(void)
+{
+       unsigned int pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8;
+
+       if (!pmbits)
+               return 0;
+       if (pmbits & XEN_PROCESSOR_PM_CX)
+               xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
+       if (pmbits & XEN_PROCESSOR_PM_PX)
+               xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
+       if (pmbits & XEN_PROCESSOR_PM_TX)
+               xen_extcntl_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier;
+
+       processor_extcntl_register(&xen_extcntl_ops);
+       return 0;
+}
+
+subsys_initcall(xen_acpi_processor_extcntl_init);

Attachment: external-control-xen.patch
Description: external-control-xen.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.