All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 8/12] Enable ACPI sleep in Linux
@ 2007-02-14  9:17 Tian, Kevin
  0 siblings, 0 replies; 2+ messages in thread
From: Tian, Kevin @ 2007-02-14  9:17 UTC (permalink / raw)
  To: Keir Fraser, Ian Pratt, xen-devel; +Cc: Yu, Ke

[-- Attachment #1: Type: text/plain, Size: 11425 bytes --]

Open CONFIG_ACPI_SLEEP in xenlinux, to enable ACPI based
power management. Basically, user can trigger power event
now by "echo *** > /sys/power/state". Also gear to pm
interface defined between xenlinux and Xen.

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

diff -r 0d3d91f87abd buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32	Tue Feb 13 16:40:58 2007
+0800
+++ b/buildconfigs/linux-defconfig_xen_x86_32	Tue Feb 13 16:40:59 2007
+0800
@@ -205,6 +205,9 @@ CONFIG_PM=y
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+ACPI_SLEEP_PROC_FS=y
+CONFIG_ACPI_SLEEP_PROC_SLEEP=y
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/Kconfig
--- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Tue Feb 13 16:40:58 2007
+0800
+++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Tue Feb 13 16:40:59 2007
+0800
@@ -816,6 +816,11 @@ config HOTPLUG_CPU
 	  Say Y here to experiment with turning CPUs off and on, and to
 	  enable suspend on SMP systems. CPUs can be controlled through
 	  /sys/devices/system/cpu.
+
+config SUSPEND_SMP
+	bool
+	depends on HOTPLUG_CPU && X86 && PM
+	default y
 
 config COMPAT_VDSO
 	bool "Compat VDSO support"
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Tue Feb 13
16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Tue Feb 13
16:40:59 2007 +0800
@@ -851,9 +851,9 @@ static int timer_resume(struct sys_devic
 	return 0;
 }
 
+void time_resume(void);
 static struct sysdev_class timer_sysclass = {
-	.resume = timer_resume,
-	.suspend = timer_suspend,
+	.resume = time_resume,
 	set_kset_name("timer"),
 };
 
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/power/Makefile
--- a/linux-2.6-xen-sparse/arch/i386/power/Makefile	Tue Feb 13
16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/arch/i386/power/Makefile	Tue Feb 13
16:40:59 2007 +0800
@@ -2,3 +2,8 @@ obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_ACPI_SLEEP)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Tue Feb 13
16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Tue Feb 13
16:40:59 2007 +0800
@@ -62,11 +62,12 @@ static void do_fpu_end(void)
 
 static void fix_processor_context(void)
 {
+#ifndef CONFIG_X86_NO_TSS
 	int cpu = smp_processor_id();
 	struct tss_struct * t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not
be necessary. But... This is necessary, because 386 hardware has concept
of busy TSS or some similar stupidity. */
-
+#endif
 	load_TR_desc();				/* This does ltr */
 	load_LDT(&current->active_mm->context);	/* This does lldt */
 
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/Kconfig
--- a/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Tue Feb 13 16:40:58 2007
+0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Tue Feb 13 16:40:59 2007
+0800
@@ -45,7 +45,7 @@ if ACPI
 
 config ACPI_SLEEP
 	bool "Sleep States"
-	depends on X86 && (!SMP || SUSPEND_SMP) && !XEN
+	depends on X86 && (!SMP || SUSPEND_SMP)
 	depends on PM
 	default y
 	---help---
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Tue Feb
13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Tue Feb
13 16:40:59 2007 +0800
@@ -7,3 +7,8 @@ obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r 0d3d91f87abd
linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Tue Feb
13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Tue Feb
13 16:49:22 2007 +0800
@@ -209,6 +209,34 @@ acpi_status acpi_enter_sleep_state_prep(
 
 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
 
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+extern unsigned long acpi_video_flags;
+extern unsigned long saved_videomode;
+static acpi_status acpi_notify_xen_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt)
+{
+	struct xen_platform_op op = {
+		.cmd = XENPF_enter_acpi_sleep,
+		.interface_version = XENPF_INTERFACE_VERSION,
+		.u = {
+			.enter_acpi_sleep = {
+				.pm1a_cnt_val = (u16)pm1a_cnt,
+				.pm1b_cnt_val = (u16)pm1b_cnt,
+				.sleep_state = sleep_state,
+			},
+		},
+	};
+
+#ifdef CONFIG_X86
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_videomode;
+#endif
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif
 
/***********************************************************************
********
  *
  * FUNCTION:    acpi_enter_sleep_state
@@ -304,6 +332,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	/* Write #1: fill in SLP_TYP data */
 
+#ifndef CONFIG_XEN
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -314,6 +343,10 @@ acpi_status asmlinkage acpi_enter_sleep_
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1B_CONTROL,
 					PM1Bcontrol);
+#else
+	status = acpi_notify_xen_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
@@ -327,6 +360,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -337,6 +371,10 @@ acpi_status asmlinkage acpi_enter_sleep_
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1B_CONTROL,
 					PM1Bcontrol);
+#else
+	status = acpi_notify_xen_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Tue Feb 13
16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Tue Feb 13
16:40:59 2007 +0800
@@ -3,3 +3,8 @@ obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc
 obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Tue Feb
13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Tue Feb
13 16:50:03 2007 +0800
@@ -75,12 +75,15 @@ static int acpi_pm_enter(suspend_state_t
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
+	/* Covered by Xen */
 	/* Do arch specific saving of state. */
 	if (pm_state > PM_SUSPEND_STANDBY) {
 		int error = acpi_save_state_mem();
 		if (error)
 			return error;
 	}
+#endif
 
 	local_irq_save(flags);
 	acpi_enable_wakeup_device(acpi_state);
@@ -91,7 +94,14 @@ static int acpi_pm_enter(suspend_state_t
 		break;
 
 	case PM_SUSPEND_MEM:
+#ifdef CONFIG_XEN
+		/* XEN hyperviosr will save and restore CPU context
+		 * and then we can skip low level housekeeping here.
+		 */
+		acpi_enter_sleep_state(acpi_state);
+#else
 		do_suspend_lowlevel();
+#endif
 		break;
 
 	case PM_SUSPEND_DISK:
@@ -121,8 +131,10 @@ static int acpi_pm_enter(suspend_state_t
 	 * And, in the case of the latter, the memory image should have
already
 	 * been loaded from disk.
 	 */
+#ifndef CONFIG_XEN
 	if (pm_state > PM_SUSPEND_STANDBY)
 		acpi_restore_state_mem();
+#endif
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
@@ -145,10 +157,12 @@ static int acpi_pm_finish(suspend_state_
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
+#ifndef CONFIG_XEN
 	if (init_8259A_after_S1) {
 		printk("Broken toshiba laptop -> kicking interrupts\n");
 		init_8259A(0);
 	}
+#endif
 	return 0;
 }
 
@@ -199,6 +213,46 @@ static struct dmi_system_id __initdata a
 	 },
 	{},
 };
+
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+/* Register sleep info to xen hypervisor which does real work later */
+static acpi_status acpi_register_sleep_info(void)
+{
+	struct xen_platform_op op;
+	acpi_status status;
+
+	if (acpi_gbl_FADT == NULL) {
+		printk(KERN_WARNING "%s: ACPI FADT not existed\n",
+				__FUNCTION__);
+		return AE_NO_ACPI_TABLES;
+	}
+
+	op.cmd = XENPF_set_acpi_sleep;
+	op.interface_version = XENPF_INTERFACE_VERSION;
+	op.u.set_acpi_sleep.pm1a_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1a_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1b_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1b_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1a_evt_port =
+		(u16)acpi_gbl_FADT->xpm1a_evt_blk.address;
+	op.u.set_acpi_sleep.pm1b_evt_port =
+		(u16)acpi_gbl_FADT->xpm1b_evt_blk.address;
+
+	status  = HYPERVISOR_platform_op(&op);
+
+	if (ACPI_FAILURE(status)){
+		printk(KERN_WARNING "%s: Fail to register acpi sleep
info,"
+               		"Xen sleep will not work\n",
__FUNCTION__);
+		return (status);
+	}
+
+	acpi_wakeup_address = (unsigned long)
+		op.u.set_acpi_sleep.xen_waking_vec;
+	return status;
+}
+#endif /* CONFIG_XEN */
 
 static int __init acpi_sleep_init(void)
 {
@@ -226,6 +280,10 @@ static int __init acpi_sleep_init(void)
 	printk(")\n");
 
 	pm_set_ops(&acpi_pm_ops);
+
+#ifdef CONFIG_XEN
+	acpi_register_sleep_info();
+#endif
 	return 0;
 }
 
diff -r 0d3d91f87abd
linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Tue Feb
13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Tue Feb
13 16:40:59 2007 +0800
@@ -25,9 +25,14 @@ int acpi_sleep_prepare(u32 acpi_state)
 		if (!acpi_wakeup_address) {
 			return -EFAULT;
 		}
+#ifndef CONFIG_XEN
 		acpi_set_firmware_waking_vector((acpi_physical_address)
 						virt_to_phys((void *)
 
acpi_wakeup_address));
+#else
+		acpi_set_firmware_waking_vector((acpi_physical_address)
+						acpi_wakeup_address);
+#endif
 
 	}
 	ACPI_FLUSH_CPU_CACHE();
diff -r 0d3d91f87abd
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
Tue Feb 13 16:40:59 2007 +0800
@@ -402,6 +402,12 @@ HYPERVISOR_kexec_op(
 	return _hypercall2(int, kexec_op, op, args);
 }
 
+static inline long
+HYPERVISOR_platform_op(
+	void* arg)
+{
+	return _hypercall1(long, platform_op, arg);
+}
 
 
 #endif /* __HYPERCALL_H__ */

[-- Attachment #2: enable_linux_acpi_sleep.patch --]
[-- Type: application/octet-stream, Size: 11057 bytes --]

Open CONFIG_ACPI_SLEEP in xenlinux, to enable ACPI based
power management. Basically, user can trigger power event
now by "echo *** > /sys/power/state". Also gear to pm
interface defined between xenlinux and Xen.

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

diff -r 0d3d91f87abd buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32	Tue Feb 13 16:40:58 2007 +0800
+++ b/buildconfigs/linux-defconfig_xen_x86_32	Tue Feb 13 16:40:59 2007 +0800
@@ -205,6 +205,9 @@ CONFIG_PM=y
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+ACPI_SLEEP_PROC_FS=y
+CONFIG_ACPI_SLEEP_PROC_SLEEP=y
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/Kconfig
--- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Tue Feb 13 16:40:59 2007 +0800
@@ -816,6 +816,11 @@ config HOTPLUG_CPU
 	  Say Y here to experiment with turning CPUs off and on, and to
 	  enable suspend on SMP systems. CPUs can be controlled through
 	  /sys/devices/system/cpu.
+
+config SUSPEND_SMP
+	bool
+	depends on HOTPLUG_CPU && X86 && PM
+	default y
 
 config COMPAT_VDSO
 	bool "Compat VDSO support"
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Tue Feb 13 16:40:59 2007 +0800
@@ -851,9 +851,9 @@ static int timer_resume(struct sys_devic
 	return 0;
 }
 
+void time_resume(void);
 static struct sysdev_class timer_sysclass = {
-	.resume = timer_resume,
-	.suspend = timer_suspend,
+	.resume = time_resume,
 	set_kset_name("timer"),
 };
 
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/power/Makefile
--- a/linux-2.6-xen-sparse/arch/i386/power/Makefile	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/arch/i386/power/Makefile	Tue Feb 13 16:40:59 2007 +0800
@@ -2,3 +2,8 @@ obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_ACPI_SLEEP)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r 0d3d91f87abd linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Tue Feb 13 16:40:59 2007 +0800
@@ -62,11 +62,12 @@ static void do_fpu_end(void)
 
 static void fix_processor_context(void)
 {
+#ifndef CONFIG_X86_NO_TSS
 	int cpu = smp_processor_id();
 	struct tss_struct * t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
-
+#endif
 	load_TR_desc();				/* This does ltr */
 	load_LDT(&current->active_mm->context);	/* This does lldt */
 
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/Kconfig
--- a/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Tue Feb 13 16:40:59 2007 +0800
@@ -45,7 +45,7 @@ if ACPI
 
 config ACPI_SLEEP
 	bool "Sleep States"
-	depends on X86 && (!SMP || SUSPEND_SMP) && !XEN
+	depends on X86 && (!SMP || SUSPEND_SMP)
 	depends on PM
 	default y
 	---help---
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Tue Feb 13 16:40:59 2007 +0800
@@ -7,3 +7,8 @@ obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Tue Feb 13 16:49:22 2007 +0800
@@ -209,6 +209,34 @@ acpi_status acpi_enter_sleep_state_prep(
 
 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
 
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+extern unsigned long acpi_video_flags;
+extern unsigned long saved_videomode;
+static acpi_status acpi_notify_xen_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt)
+{
+	struct xen_platform_op op = {
+		.cmd = XENPF_enter_acpi_sleep,
+		.interface_version = XENPF_INTERFACE_VERSION,
+		.u = {
+			.enter_acpi_sleep = {
+				.pm1a_cnt_val = (u16)pm1a_cnt,
+				.pm1b_cnt_val = (u16)pm1b_cnt,
+				.sleep_state = sleep_state,
+			},
+		},
+	};
+
+#ifdef CONFIG_X86
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_videomode;
+#endif
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enter_sleep_state
@@ -304,6 +332,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	/* Write #1: fill in SLP_TYP data */
 
+#ifndef CONFIG_XEN
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -314,6 +343,10 @@ acpi_status asmlinkage acpi_enter_sleep_
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1B_CONTROL,
 					PM1Bcontrol);
+#else
+	status = acpi_notify_xen_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
@@ -327,6 +360,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -337,6 +371,10 @@ acpi_status asmlinkage acpi_enter_sleep_
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1B_CONTROL,
 					PM1Bcontrol);
+#else
+	status = acpi_notify_xen_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Tue Feb 13 16:40:59 2007 +0800
@@ -3,3 +3,8 @@ obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc
 obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Tue Feb 13 16:50:03 2007 +0800
@@ -75,12 +75,15 @@ static int acpi_pm_enter(suspend_state_t
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
+	/* Covered by Xen */
 	/* Do arch specific saving of state. */
 	if (pm_state > PM_SUSPEND_STANDBY) {
 		int error = acpi_save_state_mem();
 		if (error)
 			return error;
 	}
+#endif
 
 	local_irq_save(flags);
 	acpi_enable_wakeup_device(acpi_state);
@@ -91,7 +94,14 @@ static int acpi_pm_enter(suspend_state_t
 		break;
 
 	case PM_SUSPEND_MEM:
+#ifdef CONFIG_XEN
+		/* XEN hyperviosr will save and restore CPU context
+		 * and then we can skip low level housekeeping here.
+		 */
+		acpi_enter_sleep_state(acpi_state);
+#else
 		do_suspend_lowlevel();
+#endif
 		break;
 
 	case PM_SUSPEND_DISK:
@@ -121,8 +131,10 @@ static int acpi_pm_enter(suspend_state_t
 	 * And, in the case of the latter, the memory image should have already
 	 * been loaded from disk.
 	 */
+#ifndef CONFIG_XEN
 	if (pm_state > PM_SUSPEND_STANDBY)
 		acpi_restore_state_mem();
+#endif
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
@@ -145,10 +157,12 @@ static int acpi_pm_finish(suspend_state_
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
+#ifndef CONFIG_XEN
 	if (init_8259A_after_S1) {
 		printk("Broken toshiba laptop -> kicking interrupts\n");
 		init_8259A(0);
 	}
+#endif
 	return 0;
 }
 
@@ -199,6 +213,46 @@ static struct dmi_system_id __initdata a
 	 },
 	{},
 };
+
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+/* Register sleep info to xen hypervisor which does real work later */
+static acpi_status acpi_register_sleep_info(void)
+{
+	struct xen_platform_op op;
+	acpi_status status;
+
+	if (acpi_gbl_FADT == NULL) {
+		printk(KERN_WARNING "%s: ACPI FADT not existed\n",
+				__FUNCTION__);
+		return AE_NO_ACPI_TABLES;
+	}
+
+	op.cmd = XENPF_set_acpi_sleep;
+	op.interface_version = XENPF_INTERFACE_VERSION;
+	op.u.set_acpi_sleep.pm1a_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1a_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1b_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1b_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1a_evt_port =
+		(u16)acpi_gbl_FADT->xpm1a_evt_blk.address;
+	op.u.set_acpi_sleep.pm1b_evt_port =
+		(u16)acpi_gbl_FADT->xpm1b_evt_blk.address;
+
+	status  = HYPERVISOR_platform_op(&op);
+
+	if (ACPI_FAILURE(status)){
+		printk(KERN_WARNING "%s: Fail to register acpi sleep info,"
+               		"Xen sleep will not work\n", __FUNCTION__);
+		return (status);
+	}
+
+	acpi_wakeup_address = (unsigned long)
+		op.u.set_acpi_sleep.xen_waking_vec;
+	return status;
+}
+#endif /* CONFIG_XEN */
 
 static int __init acpi_sleep_init(void)
 {
@@ -226,6 +280,10 @@ static int __init acpi_sleep_init(void)
 	printk(")\n");
 
 	pm_set_ops(&acpi_pm_ops);
+
+#ifdef CONFIG_XEN
+	acpi_register_sleep_info();
+#endif
 	return 0;
 }
 
diff -r 0d3d91f87abd linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Tue Feb 13 16:40:59 2007 +0800
@@ -25,9 +25,14 @@ int acpi_sleep_prepare(u32 acpi_state)
 		if (!acpi_wakeup_address) {
 			return -EFAULT;
 		}
+#ifndef CONFIG_XEN
 		acpi_set_firmware_waking_vector((acpi_physical_address)
 						virt_to_phys((void *)
 							     acpi_wakeup_address));
+#else
+		acpi_set_firmware_waking_vector((acpi_physical_address)
+						acpi_wakeup_address);
+#endif
 
 	}
 	ACPI_FLUSH_CPU_CACHE();
diff -r 0d3d91f87abd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Tue Feb 13 16:40:58 2007 +0800
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Tue Feb 13 16:40:59 2007 +0800
@@ -402,6 +402,12 @@ HYPERVISOR_kexec_op(
 	return _hypercall2(int, kexec_op, op, args);
 }
 
+static inline long
+HYPERVISOR_platform_op(
+	void* arg)
+{
+	return _hypercall1(long, platform_op, arg);
+}
 
 
 #endif /* __HYPERCALL_H__ */

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH 8/12] Enable ACPI sleep in Linux
@ 2007-05-15 14:20 Tian, Kevin
  0 siblings, 0 replies; 2+ messages in thread
From: Tian, Kevin @ 2007-05-15 14:20 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 13450 bytes --]

Open CONFIG_ACPI_SLEEP in xenlinux, to enable ACPI based
power management. Basically, user can trigger power event
now by "echo *** > /sys/power/state". Also gear to pm
interface defined between xenlinux and Xen.

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

diff -r ae6a502a5db4 buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32	Wed Apr 11 14:09:56 2007
-0400
+++ b/buildconfigs/linux-defconfig_xen_x86_32	Wed Apr 11 14:09:57 2007
-0400
@@ -205,6 +205,9 @@ CONFIG_PM=y
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+ACPI_SLEEP_PROC_FS=y
+CONFIG_ACPI_SLEEP_PROC_SLEEP=y
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r ae6a502a5db4 buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64	Wed Apr 11 14:09:56 2007
-0400
+++ b/buildconfigs/linux-defconfig_xen_x86_64	Wed Apr 11 14:09:57 2007
-0400
@@ -167,6 +167,9 @@ CONFIG_PM=y
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+CONFIG_ACPI_SLEEP_PROC_SLEEP=y
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/Kconfig
--- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Wed Apr 11 14:09:56 2007
-0400
+++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Wed Apr 11 14:09:57 2007
-0400
@@ -810,6 +810,11 @@ config HOTPLUG_CPU
 	  Say Y here to experiment with turning CPUs off and on, and to
 	  enable suspend on SMP systems. CPUs can be controlled through
 	  /sys/devices/system/cpu.
+
+config SUSPEND_SMP
+	bool
+	depends on HOTPLUG_CPU && X86 && PM
+	default y
 
 config COMPAT_VDSO
 	bool "Compat VDSO support"
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Wed Apr 11
14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Wed Apr 11
14:09:57 2007 -0400
@@ -849,9 +849,9 @@ static int timer_resume(struct sys_devic
 	return 0;
 }
 
+void time_resume(void);
 static struct sysdev_class timer_sysclass = {
-	.resume = timer_resume,
-	.suspend = timer_suspend,
+	.resume = time_resume,
 	set_kset_name("timer"),
 };
 
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/power/Makefile
--- a/linux-2.6-xen-sparse/arch/i386/power/Makefile	Wed Apr 11
14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/power/Makefile	Wed Apr 11
14:09:57 2007 -0400
@@ -2,3 +2,8 @@ obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_ACPI_SLEEP)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Wed Apr 11
14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Wed Apr 11
14:09:57 2007 -0400
@@ -62,11 +62,12 @@ static void do_fpu_end(void)
 
 static void fix_processor_context(void)
 {
+#ifndef CONFIG_X86_NO_TSS
 	int cpu = smp_processor_id();
 	struct tss_struct * t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not
be necessary. But... This is necessary, because 386 hardware has concept
of busy TSS or some similar stupidity. */
-
+#endif
 	load_TR_desc();				/* This does ltr */
 	load_LDT(&current->active_mm->context);	/* This does lldt */
 
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/x86_64/Kconfig
--- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Wed Apr 11 14:09:56 2007
-0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Wed Apr 11 14:09:57 2007
-0400
@@ -408,6 +408,11 @@ config HOTPLUG_CPU
 		can be controlled through /sys/devices/system/cpu/cpu#.
 		Say N if you want to disable CPU hotplug.
 
+config SUSPEND_SMP
+	bool 
+	depends on HOTPLUG_CPU && X86 && PM
+	default y
+
 config ARCH_ENABLE_MEMORY_HOTPLUG
 	def_bool y
 
diff -r ae6a502a5db4
linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile	Wed Apr
11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile	Wed Apr
11 14:09:57 2007 -0400
@@ -8,3 +8,8 @@ endif
 endif
 
 boot-$(CONFIG_XEN)		:= ../../../i386/kernel/acpi/boot-xen.o
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S	Wed Apr
11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S	Wed Apr
11 14:09:57 2007 -0400
@@ -43,6 +43,13 @@ ENTRY(_start)
 	pushq $0		# fake return address
 	jmp x86_64_start_kernel
 
+#ifdef CONFIG_ACPI_SLEEP
+.org 0xf00
+	.globl pGDT32
+pGDT32:
+	.word	gdt_end-cpu_gdt_table-1
+	.long	cpu_gdt_table-__START_KERNEL_map
+#endif
 ENTRY(stext)
 ENTRY(_stext)
 
@@ -102,6 +109,14 @@ NEXT_PAGE(hypercall_page)
 	CFI_ENDPROC
 
 #undef NEXT_PAGE
+
+	.data
+
+#ifdef CONFIG_ACPI_SLEEP
+	.align PAGE_SIZE
+ENTRY(wakeup_level4_pgt)
+	.fill	512,8,0
+#endif
 
 	.data
 
diff -r ae6a502a5db4
linux-2.6-xen-sparse/arch/x86_64/kernel/suspend-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/suspend-xen.c	Wed Apr
11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/suspend-xen.c	Wed Apr
11 14:09:57 2007 -0400
@@ -114,12 +114,14 @@ void restore_processor_state(void)
 
 void fix_processor_context(void)
 {
+#ifndef CONFIG_X86_NO_TSS    
 	int cpu = smp_processor_id();
 	struct tss_struct *t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not
be neccessary. But... This is neccessary, because 386 hardware has
concept of busy TSS or some similar stupidity. */
 
 	cpu_gdt(cpu)[GDT_ENTRY_TSS].type = 9;
+#endif    
 
 	syscall_init();                         /* This sets MSR_*STAR
and related */
 	load_TR_desc();				/* This does ltr */
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/Kconfig
--- a/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Wed Apr 11 14:09:56 2007
-0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Wed Apr 11 14:09:57 2007
-0400
@@ -45,7 +45,7 @@ if ACPI
 
 config ACPI_SLEEP
 	bool "Sleep States"
-	depends on X86 && (!SMP || SUSPEND_SMP) && !XEN
+	depends on X86 && (!SMP || SUSPEND_SMP)
 	depends on PM
 	default y
 	---help---
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Wed Apr
11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Wed Apr
11 14:09:57 2007 -0400
@@ -7,3 +7,8 @@ obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4
linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Wed Apr
11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Wed Apr
11 14:09:57 2007 -0400
@@ -209,6 +209,37 @@ acpi_status acpi_enter_sleep_state_prep(
 
 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
 
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+#ifdef CONFIG_X86_64
+#define saved_videomode saved_video_mode
+#endif
+extern unsigned long acpi_video_flags;
+extern unsigned long saved_videomode;
+static acpi_status acpi_notify_xen_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt)
+{
+	struct xen_platform_op op = {
+		.cmd = XENPF_enter_acpi_sleep,
+		.interface_version = XENPF_INTERFACE_VERSION,
+		.u = {
+			.enter_acpi_sleep = {
+				.pm1a_cnt_val = (u16)pm1a_cnt,
+				.pm1b_cnt_val = (u16)pm1b_cnt,
+				.sleep_state = sleep_state,
+			},
+		},
+	};
+
+#ifdef CONFIG_X86
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_videomode;
+#endif
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif
 
/***********************************************************************
********
  *
  * FUNCTION:    acpi_enter_sleep_state
@@ -327,6 +358,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -337,6 +369,10 @@ acpi_status asmlinkage acpi_enter_sleep_
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1B_CONTROL,
 					PM1Bcontrol);
+#else
+	status = acpi_notify_xen_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Wed Apr 11
14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Wed Apr 11
14:09:57 2007 -0400
@@ -3,3 +3,8 @@ obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc
 obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Wed Apr
11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Wed Apr
11 14:09:57 2007 -0400
@@ -75,12 +75,15 @@ static int acpi_pm_enter(suspend_state_t
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
+	/* Covered by Xen */
 	/* Do arch specific saving of state. */
 	if (pm_state > PM_SUSPEND_STANDBY) {
 		int error = acpi_save_state_mem();
 		if (error)
 			return error;
 	}
+#endif
 
 	local_irq_save(flags);
 	acpi_enable_wakeup_device(acpi_state);
@@ -91,7 +94,14 @@ static int acpi_pm_enter(suspend_state_t
 		break;
 
 	case PM_SUSPEND_MEM:
+#ifdef CONFIG_XEN
+		/* XEN hyperviosr will save and restore CPU context
+		 * and then we can skip low level housekeeping here.
+		 */
+		acpi_enter_sleep_state(acpi_state);
+#else
 		do_suspend_lowlevel();
+#endif
 		break;
 
 	case PM_SUSPEND_DISK:
@@ -121,8 +131,10 @@ static int acpi_pm_enter(suspend_state_t
 	 * And, in the case of the latter, the memory image should have
already
 	 * been loaded from disk.
 	 */
+#ifndef CONFIG_XEN
 	if (pm_state > PM_SUSPEND_STANDBY)
 		acpi_restore_state_mem();
+#endif
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
@@ -145,10 +157,12 @@ static int acpi_pm_finish(suspend_state_
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
+#ifndef CONFIG_XEN
 	if (init_8259A_after_S1) {
 		printk("Broken toshiba laptop -> kicking interrupts\n");
 		init_8259A(0);
 	}
+#endif
 	return 0;
 }
 
@@ -199,6 +213,46 @@ static struct dmi_system_id __initdata a
 	 },
 	{},
 };
+
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+/* Register sleep info to xen hypervisor which does real work later */
+static acpi_status acpi_register_sleep_info(void)
+{
+	struct xen_platform_op op;
+	acpi_status status;
+
+	if (acpi_gbl_FADT == NULL) {
+		printk(KERN_WARNING "%s: ACPI FADT not existed\n",
+				__FUNCTION__);
+		return AE_NO_ACPI_TABLES;
+	}
+
+	op.cmd = XENPF_set_acpi_sleep;
+	op.interface_version = XENPF_INTERFACE_VERSION;
+	op.u.set_acpi_sleep.pm1a_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1a_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1b_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1b_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1a_evt_port =
+		(u16)acpi_gbl_FADT->xpm1a_evt_blk.address;
+	op.u.set_acpi_sleep.pm1b_evt_port =
+		(u16)acpi_gbl_FADT->xpm1b_evt_blk.address;
+
+	status  = HYPERVISOR_platform_op(&op);
+
+	if (ACPI_FAILURE(status)){
+		printk(KERN_WARNING "%s: Fail to register acpi sleep
info,"
+               		"Xen sleep will not work\n",
__FUNCTION__);
+		return (status);
+	}
+
+	acpi_wakeup_address = (unsigned long)
+		op.u.set_acpi_sleep.xen_waking_vec;
+	return status;
+}
+#endif /* CONFIG_XEN */
 
 static int __init acpi_sleep_init(void)
 {
@@ -226,6 +280,10 @@ static int __init acpi_sleep_init(void)
 	printk(")\n");
 
 	pm_set_ops(&acpi_pm_ops);
+
+#ifdef CONFIG_XEN
+	acpi_register_sleep_info();
+#endif
 	return 0;
 }
 
diff -r ae6a502a5db4
linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Wed Apr
11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Wed Apr
11 14:09:57 2007 -0400
@@ -25,9 +25,14 @@ int acpi_sleep_prepare(u32 acpi_state)
 		if (!acpi_wakeup_address) {
 			return -EFAULT;
 		}
+#ifndef CONFIG_XEN
 		acpi_set_firmware_waking_vector((acpi_physical_address)
 						virt_to_phys((void *)
 
acpi_wakeup_address));
+#else
+		acpi_set_firmware_waking_vector((acpi_physical_address)
+						acpi_wakeup_address);
+#endif
 
 	}
 	ACPI_FLUSH_CPU_CACHE();

[-- Attachment #2: enable_linux_acpi_sleep.patch --]
[-- Type: application/octet-stream, Size: 13412 bytes --]

Open CONFIG_ACPI_SLEEP in xenlinux, to enable ACPI based
power management. Basically, user can trigger power event
now by "echo *** > /sys/power/state". Also gear to pm
interface defined between xenlinux and Xen.

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

diff -r ae6a502a5db4 buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32	Wed Apr 11 14:09:56 2007 -0400
+++ b/buildconfigs/linux-defconfig_xen_x86_32	Wed Apr 11 14:09:57 2007 -0400
@@ -205,6 +205,9 @@ CONFIG_PM=y
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+ACPI_SLEEP_PROC_FS=y
+CONFIG_ACPI_SLEEP_PROC_SLEEP=y
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r ae6a502a5db4 buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64	Wed Apr 11 14:09:56 2007 -0400
+++ b/buildconfigs/linux-defconfig_xen_x86_64	Wed Apr 11 14:09:57 2007 -0400
@@ -167,6 +167,9 @@ CONFIG_PM=y
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+CONFIG_ACPI_SLEEP_PROC_SLEEP=y
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/Kconfig
--- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Wed Apr 11 14:09:57 2007 -0400
@@ -810,6 +810,11 @@ config HOTPLUG_CPU
 	  Say Y here to experiment with turning CPUs off and on, and to
 	  enable suspend on SMP systems. CPUs can be controlled through
 	  /sys/devices/system/cpu.
+
+config SUSPEND_SMP
+	bool
+	depends on HOTPLUG_CPU && X86 && PM
+	default y
 
 config COMPAT_VDSO
 	bool "Compat VDSO support"
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Wed Apr 11 14:09:57 2007 -0400
@@ -849,9 +849,9 @@ static int timer_resume(struct sys_devic
 	return 0;
 }
 
+void time_resume(void);
 static struct sysdev_class timer_sysclass = {
-	.resume = timer_resume,
-	.suspend = timer_suspend,
+	.resume = time_resume,
 	set_kset_name("timer"),
 };
 
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/power/Makefile
--- a/linux-2.6-xen-sparse/arch/i386/power/Makefile	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/power/Makefile	Wed Apr 11 14:09:57 2007 -0400
@@ -2,3 +2,8 @@ obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= cpu.o
 obj-$(CONFIG_ACPI_SLEEP)	+= cpu.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c	Wed Apr 11 14:09:57 2007 -0400
@@ -62,11 +62,12 @@ static void do_fpu_end(void)
 
 static void fix_processor_context(void)
 {
+#ifndef CONFIG_X86_NO_TSS
 	int cpu = smp_processor_id();
 	struct tss_struct * t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
-
+#endif
 	load_TR_desc();				/* This does ltr */
 	load_LDT(&current->active_mm->context);	/* This does lldt */
 
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/x86_64/Kconfig
--- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Wed Apr 11 14:09:57 2007 -0400
@@ -408,6 +408,11 @@ config HOTPLUG_CPU
 		can be controlled through /sys/devices/system/cpu/cpu#.
 		Say N if you want to disable CPU hotplug.
 
+config SUSPEND_SMP
+	bool 
+	depends on HOTPLUG_CPU && X86 && PM
+	default y
+
 config ARCH_ENABLE_MEMORY_HOTPLUG
 	def_bool y
 
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile	Wed Apr 11 14:09:57 2007 -0400
@@ -8,3 +8,8 @@ endif
 endif
 
 boot-$(CONFIG_XEN)		:= ../../../i386/kernel/acpi/boot-xen.o
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S	Wed Apr 11 14:09:57 2007 -0400
@@ -43,6 +43,13 @@ ENTRY(_start)
 	pushq $0		# fake return address
 	jmp x86_64_start_kernel
 
+#ifdef CONFIG_ACPI_SLEEP
+.org 0xf00
+	.globl pGDT32
+pGDT32:
+	.word	gdt_end-cpu_gdt_table-1
+	.long	cpu_gdt_table-__START_KERNEL_map
+#endif
 ENTRY(stext)
 ENTRY(_stext)
 
@@ -102,6 +109,14 @@ NEXT_PAGE(hypercall_page)
 	CFI_ENDPROC
 
 #undef NEXT_PAGE
+
+	.data
+
+#ifdef CONFIG_ACPI_SLEEP
+	.align PAGE_SIZE
+ENTRY(wakeup_level4_pgt)
+	.fill	512,8,0
+#endif
 
 	.data
 
diff -r ae6a502a5db4 linux-2.6-xen-sparse/arch/x86_64/kernel/suspend-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/suspend-xen.c	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/suspend-xen.c	Wed Apr 11 14:09:57 2007 -0400
@@ -114,12 +114,14 @@ void restore_processor_state(void)
 
 void fix_processor_context(void)
 {
+#ifndef CONFIG_X86_NO_TSS    
 	int cpu = smp_processor_id();
 	struct tss_struct *t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
 
 	cpu_gdt(cpu)[GDT_ENTRY_TSS].type = 9;
+#endif    
 
 	syscall_init();                         /* This sets MSR_*STAR and related */
 	load_TR_desc();				/* This does ltr */
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/Kconfig
--- a/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Wed Apr 11 14:09:57 2007 -0400
@@ -45,7 +45,7 @@ if ACPI
 
 config ACPI_SLEEP
 	bool "Sleep States"
-	depends on X86 && (!SMP || SUSPEND_SMP) && !XEN
+	depends on X86 && (!SMP || SUSPEND_SMP)
 	depends on PM
 	default y
 	---help---
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile	Wed Apr 11 14:09:57 2007 -0400
@@ -7,3 +7,8 @@ obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c	Wed Apr 11 14:09:57 2007 -0400
@@ -209,6 +209,37 @@ acpi_status acpi_enter_sleep_state_prep(
 
 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
 
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+#ifdef CONFIG_X86_64
+#define saved_videomode saved_video_mode
+#endif
+extern unsigned long acpi_video_flags;
+extern unsigned long saved_videomode;
+static acpi_status acpi_notify_xen_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt)
+{
+	struct xen_platform_op op = {
+		.cmd = XENPF_enter_acpi_sleep,
+		.interface_version = XENPF_INTERFACE_VERSION,
+		.u = {
+			.enter_acpi_sleep = {
+				.pm1a_cnt_val = (u16)pm1a_cnt,
+				.pm1b_cnt_val = (u16)pm1b_cnt,
+				.sleep_state = sleep_state,
+			},
+		},
+	};
+
+#ifdef CONFIG_X86
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_videomode;
+#endif
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enter_sleep_state
@@ -327,6 +358,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -337,6 +369,10 @@ acpi_status asmlinkage acpi_enter_sleep_
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1B_CONTROL,
 					PM1Bcontrol);
+#else
+	status = acpi_notify_xen_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile	Wed Apr 11 14:09:57 2007 -0400
@@ -3,3 +3,8 @@ obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc
 obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
+
+ifdef CONFIG_XEN
+include $(srctree)/scripts/Makefile.xen
+obj-y := $(call cherrypickxen, $(obj-y))
+endif
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c	Wed Apr 11 14:09:57 2007 -0400
@@ -75,12 +75,15 @@ static int acpi_pm_enter(suspend_state_t
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_XEN
+	/* Covered by Xen */
 	/* Do arch specific saving of state. */
 	if (pm_state > PM_SUSPEND_STANDBY) {
 		int error = acpi_save_state_mem();
 		if (error)
 			return error;
 	}
+#endif
 
 	local_irq_save(flags);
 	acpi_enable_wakeup_device(acpi_state);
@@ -91,7 +94,14 @@ static int acpi_pm_enter(suspend_state_t
 		break;
 
 	case PM_SUSPEND_MEM:
+#ifdef CONFIG_XEN
+		/* XEN hyperviosr will save and restore CPU context
+		 * and then we can skip low level housekeeping here.
+		 */
+		acpi_enter_sleep_state(acpi_state);
+#else
 		do_suspend_lowlevel();
+#endif
 		break;
 
 	case PM_SUSPEND_DISK:
@@ -121,8 +131,10 @@ static int acpi_pm_enter(suspend_state_t
 	 * And, in the case of the latter, the memory image should have already
 	 * been loaded from disk.
 	 */
+#ifndef CONFIG_XEN
 	if (pm_state > PM_SUSPEND_STANDBY)
 		acpi_restore_state_mem();
+#endif
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
@@ -145,10 +157,12 @@ static int acpi_pm_finish(suspend_state_
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
+#ifndef CONFIG_XEN
 	if (init_8259A_after_S1) {
 		printk("Broken toshiba laptop -> kicking interrupts\n");
 		init_8259A(0);
 	}
+#endif
 	return 0;
 }
 
@@ -199,6 +213,46 @@ static struct dmi_system_id __initdata a
 	 },
 	{},
 };
+
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+/* Register sleep info to xen hypervisor which does real work later */
+static acpi_status acpi_register_sleep_info(void)
+{
+	struct xen_platform_op op;
+	acpi_status status;
+
+	if (acpi_gbl_FADT == NULL) {
+		printk(KERN_WARNING "%s: ACPI FADT not existed\n",
+				__FUNCTION__);
+		return AE_NO_ACPI_TABLES;
+	}
+
+	op.cmd = XENPF_set_acpi_sleep;
+	op.interface_version = XENPF_INTERFACE_VERSION;
+	op.u.set_acpi_sleep.pm1a_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1a_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1b_cnt_port =
+		(u16)acpi_gbl_FADT->xpm1b_cnt_blk.address;
+	op.u.set_acpi_sleep.pm1a_evt_port =
+		(u16)acpi_gbl_FADT->xpm1a_evt_blk.address;
+	op.u.set_acpi_sleep.pm1b_evt_port =
+		(u16)acpi_gbl_FADT->xpm1b_evt_blk.address;
+
+	status  = HYPERVISOR_platform_op(&op);
+
+	if (ACPI_FAILURE(status)){
+		printk(KERN_WARNING "%s: Fail to register acpi sleep info,"
+               		"Xen sleep will not work\n", __FUNCTION__);
+		return (status);
+	}
+
+	acpi_wakeup_address = (unsigned long)
+		op.u.set_acpi_sleep.xen_waking_vec;
+	return status;
+}
+#endif /* CONFIG_XEN */
 
 static int __init acpi_sleep_init(void)
 {
@@ -226,6 +280,10 @@ static int __init acpi_sleep_init(void)
 	printk(")\n");
 
 	pm_set_ops(&acpi_pm_ops);
+
+#ifdef CONFIG_XEN
+	acpi_register_sleep_info();
+#endif
 	return 0;
 }
 
diff -r ae6a502a5db4 linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c
--- a/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Wed Apr 11 14:09:56 2007 -0400
+++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c	Wed Apr 11 14:09:57 2007 -0400
@@ -25,9 +25,14 @@ int acpi_sleep_prepare(u32 acpi_state)
 		if (!acpi_wakeup_address) {
 			return -EFAULT;
 		}
+#ifndef CONFIG_XEN
 		acpi_set_firmware_waking_vector((acpi_physical_address)
 						virt_to_phys((void *)
 							     acpi_wakeup_address));
+#else
+		acpi_set_firmware_waking_vector((acpi_physical_address)
+						acpi_wakeup_address);
+#endif
 
 	}
 	ACPI_FLUSH_CPU_CACHE();

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-05-15 14:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-14  9:17 [PATCH 8/12] Enable ACPI sleep in Linux Tian, Kevin
2007-05-15 14:20 Tian, Kevin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.