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

[Xen-changelog] [linux-2.6.18-xen] Notify xen about Cx acpi info, such as table returned by _CST/_CSD methods.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1209635587 -3600
# Node ID e97855b90cc280e75c583cc6ac78d924f8cf16b8
# Parent  3c564f80f2ef2b458f9a81598c0928acb72cc891
Notify xen about Cx acpi info, such as table returned by _CST/_CSD methods.

Add notifiers for P/T & hotplug as placeholders.
Add option "xen_processor_pmbits" for enable/disable control.

Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx>
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>
---
 arch/i386/kernel/acpi/Makefile                |    1 
 arch/i386/kernel/acpi/processor_extcntl_xen.c |  142 ++++++++++++++++++++++++++
 arch/x86_64/kernel/acpi/Makefile              |    2 
 drivers/acpi/Kconfig                          |    1 
 drivers/acpi/processor_extcntl.c              |   26 ++++
 drivers/acpi/processor_idle.c                 |   22 +++-
 include/acpi/processor.h                      |   17 +++
 include/xen/interface/platform.h              |   73 +++++++++++++
 8 files changed, 279 insertions(+), 5 deletions(-)

diff -r 3c564f80f2ef -r e97855b90cc2 arch/i386/kernel/acpi/Makefile
--- a/arch/i386/kernel/acpi/Makefile    Thu May 01 10:52:31 2008 +0100
+++ b/arch/i386/kernel/acpi/Makefile    Thu May 01 10:53:07 2008 +0100
@@ -1,6 +1,7 @@ obj-$(CONFIG_ACPI)              += boot.o
 obj-$(CONFIG_ACPI)             += boot.o
 obj-$(CONFIG_X86_IO_APIC)      += earlyquirk.o
 obj-$(CONFIG_ACPI_SLEEP)       += sleep.o wakeup.o
+obj-$(CONFIG_XEN)              += processor_extcntl_xen.o
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
 obj-y                          += cstate.o processor.o
diff -r 3c564f80f2ef -r e97855b90cc2 
arch/i386/kernel/acpi/processor_extcntl_xen.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/i386/kernel/acpi/processor_extcntl_xen.c     Thu May 01 10:53:07 
2008 +0100
@@ -0,0 +1,142 @@
+/*
+ * processor_extcntl_xen.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 <acpi/processor.h>
+#include <asm/hypercall.h>
+
+static int xen_processor_pmbits;
+static int __init set_xen_processor_pmbits(char *str)
+{
+       get_option(&str, &xen_processor_pmbits);
+
+       return 1;
+}
+__setup("xen_processor_pmbits=", set_xen_processor_pmbits);
+EXPORT_SYMBOL(xen_processor_pmbits);
+
+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 */
+               if (cx->csd_count) {
+                       printk("Wow! _CSD is found. Not support for now!\n");
+                       kfree(buf);
+                       return -EINVAL;
+               } else {
+                       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_platform_op(&op);
+       kfree(buf);
+       return ret;
+}
+
+static int xen_px_notifier(struct acpi_processor *pr, int action)
+{
+       return -EINVAL;
+}
+
+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 __cpuinit xen_init_processor_extcntl(void)
+{
+       if (xen_processor_pmbits & XEN_PROCESSOR_PM_CX)
+               xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
+       if (xen_processor_pmbits & XEN_PROCESSOR_PM_PX)
+               xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
+       if (xen_processor_pmbits & XEN_PROCESSOR_PM_TX)
+               xen_extcntl_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier;
+
+       return processor_register_extcntl(&xen_extcntl_ops);
+}
+core_initcall(xen_init_processor_extcntl);
diff -r 3c564f80f2ef -r e97855b90cc2 arch/x86_64/kernel/acpi/Makefile
--- a/arch/x86_64/kernel/acpi/Makefile  Thu May 01 10:52:31 2008 +0100
+++ b/arch/x86_64/kernel/acpi/Makefile  Thu May 01 10:53:07 2008 +0100
@@ -8,4 +8,6 @@ processor-$(CONFIG_XEN) := ../../../i386
 processor-$(CONFIG_XEN)        := ../../../i386/kernel/acpi/processor.o
 endif
 
+obj-$(CONFIG_XEN)      += processor_extcnt_xen.o
+processor_extcnt_xen-$(CONFIG_XEN) := 
../../../i386/kernel/acpi/processor_extcntl_xen.o
 disabled-obj-$(CONFIG_XEN) := wakeup.o
diff -r 3c564f80f2ef -r e97855b90cc2 drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig      Thu May 01 10:52:31 2008 +0100
+++ b/drivers/acpi/Kconfig      Thu May 01 10:53:07 2008 +0100
@@ -371,6 +371,7 @@ config PROCESSOR_EXTERNAL_CONTROL
 config PROCESSOR_EXTERNAL_CONTROL
        bool
        depends on X86 && XEN
+       select ACPI_PROCESSOR
        default y
 endif  # ACPI
 
diff -r 3c564f80f2ef -r e97855b90cc2 drivers/acpi/processor_extcntl.c
--- a/drivers/acpi/processor_extcntl.c  Thu May 01 10:52:31 2008 +0100
+++ b/drivers/acpi/processor_extcntl.c  Thu May 01 10:53:07 2008 +0100
@@ -30,6 +30,7 @@
 
 #include <acpi/processor.h>
 
+static int processor_extcntl_parse_csd(struct acpi_processor *pr);
 /*
  * External processor control logic may register with its own set of
  * ops to get ACPI related notification. One example is like VMM.
@@ -107,5 +108,30 @@ int processor_unregister_extcntl(struct 
  */
 int processor_extcntl_init(struct acpi_processor *pr)
 {
+       /* parse cstate dependency information */
+       processor_extcntl_parse_csd(pr);
+
        return 0;
 }
+
+/*
+ * Currently no _CSD is implemented which is why existing ACPI code
+ * doesn't parse _CSD at all. But to keep interface complete with
+ * external control logic, we put a placeholder here for future
+ * compatibility.
+ */
+static int processor_extcntl_parse_csd(struct acpi_processor *pr)
+{
+       int i;
+
+       for (i = 0; i < pr->power.count; i++) {
+               if (!pr->power.states[i].valid)
+                       continue;
+
+               /* No dependency by default */
+               pr->power.states[i].domain_info = NULL;
+               pr->power.states[i].csd_count = 0;
+       }
+
+       return 0;
+}
diff -r 3c564f80f2ef -r e97855b90cc2 drivers/acpi/processor_idle.c
--- a/drivers/acpi/processor_idle.c     Thu May 01 10:52:31 2008 +0100
+++ b/drivers/acpi/processor_idle.c     Thu May 01 10:53:07 2008 +0100
@@ -714,8 +714,12 @@ static int acpi_processor_get_power_info
                    (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
                        continue;
 
-               cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
-                   0 : reg->address;
+               if (!processor_pm_external())
+                       cx.address = (reg->space_id ==
+                                     ACPI_ADR_SPACE_FIXED_HARDWARE) ?
+                                     0 : reg->address;
+               else
+                       cx.address = reg->address;
 
                /* There should be an easy way to extract an integer... */
                obj = (union acpi_object *)&(element->package.elements[1]);
@@ -724,9 +728,11 @@ static int acpi_processor_get_power_info
 
                cx.type = obj->integer.value;
 
-               if ((cx.type != ACPI_STATE_C1) &&
-                   (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
-                       continue;
+               /* Following check doesn't apply to external control case */
+               if (!processor_pm_external())
+                       if ((cx.type != ACPI_STATE_C1) &&
+                           (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
+                               continue;
 
                if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3))
                        continue;
@@ -742,6 +748,12 @@ static int acpi_processor_get_power_info
                        continue;
 
                cx.power = obj->integer.value;
+
+#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+               /* cache control methods to notify external logic */
+               if (processor_pm_external())
+                       memcpy(&cx.reg, reg, sizeof(*reg));
+#endif
 
                current_count++;
                memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
diff -r 3c564f80f2ef -r e97855b90cc2 include/acpi/processor.h
--- a/include/acpi/processor.h  Thu May 01 10:52:31 2008 +0100
+++ b/include/acpi/processor.h  Thu May 01 10:53:07 2008 +0100
@@ -32,6 +32,17 @@
 /* Power Management */
 
 struct acpi_processor_cx;
+
+#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+struct acpi_csd_package {
+       acpi_integer num_entries;
+       acpi_integer revision;
+       acpi_integer domain;
+       acpi_integer coord_type;
+       acpi_integer num_processors;
+       acpi_integer index;
+} __attribute__ ((packed));
+#endif
 
 struct acpi_power_register {
        u8 descriptor;
@@ -63,6 +74,12 @@ struct acpi_processor_cx {
        u32 power;
        u32 usage;
        u64 time;
+#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+       /* Require raw information for external control logic */
+       struct acpi_power_register reg;
+       u32 csd_count;
+       struct acpi_csd_package *domain_info;
+#endif
        struct acpi_processor_cx_policy promotion;
        struct acpi_processor_cx_policy demotion;
 };
diff -r 3c564f80f2ef -r e97855b90cc2 include/xen/interface/platform.h
--- a/include/xen/interface/platform.h  Thu May 01 10:52:31 2008 +0100
+++ b/include/xen/interface/platform.h  Thu May 01 10:53:07 2008 +0100
@@ -199,6 +199,78 @@ typedef struct xenpf_getidletime xenpf_g
 typedef struct xenpf_getidletime xenpf_getidletime_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
 
+#define XENPF_set_processor_pminfo      54
+
+/* ability bits */
+#define XEN_PROCESSOR_PM_CX    1
+#define XEN_PROCESSOR_PM_PX    2
+#define XEN_PROCESSOR_PM_TX    4
+
+/* cmd type */
+#define XEN_PM_CX   0
+#define XEN_PM_PX   1
+#define XEN_PM_TX   2
+
+struct xen_power_register {
+    uint32_t     space_id;
+    uint32_t     bit_width;
+    uint32_t     bit_offset;
+    uint32_t     access_size;
+    uint64_t     address;
+};
+
+struct xen_processor_csd {
+    uint32_t    domain;      /* domain number of one dependent group */
+    uint32_t    coord_type;  /* coordination type */
+    uint32_t    num;         /* number of processors in same domain */
+};
+typedef struct xen_processor_csd xen_processor_csd_t;
+DEFINE_XEN_GUEST_HANDLE(xen_processor_csd_t);
+
+struct xen_processor_cx {
+    struct xen_power_register  reg; /* GAS for Cx trigger register */
+    uint8_t     type;     /* cstate value, c0: 0, c1: 1, ... */
+    uint32_t    latency;  /* worst latency (ms) to enter/exit this cstate */
+    uint32_t    power;    /* average power consumption(mW) */
+    uint32_t    dpcnt;    /* number of dependency entries */
+    XEN_GUEST_HANDLE(xen_processor_csd_t) dp; /* NULL if no dependency */
+};
+typedef struct xen_processor_cx xen_processor_cx_t;
+DEFINE_XEN_GUEST_HANDLE(xen_processor_cx_t);
+
+struct xen_processor_flags {
+    uint8_t bm_control:1;
+    uint8_t bm_check:1;
+    uint8_t has_cst:1;
+    uint8_t power_setup_done:1;
+    uint8_t bm_rld_set:1;
+};
+
+struct xen_processor_power {
+    uint32_t count;  /* number of C state entries in array below */
+    struct xen_processor_flags flags;  /* global flags of this processor */
+    XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */
+};
+
+struct xen_processor_performance {
+};
+
+struct xen_processor_throttling {
+};
+
+struct xenpf_set_processor_pminfo {
+    /* IN variables */
+    uint32_t id;    /* ACPI CPU ID */
+    uint32_t type;  /* {XEN_PM_CX, XEN_PM_PX, XEN_PM_TX} */
+    union {
+        struct xen_processor_power          power;/* Cx: _CST/_CSD */
+        struct xen_processor_performance    perf; /* Px: _PPC/_PCT/_PSS/_PSD */
+        struct xen_processor_throttling     throt;/* Tx: _TPC/_PTC/_TSS/_TSD */
+    };
+};
+typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
+
 struct xen_platform_op {
     uint32_t cmd;
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -213,6 +285,7 @@ struct xen_platform_op {
         struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
         struct xenpf_change_freq       change_freq;
         struct xenpf_getidletime       getidletime;
+        struct xenpf_set_processor_pminfo set_pminfo;
         uint8_t                        pad[128];
     } u;
 };

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


 


Rackspace

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