=== Overview ===
Requirement: Xen hypervisor need Cx/Px ACPI info to do the Cx/Px states
power management. This info is provided by BIOS ACPI table. Since
hypervisor has no ACPI parser, this info has to be parsed by domain0
kernel ACPI sub-system, and then passed to hypervisor by hypercall.
To make this happen, the key point is to add hook in the kernel ACPI
sub-system. Fortunately, kernel already has good abstraction, and
only several places need to add hook. To be more detail, there is an
acpi_processor_driver (in drivers/acpi/processor_core.c) , which all the
Cx/Px parsing event will go to. This driver will call its acpi processor
event handler, e.g. add/remove, start/stop, notify to handle these
events. These event handlers in turn will call some library functions (in
drivers/acpi/processor_perflib.c), e.g. acpi_processor_ppc_has_changed,
acpi_processor_ppc_has_changed, acpi_processor_cst_has_changed, to finish
the acpi info parsing.
So this patch add the xen hook in these places to notify xen for the parsed
Cx/Px state information.
Signed-off-by: Yu Ke <ke.yu@intel.com>
Signed-off-by: Tian Kevin <kevin.tian@intel.com>
---
drivers/acpi/processor_core.c | 17 ++
drivers/acpi/processor_idle.c | 25 ++
drivers/acpi/processor_perflib.c | 10 +
drivers/xen/Kconfig | 7 +
drivers/xen/Makefile | 3
drivers/xen/processor_extcntl.c | 413 ++++++++++++++++++++++++++++++++++++++
include/acpi/processor.h | 6 +
include/xen/acpi.h | 55 +++++
8 files changed, 528 insertions(+), 8 deletions(-)
create mode 100644 drivers/xen/processor_extcntl.c
@@ -58,6 +58,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
+#include <xen/acpi.h>
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
@@ -751,6 +752,10 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
acpi_processor_power_init(pr, device);
+ result = processor_cntl_xen_prepare(pr);
+ if (result)
+ goto end;
+
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (IS_ERR(pr->cdev)) {
@@ -963,6 +968,10 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
if (!pr)
return -ENODEV;
+ if (processor_cntl_xen())
+ processor_cntl_xen_notify(pr,
+ PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
+
if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) {
kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE);
}
@@ -1002,11 +1011,19 @@ static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
break;
}
+ if (processor_cntl_xen())
+ processor_cntl_xen_notify(pr,
+ PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
+
if (pr->id >= 0 && (pr->id < nr_cpu_ids)) {
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break;
}
+ if (processor_cntl_xen())
+ processor_cntl_xen_notify(pr, PROCESSOR_HOTPLUG,
+ HOTPLUG_TYPE_REMOVE);
+
result = acpi_processor_start(device);
if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) {
kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
@@ -58,6 +58,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/processor.h>
+#include <xen/acpi.h>
#include <asm/processor.h>
#define ACPI_PROCESSOR_CLASS "processor"
@@ -455,6 +456,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
cx.power = obj->integer.value;
+#ifdef CONFIG_ACPI_PROCESSOR_XEN
+ /* cache control methods to notify xen*/
+ if (processor_cntl_xen_pm())
+ memcpy(&cx.reg, reg, sizeof(*reg));
+#endif
+
current_count++;
memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
@@ -1141,6 +1148,13 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
if (!pr->flags.power_setup_done)
return -ENODEV;
+ if (processor_cntl_xen_pm()) {
+ acpi_processor_get_power_info(pr);
+ processor_cntl_xen_notify(pr,
+ PROCESSOR_PM_CHANGE, PM_TYPE_IDLE);
+ return ret;
+ }
+
cpuidle_pause_and_lock();
cpuidle_disable_device(&pr->power.dev);
acpi_processor_get_power_info(pr);
@@ -1204,9 +1218,14 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
* platforms that only support C1.
*/
if (pr->flags.power) {
- acpi_processor_setup_cpuidle(pr);
- if (cpuidle_register_device(&pr->power.dev))
- return -EIO;
+ if (processor_cntl_xen_pm())
+ processor_cntl_xen_notify(pr,
+ PROCESSOR_PM_INIT, PM_TYPE_IDLE);
+ else {
+ acpi_processor_setup_cpuidle(pr);
+ if (cpuidle_register_device(&pr->power.dev))
+ return -EIO;
+ }
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
for (i = 1; i <= pr->power.count; i++)
@@ -38,6 +38,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
+#include <xen/acpi.h>
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
@@ -154,13 +155,16 @@ int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
{
int ret;
- if (ignore_ppc)
+ if (ignore_ppc && !processor_cntl_xen_pmperf())
return 0;
ret = acpi_processor_get_platform_limit(pr);
if (ret < 0)
return (ret);
+ else if (processor_cntl_xen_pmperf())
+ return processor_cntl_xen_notify(pr,
+ PROCESSOR_PM_CHANGE, PM_TYPE_PERF);
else
return cpufreq_update_policy(pr->id);
}
@@ -330,7 +334,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
return result;
}
-static int acpi_processor_get_performance_info(struct acpi_processor *pr)
+int acpi_processor_get_performance_info(struct acpi_processor *pr)
{
int result = 0;
acpi_status status = AE_OK;
@@ -432,7 +436,7 @@ int acpi_processor_notify_smm(struct module *calling_module)
EXPORT_SYMBOL(acpi_processor_notify_smm);
-static int acpi_processor_get_psd(struct acpi_processor *pr)
+int acpi_processor_get_psd(struct acpi_processor *pr)
{
int result = 0;
acpi_status status = AE_OK;
@@ -90,4 +90,9 @@ config XEN_XENBUS_FRONTEND
config XEN_S3
def_bool y
- depends on XEN_DOM0 && ACPI
\ No newline at end of file
+ depends on XEN_DOM0 && ACPI
+
+config ACPI_PROCESSOR_XEN
+ bool
+ depends on XEN_DOM0 && ACPI_PROCESSOR && CPU_FREQ
+ default y
@@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
obj-$(CONFIG_XENFS) += xenfs/
obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
-obj-$(CONFIG_XEN_S3) += acpi.o
\ No newline at end of file
+obj-$(CONFIG_XEN_S3) += acpi.o
+obj-$(CONFIG_ACPI_PROCESSOR_XEN) += processor_extcntl.o
new file mode 100644
@@ -0,0 +1,413 @@
+/*
+ * 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 int processor_cntl_xen_get_performance(struct acpi_processor *pr);
+static int xen_hotplug_notifier(struct acpi_processor *pr, int event);
+
+static struct processor_cntl_xen_ops xen_ops = {
+ .hotplug = xen_hotplug_notifier,
+};
+
+int processor_cntl_xen(void)
+{
+ return 1;
+}
+
+int processor_cntl_xen_pm(void)
+{
+ return (xen_ops.pm_ops[PM_TYPE_IDLE] != NULL);
+}
+
+int processor_cntl_xen_pmperf(void)
+{
+ return (xen_ops.pm_ops[PM_TYPE_PERF] != NULL);
+}
+
+int processor_cntl_xen_pmthr(void)
+{
+ return (xen_ops.pm_ops[PM_TYPE_THR] != NULL);
+}
+
+static int processor_notify_smm(void)
+{
+ acpi_status status;
+ static int is_done = 0;
+
+ /* only need successfully notify BIOS once */
+ /* avoid double notification which may lead to unexpected result */
+ if (is_done)
+ return 0;
+
+ /* Can't write pstate_cnt to smi_cmd if either value is zero */
+ if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"No SMI port or pstate_cnt\n"));
+ return 0;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n",
+ acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
+
+ status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
+ (u32) acpi_gbl_FADT.pstate_control, 8);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ is_done = 1;
+
+ return 0;
+}
+
+int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type)
+{
+ int ret = -EINVAL;
+
+ switch (event) {
+ case PROCESSOR_PM_INIT:
+ case PROCESSOR_PM_CHANGE:
+ if ((type >= PM_TYPE_MAX) ||
+ !xen_ops.pm_ops[type])
+ break;
+
+ ret = xen_ops.pm_ops[type](pr, event);
+ break;
+ case PROCESSOR_HOTPLUG:
+ if (xen_ops.hotplug)
+ ret = xen_ops.hotplug(pr, type);
+ break;
+ default:
+ printk(KERN_ERR "Unsupport processor events %d.\n", event);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * This is called from ACPI processor init, and targeted to hold
+ * some tricky housekeeping jobs to satisfy xen.
+ * For example, we may put dependency parse stub here for idle
+ * and performance state. Those information may be not available
+ * if splitting from dom0 control logic like cpufreq driver.
+ */
+int processor_cntl_xen_prepare(struct acpi_processor *pr)
+{
+
+ /* Initialize performance states */
+ if (processor_cntl_xen_pmperf())
+ processor_cntl_xen_get_performance(pr);
+
+ return 0;
+}
+
+/*
+ * Existing ACPI module does parse performance states at some point,
+ * when acpi-cpufreq driver is loaded which however is something
+ * we'd like to disable to avoid confliction with xen PM
+ * logic. So we have to collect raw performance information here
+ * when ACPI processor object is found and started.
+ */
+static int processor_cntl_xen_get_performance(struct acpi_processor *pr)
+{
+ int ret;
+ struct acpi_processor_performance *perf;
+ struct acpi_psd_package *pdomain;
+
+ if (pr->performance)
+ return -EBUSY;
+
+ perf = kzalloc(sizeof(struct acpi_processor_performance), GFP_KERNEL);
+ if (!perf)
+ return -ENOMEM;
+
+ pr->performance = perf;
+ /* Get basic performance state information */
+ ret = acpi_processor_get_performance_info(pr);
+ if (ret < 0)
+ goto err_out;
+
+ /*
+ * Well, here we need retrieve performance dependency information
+ * from _PSD object. The reason why existing interface is not used
+ * is due to the reason that existing interface sticks to Linux cpu
+ * id to construct some bitmap, however we want to split ACPI
+ * processor objects from Linux cpu id logic. For example, even
+ * when Linux is configured as UP, we still want to parse all ACPI
+ * processor objects to xen. In this case, it's preferred
+ * to use ACPI ID instead.
+ */
+ pdomain = &pr->performance->domain_info;
+ pdomain->num_processors = 0;
+ ret = acpi_processor_get_psd(pr);
+ if (ret < 0) {
+ /*
+ * _PSD is optional - assume no coordination if absent (or
+ * broken), matching native kernels' behavior.
+ */
+ pdomain->num_entries = ACPI_PSD_REV0_ENTRIES;
+ pdomain->revision = ACPI_PSD_REV0_REVISION;
+ pdomain->domain = pr->acpi_id;
+ pdomain->coord_type = DOMAIN_COORD_TYPE_SW_ALL;
+ pdomain->num_processors = 1;
+ }
+
+ /* Some sanity check */
+ if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
+ (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) ||
+ ((pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL) &&
+ (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY) &&
+ (pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL))) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ /* Last step is to notify BIOS that xen exists */
+ processor_notify_smm();
+
+ processor_cntl_xen_notify(pr, PROCESSOR_PM_INIT, PM_TYPE_PERF);
+
+ return 0;
+err_out:
+ pr->performance = NULL;
+ kfree(perf);
+ return ret;
+}
+
+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 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_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
+ if (pmbits & XEN_PROCESSOR_PM_PX)
+ xen_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
+ if (pmbits & XEN_PROCESSOR_PM_TX)
+ xen_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier;
+
+ return 0;
+}
+
+subsys_initcall(xen_acpi_processor_extcntl_init);
@@ -77,6 +77,10 @@ struct acpi_processor_cx {
struct acpi_processor_cx_policy promotion;
struct acpi_processor_cx_policy demotion;
char desc[ACPI_CX_DESC_LEN];
+#ifdef CONFIG_ACPI_PROCESSOR_XEN
+ /* Require raw information for xen*/
+ struct acpi_power_register reg;
+#endif /* CONFIG_ACPI_PROCESSOE_XEN */
};
struct acpi_processor_power {
@@ -295,6 +299,8 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
void acpi_processor_ppc_init(void);
void acpi_processor_ppc_exit(void);
int acpi_processor_ppc_has_changed(struct acpi_processor *pr);
+int acpi_processor_get_performance_info(struct acpi_processor *pr);
+int acpi_processor_get_psd(struct acpi_processor *pr);
#else
static inline void acpi_processor_ppc_init(void)
{
@@ -20,4 +20,59 @@ static inline bool xen_pv_acpi(void)
int acpi_notify_hypervisor_state(u8 sleep_state,
u32 pm1a_cnt, u32 pm1b_cnd);
+/*
+ * Following are interfaces for xen acpi processor control
+ */
+
+/* Events notified to xen */
+#define PROCESSOR_PM_INIT 1
+#define PROCESSOR_PM_CHANGE 2
+#define PROCESSOR_HOTPLUG 3
+
+/* Objects for the PM events */
+#define PM_TYPE_IDLE 0
+#define PM_TYPE_PERF 1
+#define PM_TYPE_THR 2
+#define PM_TYPE_MAX 3
+
+/* Processor hotplug events */
+#define HOTPLUG_TYPE_ADD 0
+#define HOTPLUG_TYPE_REMOVE 1
+
+#ifdef CONFIG_ACPI_PROCESSOR_XEN
+#include <acpi/acpi_drivers.h>
+#include <acpi/processor.h>
+
+struct processor_cntl_xen_ops {
+ /* Transfer processor PM events to xen */
+int (*pm_ops[PM_TYPE_MAX])(struct acpi_processor *pr, int event);
+ /* Notify physical processor status to xen */
+ int (*hotplug)(struct acpi_processor *pr, int type);
+};
+
+extern int processor_cntl_xen(void);
+extern int processor_cntl_xen_pm(void);
+extern int processor_cntl_xen_pmperf(void);
+extern int processor_cntl_xen_pmthr(void);
+extern int processor_cntl_xen_prepare(struct acpi_processor *pr);
+extern int processor_cntl_xen_notify(struct acpi_processor *pr,
+ int event, int type);
+
+#else
+
+static inline int processor_cntl_xen(void) {return 0;}
+static inline int processor_cntl_xen_pm(void) {return 0;}
+static inline int processor_cntl_xen_pmperf(void) {return 0;}
+static inline int processor_cntl_xen_pmthr(void) {return 0;}
+static inline int processor_cntl_xen_notify(struct acpi_processor *pr,
+ int event, int type)
+{
+ return 0;
+}
+static inline int processor_cntl_xen_prepare(struct acpi_processor *pr)
+{
+ return 0;
+}
+#endif /* CONFIG_ACPI_PROCESSOR_XEN */
+
#endif /* _XEN_ACPI_H */