[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |