All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/4] Enable ACPI sleep in XenLinux
@ 2007-07-19 10:04 Tian, Kevin
  2007-07-19 10:29 ` Keir Fraser
  0 siblings, 1 reply; 6+ messages in thread
From: Tian, Kevin @ 2007-07-19 10:04 UTC (permalink / raw)
  To: Keir Fraser; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 14106 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.

Also sync to xen interface headers consequently

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

diff -r 7c8ff2db2e59 arch/i386/Kconfig
--- a/arch/i386/Kconfig	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/Kconfig	Thu Jul 19 13:29:29 2007 +0800
@@ -832,9 +832,7 @@ menu "Power management options (ACPI, AP
 menu "Power management options (ACPI, APM)"
 	depends on !(X86_VOYAGER || XEN_UNPRIVILEGED_GUEST)
 
-if !X86_XEN
-source kernel/power/Kconfig
-endif
+source "kernel/power/Kconfig"
 
 source "drivers/acpi/Kconfig"
 
diff -r 7c8ff2db2e59 arch/i386/kernel/acpi/sleep-xen.c
--- a/arch/i386/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007 +0800
@@ -27,12 +27,13 @@ extern unsigned long FASTCALL(acpi_copy_
  */
 int acpi_save_state_mem(void)
 {
+#ifndef CONFIG_ACPI_PV_SLEEP
 	if (!acpi_wakeup_address)
 		return 1;
 	memcpy((void *)acpi_wakeup_address, &wakeup_start,
 	       &wakeup_end - &wakeup_start);
 	acpi_copy_wakeup_routine(acpi_wakeup_address);
-
+#endif
 	return 0;
 }
 
@@ -104,3 +105,30 @@ static int __init acpisleep_dmi_init(voi
 }
 
 core_initcall(acpisleep_dmi_init);
+
+#ifdef CONFIG_ACPI_PV_SLEEP
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+extern unsigned long acpi_video_flags;
+extern unsigned long saved_videomode;
+int acpi_notify_hypervisor_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,
+			},
+		},
+	};
+
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_videomode;
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif /* CONFIG_ACPI_PV_SLEEP */
diff -r 7c8ff2db2e59 arch/i386/kernel/time-xen.c
--- a/arch/i386/kernel/time-xen.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/kernel/time-xen.c	Thu Jul 19 13:29:29 2007 +0800
@@ -867,9 +867,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 7c8ff2db2e59 arch/i386/power/cpu.c
--- a/arch/i386/power/cpu.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/power/cpu.c	Thu Jul 19 13:29:29 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 7c8ff2db2e59 arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/Kconfig	Thu Jul 19 13:29:29 2007 +0800
@@ -594,9 +594,7 @@ menu "Power management options"
 menu "Power management options"
 	depends on !XEN_UNPRIVILEGED_GUEST
 
-if !X86_64_XEN
-source kernel/power/Kconfig
-endif
+source "kernel/power/Kconfig"
 
 source "drivers/acpi/Kconfig"
 
diff -r 7c8ff2db2e59 arch/x86_64/kernel/acpi/Makefile
--- a/arch/x86_64/kernel/acpi/Makefile	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/kernel/acpi/Makefile	Thu Jul 19 13:29:29 2007 +0800
@@ -8,3 +8,7 @@ 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 7c8ff2db2e59 arch/x86_64/kernel/acpi/sleep-xen.c
--- a/arch/x86_64/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007
+0800
+++ b/arch/x86_64/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007
+0800
@@ -79,12 +79,13 @@ static void init_low_mapping(void)
  */
 int acpi_save_state_mem(void)
 {
+#ifndef CONFIG_ACPI_PV_SLEEP
 	init_low_mapping();
 
 	memcpy((void *)acpi_wakeup_address, &wakeup_start,
 	       &wakeup_end - &wakeup_start);
 	acpi_copy_wakeup_routine(acpi_wakeup_address);
-
+#endif
 	return 0;
 }
 
@@ -93,8 +94,10 @@ int acpi_save_state_mem(void)
  */
 void acpi_restore_state_mem(void)
 {
+#ifndef CONFIG_ACPI_PV_SLEEP
 	set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
 	local_flush_tlb();
+#endif
 }
 
 /**
@@ -124,10 +127,37 @@ static int __init acpi_sleep_setup(char 
 		if (str != NULL)
 			str += strspn(str, ", \t");
 	}
+
 	return 1;
 }
 
 __setup("acpi_sleep=", acpi_sleep_setup);
+
+#ifdef CONFIG_ACPI_PV_SLEEP
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+extern unsigned long saved_video_mode;
+int acpi_notify_hypervisor_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,
+			},
+		},
+	};
+
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_video_mode;
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif				/* CONFIG_ACPI_PV_SLEEP */
 
 #endif				/*CONFIG_ACPI_SLEEP */
 
diff -r 7c8ff2db2e59 arch/x86_64/kernel/head-xen.S
--- a/arch/x86_64/kernel/head-xen.S	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/kernel/head-xen.S	Thu Jul 19 13:29:29 2007 +0800
@@ -37,6 +37,13 @@ startup_64:
 	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)
 
@@ -95,6 +102,14 @@ NEXT_PAGE(hypercall_page)
 	CFI_ENDPROC
 
 #undef NEXT_PAGE
+
+	.data
+/* Just dummy symbol to allow compilation. Not used in sleep path */
+#ifdef CONFIG_ACPI_SLEEP
+	.align PAGE_SIZE
+ENTRY(wakeup_level4_pgt)
+	.fill	512,8,0
+#endif
 
 	.data
 
diff -r 7c8ff2db2e59 arch/x86_64/kernel/suspend.c
--- a/arch/x86_64/kernel/suspend.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/kernel/suspend.c	Thu Jul 19 13:29:29 2007 +0800
@@ -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 7c8ff2db2e59 buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32	Thu Jul 19 13:29:29 2007
+0800
+++ b/buildconfigs/linux-defconfig_xen_x86_32	Thu Jul 19 13:29:29 2007
+0800
@@ -202,11 +202,18 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # Power management options (ACPI, APM)
 #
 CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+CONFIG_PM_DEBUG=y
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SUSPEND_SMP=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 is not set
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r 7c8ff2db2e59 buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64	Thu Jul 19 13:29:29 2007
+0800
+++ b/buildconfigs/linux-defconfig_xen_x86_64	Thu Jul 19 13:29:29 2007
+0800
@@ -161,11 +161,18 @@ CONFIG_GENERIC_PENDING_IRQ=y
 # Power management options
 #
 CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+CONFIG_PM_DEBUG=y
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SUSPEND_SMP=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 is not set
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r 7c8ff2db2e59 drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/Kconfig	Thu Jul 19 13:29:29 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---
@@ -363,6 +363,10 @@ config ACPI_SBS
 	  A "Smart Battery" is quite old and quite rare compared
 	  to today's ACPI "Control Method" battery.
 
+config ACPI_PV_SLEEP
+	bool
+	depends on X86 && XEN
+	default y
 endif	# ACPI
 
 endmenu
diff -r 7c8ff2db2e59 drivers/acpi/hardware/hwsleep.c
--- a/drivers/acpi/hardware/hwsleep.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/hardware/hwsleep.c	Thu Jul 19 13:29:29 2007 +0800
@@ -327,6 +327,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_ACPI_PV_SLEEP
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -337,6 +338,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_hypervisor_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff -r 7c8ff2db2e59 drivers/acpi/sleep/main.c
--- a/drivers/acpi/sleep/main.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/sleep/main.c	Thu Jul 19 15:30:38 2007 +0800
@@ -91,7 +91,14 @@ static int acpi_pm_enter(suspend_state_t
 		break;
 
 	case PM_SUSPEND_MEM:
+#ifdef CONFIG_ACPI_PV_SLEEP
+		/* 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:
@@ -145,10 +152,12 @@ static int acpi_pm_finish(suspend_state_
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
+#ifndef CONFIG_ACPI_PV_SLEEP
 	if (init_8259A_after_S1) {
 		printk("Broken toshiba laptop -> kicking interrupts\n");
 		init_8259A(0);
 	}
+#endif
 	return 0;
 }
 
diff -r 7c8ff2db2e59 drivers/acpi/sleep/poweroff.c
--- a/drivers/acpi/sleep/poweroff.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/sleep/poweroff.c	Thu Jul 19 15:31:45 2007 +0800
@@ -20,6 +20,7 @@ int acpi_sleep_prepare(u32 acpi_state)
 int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
+#ifndef CONFIG_ACPI_PV_SLEEP
 	/* do we have a wakeup address for S2 and S3? */
 	if (acpi_state == ACPI_STATE_S3) {
 		if (!acpi_wakeup_address) {
@@ -30,6 +31,7 @@ int acpi_sleep_prepare(u32 acpi_state)
 
acpi_wakeup_address));
 
 	}
+#endif
 	ACPI_FLUSH_CPU_CACHE();
 	acpi_enable_wakeup_device_prep(acpi_state);
 #endif
diff -r 7c8ff2db2e59 include/asm-i386/acpi.h
--- a/include/asm-i386/acpi.h	Thu Jul 19 13:29:29 2007 +0800
+++ b/include/asm-i386/acpi.h	Thu Jul 19 13:29:29 2007 +0800
@@ -177,6 +177,10 @@ extern unsigned long acpi_wakeup_address
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+#ifdef CONFIG_ACPI_PV_SLEEP
+extern int acpi_notify_hypervisor_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt);
+#endif /* CONFIG_ACPI_PV_SLEEP */
 #endif /*CONFIG_ACPI_SLEEP*/
 
 extern u8 x86_acpiid_to_apicid[];
diff -r 7c8ff2db2e59 include/asm-x86_64/acpi.h
--- a/include/asm-x86_64/acpi.h	Thu Jul 19 13:29:29 2007 +0800
+++ b/include/asm-x86_64/acpi.h	Thu Jul 19 13:29:29 2007 +0800
@@ -153,6 +153,10 @@ extern unsigned long acpi_wakeup_address
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+#ifdef CONFIG_ACPI_PV_SLEEP
+extern int acpi_notify_hypervisor_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt);
+#endif /* CONFIG_ACPI_PV_SLEEP */
 #endif /*CONFIG_ACPI_SLEEP*/
 
 #define boot_cpu_physical_apicid boot_cpu_id
diff -r 7c8ff2db2e59 include/xen/interface/platform.h
--- a/include/xen/interface/platform.h	Thu Jul 19 13:29:29 2007 +0800
+++ b/include/xen/interface/platform.h	Thu Jul 19 13:29:29 2007 +0800
@@ -153,6 +153,18 @@ typedef struct xenpf_firmware_info xenpf
 typedef struct xenpf_firmware_info xenpf_firmware_info_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
 
+#define XENPF_enter_acpi_sleep    51
+struct xenpf_enter_acpi_sleep {
+    /* IN variables */
+    uint16_t pm1a_cnt_val;
+    uint16_t pm1b_cnt_val;
+    uint32_t sleep_state;       /* Which state to enter */
+    uint32_t video_flags;       /* S3_bios or s3_mode */
+    uint32_t video_mode;        /* Mode setting for s3_mode */
+};
+typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
+
 struct xen_platform_op {
     uint32_t cmd;
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -164,6 +176,7 @@ struct xen_platform_op {
         struct xenpf_microcode_update  microcode;
         struct xenpf_platform_quirk    platform_quirk;
         struct xenpf_firmware_info     firmware_info;
+        struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
         uint8_t                        pad[128];
     } u;
 };

[-- Attachment #2: enable_linux_acpi_sleep.patch --]
[-- Type: application/octet-stream, Size: 14105 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.

Also sync to xen interface headers consequently

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

diff -r 7c8ff2db2e59 arch/i386/Kconfig
--- a/arch/i386/Kconfig	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/Kconfig	Thu Jul 19 13:29:29 2007 +0800
@@ -832,9 +832,7 @@ menu "Power management options (ACPI, AP
 menu "Power management options (ACPI, APM)"
 	depends on !(X86_VOYAGER || XEN_UNPRIVILEGED_GUEST)
 
-if !X86_XEN
-source kernel/power/Kconfig
-endif
+source "kernel/power/Kconfig"
 
 source "drivers/acpi/Kconfig"
 
diff -r 7c8ff2db2e59 arch/i386/kernel/acpi/sleep-xen.c
--- a/arch/i386/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007 +0800
@@ -27,12 +27,13 @@ extern unsigned long FASTCALL(acpi_copy_
  */
 int acpi_save_state_mem(void)
 {
+#ifndef CONFIG_ACPI_PV_SLEEP
 	if (!acpi_wakeup_address)
 		return 1;
 	memcpy((void *)acpi_wakeup_address, &wakeup_start,
 	       &wakeup_end - &wakeup_start);
 	acpi_copy_wakeup_routine(acpi_wakeup_address);
-
+#endif
 	return 0;
 }
 
@@ -104,3 +105,30 @@ static int __init acpisleep_dmi_init(voi
 }
 
 core_initcall(acpisleep_dmi_init);
+
+#ifdef CONFIG_ACPI_PV_SLEEP
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+extern unsigned long acpi_video_flags;
+extern unsigned long saved_videomode;
+int acpi_notify_hypervisor_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,
+			},
+		},
+	};
+
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_videomode;
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif /* CONFIG_ACPI_PV_SLEEP */
diff -r 7c8ff2db2e59 arch/i386/kernel/time-xen.c
--- a/arch/i386/kernel/time-xen.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/kernel/time-xen.c	Thu Jul 19 13:29:29 2007 +0800
@@ -867,9 +867,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 7c8ff2db2e59 arch/i386/power/cpu.c
--- a/arch/i386/power/cpu.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/i386/power/cpu.c	Thu Jul 19 13:29:29 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 7c8ff2db2e59 arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/Kconfig	Thu Jul 19 13:29:29 2007 +0800
@@ -594,9 +594,7 @@ menu "Power management options"
 menu "Power management options"
 	depends on !XEN_UNPRIVILEGED_GUEST
 
-if !X86_64_XEN
-source kernel/power/Kconfig
-endif
+source "kernel/power/Kconfig"
 
 source "drivers/acpi/Kconfig"
 
diff -r 7c8ff2db2e59 arch/x86_64/kernel/acpi/Makefile
--- a/arch/x86_64/kernel/acpi/Makefile	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/kernel/acpi/Makefile	Thu Jul 19 13:29:29 2007 +0800
@@ -8,3 +8,7 @@ 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 7c8ff2db2e59 arch/x86_64/kernel/acpi/sleep-xen.c
--- a/arch/x86_64/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/kernel/acpi/sleep-xen.c	Thu Jul 19 13:29:29 2007 +0800
@@ -79,12 +79,13 @@ static void init_low_mapping(void)
  */
 int acpi_save_state_mem(void)
 {
+#ifndef CONFIG_ACPI_PV_SLEEP
 	init_low_mapping();
 
 	memcpy((void *)acpi_wakeup_address, &wakeup_start,
 	       &wakeup_end - &wakeup_start);
 	acpi_copy_wakeup_routine(acpi_wakeup_address);
-
+#endif
 	return 0;
 }
 
@@ -93,8 +94,10 @@ int acpi_save_state_mem(void)
  */
 void acpi_restore_state_mem(void)
 {
+#ifndef CONFIG_ACPI_PV_SLEEP
 	set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
 	local_flush_tlb();
+#endif
 }
 
 /**
@@ -124,10 +127,37 @@ static int __init acpi_sleep_setup(char 
 		if (str != NULL)
 			str += strspn(str, ", \t");
 	}
+
 	return 1;
 }
 
 __setup("acpi_sleep=", acpi_sleep_setup);
+
+#ifdef CONFIG_ACPI_PV_SLEEP
+#include <asm/hypervisor.h>
+#include <xen/interface/platform.h>
+extern unsigned long saved_video_mode;
+int acpi_notify_hypervisor_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,
+			},
+		},
+	};
+
+	op.u.enter_acpi_sleep.video_flags = acpi_video_flags;
+	op.u.enter_acpi_sleep.video_mode = saved_video_mode;
+
+	return HYPERVISOR_platform_op(&op);
+}
+#endif				/* CONFIG_ACPI_PV_SLEEP */
 
 #endif				/*CONFIG_ACPI_SLEEP */
 
diff -r 7c8ff2db2e59 arch/x86_64/kernel/head-xen.S
--- a/arch/x86_64/kernel/head-xen.S	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/kernel/head-xen.S	Thu Jul 19 13:29:29 2007 +0800
@@ -37,6 +37,13 @@ startup_64:
 	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)
 
@@ -95,6 +102,14 @@ NEXT_PAGE(hypercall_page)
 	CFI_ENDPROC
 
 #undef NEXT_PAGE
+
+	.data
+/* Just dummy symbol to allow compilation. Not used in sleep path */
+#ifdef CONFIG_ACPI_SLEEP
+	.align PAGE_SIZE
+ENTRY(wakeup_level4_pgt)
+	.fill	512,8,0
+#endif
 
 	.data
 
diff -r 7c8ff2db2e59 arch/x86_64/kernel/suspend.c
--- a/arch/x86_64/kernel/suspend.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/arch/x86_64/kernel/suspend.c	Thu Jul 19 13:29:29 2007 +0800
@@ -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 7c8ff2db2e59 buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32	Thu Jul 19 13:29:29 2007 +0800
+++ b/buildconfigs/linux-defconfig_xen_x86_32	Thu Jul 19 13:29:29 2007 +0800
@@ -202,11 +202,18 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # Power management options (ACPI, APM)
 #
 CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+CONFIG_PM_DEBUG=y
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SUSPEND_SMP=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 is not set
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r 7c8ff2db2e59 buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64	Thu Jul 19 13:29:29 2007 +0800
+++ b/buildconfigs/linux-defconfig_xen_x86_64	Thu Jul 19 13:29:29 2007 +0800
@@ -161,11 +161,18 @@ CONFIG_GENERIC_PENDING_IRQ=y
 # Power management options
 #
 CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+CONFIG_PM_DEBUG=y
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SUSPEND_SMP=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 is not set
 CONFIG_ACPI_AC=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
diff -r 7c8ff2db2e59 drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/Kconfig	Thu Jul 19 13:29:29 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---
@@ -363,6 +363,10 @@ config ACPI_SBS
 	  A "Smart Battery" is quite old and quite rare compared
 	  to today's ACPI "Control Method" battery.
 
+config ACPI_PV_SLEEP
+	bool
+	depends on X86 && XEN
+	default y
 endif	# ACPI
 
 endmenu
diff -r 7c8ff2db2e59 drivers/acpi/hardware/hwsleep.c
--- a/drivers/acpi/hardware/hwsleep.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/hardware/hwsleep.c	Thu Jul 19 13:29:29 2007 +0800
@@ -327,6 +327,7 @@ acpi_status asmlinkage acpi_enter_sleep_
 
 	ACPI_FLUSH_CPU_CACHE();
 
+#ifndef CONFIG_ACPI_PV_SLEEP
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1A_CONTROL,
 					PM1Acontrol);
@@ -337,6 +338,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_hypervisor_state(sleep_state,
+			PM1Acontrol, PM1Bcontrol);
+#endif
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff -r 7c8ff2db2e59 drivers/acpi/sleep/main.c
--- a/drivers/acpi/sleep/main.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/sleep/main.c	Thu Jul 19 15:30:38 2007 +0800
@@ -91,7 +91,14 @@ static int acpi_pm_enter(suspend_state_t
 		break;
 
 	case PM_SUSPEND_MEM:
+#ifdef CONFIG_ACPI_PV_SLEEP
+		/* 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:
@@ -145,10 +152,12 @@ static int acpi_pm_finish(suspend_state_
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
+#ifndef CONFIG_ACPI_PV_SLEEP
 	if (init_8259A_after_S1) {
 		printk("Broken toshiba laptop -> kicking interrupts\n");
 		init_8259A(0);
 	}
+#endif
 	return 0;
 }
 
diff -r 7c8ff2db2e59 drivers/acpi/sleep/poweroff.c
--- a/drivers/acpi/sleep/poweroff.c	Thu Jul 19 13:29:29 2007 +0800
+++ b/drivers/acpi/sleep/poweroff.c	Thu Jul 19 15:31:45 2007 +0800
@@ -20,6 +20,7 @@ int acpi_sleep_prepare(u32 acpi_state)
 int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
+#ifndef CONFIG_ACPI_PV_SLEEP
 	/* do we have a wakeup address for S2 and S3? */
 	if (acpi_state == ACPI_STATE_S3) {
 		if (!acpi_wakeup_address) {
@@ -30,6 +31,7 @@ int acpi_sleep_prepare(u32 acpi_state)
 							     acpi_wakeup_address));
 
 	}
+#endif
 	ACPI_FLUSH_CPU_CACHE();
 	acpi_enable_wakeup_device_prep(acpi_state);
 #endif
diff -r 7c8ff2db2e59 include/asm-i386/acpi.h
--- a/include/asm-i386/acpi.h	Thu Jul 19 13:29:29 2007 +0800
+++ b/include/asm-i386/acpi.h	Thu Jul 19 13:29:29 2007 +0800
@@ -177,6 +177,10 @@ extern unsigned long acpi_wakeup_address
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+#ifdef CONFIG_ACPI_PV_SLEEP
+extern int acpi_notify_hypervisor_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt);
+#endif /* CONFIG_ACPI_PV_SLEEP */
 #endif /*CONFIG_ACPI_SLEEP*/
 
 extern u8 x86_acpiid_to_apicid[];
diff -r 7c8ff2db2e59 include/asm-x86_64/acpi.h
--- a/include/asm-x86_64/acpi.h	Thu Jul 19 13:29:29 2007 +0800
+++ b/include/asm-x86_64/acpi.h	Thu Jul 19 13:29:29 2007 +0800
@@ -153,6 +153,10 @@ extern unsigned long acpi_wakeup_address
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+#ifdef CONFIG_ACPI_PV_SLEEP
+extern int acpi_notify_hypervisor_state(u8 sleep_state,
+	u32 pm1a_cnt, u32 pm1b_cnt);
+#endif /* CONFIG_ACPI_PV_SLEEP */
 #endif /*CONFIG_ACPI_SLEEP*/
 
 #define boot_cpu_physical_apicid boot_cpu_id
diff -r 7c8ff2db2e59 include/xen/interface/platform.h
--- a/include/xen/interface/platform.h	Thu Jul 19 13:29:29 2007 +0800
+++ b/include/xen/interface/platform.h	Thu Jul 19 13:29:29 2007 +0800
@@ -153,6 +153,18 @@ typedef struct xenpf_firmware_info xenpf
 typedef struct xenpf_firmware_info xenpf_firmware_info_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
 
+#define XENPF_enter_acpi_sleep    51
+struct xenpf_enter_acpi_sleep {
+    /* IN variables */
+    uint16_t pm1a_cnt_val;
+    uint16_t pm1b_cnt_val;
+    uint32_t sleep_state;       /* Which state to enter */
+    uint32_t video_flags;       /* S3_bios or s3_mode */
+    uint32_t video_mode;        /* Mode setting for s3_mode */
+};
+typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
+
 struct xen_platform_op {
     uint32_t cmd;
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -164,6 +176,7 @@ struct xen_platform_op {
         struct xenpf_microcode_update  microcode;
         struct xenpf_platform_quirk    platform_quirk;
         struct xenpf_firmware_info     firmware_info;
+        struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
         uint8_t                        pad[128];
     } u;
 };

[-- 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] 6+ messages in thread

* Re: [PATCH 4/4] Enable ACPI sleep in XenLinux
  2007-07-19 10:04 [PATCH 4/4] Enable ACPI sleep in XenLinux Tian, Kevin
@ 2007-07-19 10:29 ` Keir Fraser
  2007-07-19 13:12   ` Tian, Kevin
  0 siblings, 1 reply; 6+ messages in thread
From: Keir Fraser @ 2007-07-19 10:29 UTC (permalink / raw)
  To: Tian, Kevin; +Cc: xen-devel

On 19/7/07 11:04, "Tian, Kevin" <kevin.tian@intel.com> wrote:

> +    uint32_t video_flags;       /* S3_bios or s3_mode */
> +    uint32_t video_mode;        /* Mode setting for s3_mode */

I'd like this to be two three-way flags: video_bios_reset and
video_mode_reset. Each can be set to yes, no, or default.

Yes means force to true. No means force to false. Default means default Xen
policy (i.e., false unless changed by Xen command-line option
'acpi_sleep=').

If video_bios_reset is true, we call c000:0003.

If video_mode_reset is true, we reset video mode to what we set up at boot
time.

Anything other wakeup re-set should be done by dom0 itself.

 -- Keir

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

* RE: [PATCH 4/4] Enable ACPI sleep in XenLinux
  2007-07-19 10:29 ` Keir Fraser
@ 2007-07-19 13:12   ` Tian, Kevin
  2007-07-19 13:17     ` Keir Fraser
  0 siblings, 1 reply; 6+ messages in thread
From: Tian, Kevin @ 2007-07-19 13:12 UTC (permalink / raw)
  To: Keir Fraser; +Cc: xen-devel

>From: Keir Fraser [mailto:keir@xensource.com]
>Sent: 2007年7月19日 18:29
>
>On 19/7/07 11:04, "Tian, Kevin" <kevin.tian@intel.com> wrote:
>
>> +    uint32_t video_flags;       /* S3_bios or s3_mode */
>> +    uint32_t video_mode;        /* Mode setting for s3_mode */
>
>I'd like this to be two three-way flags: video_bios_reset and
>video_mode_reset. Each can be set to yes, no, or default.
>
>Yes means force to true. No means force to false. Default means default
>Xen
>policy (i.e., false unless changed by Xen command-line option
>'acpi_sleep=').
>
>If video_bios_reset is true, we call c000:0003.
>
>If video_mode_reset is true, we reset video mode to what we set up at
>boot
>time.
>
>Anything other wakeup re-set should be done by dom0 itself.
>
> -- Keir

Still I'm not inclined to this way by two reasons:
	- There's really no point to reset Xen's VGA mode since xen doesn't 
require to touch it.
	- As in another mail, we either need to support dom0 real mode to 
try dom0's re-set path, or write a new one. But either way seems not 
meaningful, does it? :-)

Thanks,
Kevin

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

* Re: [PATCH 4/4] Enable ACPI sleep in XenLinux
  2007-07-19 13:12   ` Tian, Kevin
@ 2007-07-19 13:17     ` Keir Fraser
  2007-07-19 13:24       ` Tian, Kevin
  2007-07-19 13:44       ` Alan Cox
  0 siblings, 2 replies; 6+ messages in thread
From: Keir Fraser @ 2007-07-19 13:17 UTC (permalink / raw)
  To: Tian, Kevin; +Cc: xen-devel

On 19/7/07 14:12, "Tian, Kevin" <kevin.tian@intel.com> wrote:

> Still I'm not inclined to this way by two reasons:
> - There's really no point to reset Xen's VGA mode since xen doesn't
> require to touch it.
> - As in another mail, we either need to support dom0 real mode to
> try dom0's re-set path, or write a new one. But either way seems not
> meaningful, does it? :-)

Doing vm86 or real-mode crap in dom0 itself is obviously not on. However,
currently Linux will only ever regurgitate Xen's original video mode. So the
video-mode field has no real user.

So... The video-mode stuff is removed for now. A flags field is added to the
platform hypercall so that something can be added later in a backwards
compatible manner if there is an actual user for it.

-- Keir

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

* RE: [PATCH 4/4] Enable ACPI sleep in XenLinux
  2007-07-19 13:17     ` Keir Fraser
@ 2007-07-19 13:24       ` Tian, Kevin
  2007-07-19 13:44       ` Alan Cox
  1 sibling, 0 replies; 6+ messages in thread
From: Tian, Kevin @ 2007-07-19 13:24 UTC (permalink / raw)
  To: Keir Fraser; +Cc: xen-devel

>From: Keir Fraser [mailto:keir@xensource.com]
>Sent: 2007年7月19日 21:17
>
>On 19/7/07 14:12, "Tian, Kevin" <kevin.tian@intel.com> wrote:
>
>> Still I'm not inclined to this way by two reasons:
>> - There's really no point to reset Xen's VGA mode since xen doesn't
>> require to touch it.
>> - As in another mail, we either need to support dom0 real mode to
>> try dom0's re-set path, or write a new one. But either way seems not
>> meaningful, does it? :-)
>
>Doing vm86 or real-mode crap in dom0 itself is obviously not on.
>However,
>currently Linux will only ever regurgitate Xen's original video mode. So
>the
>video-mode field has no real user.

OK, that's the current fact.

>
>So... The video-mode stuff is removed for now. A flags field is added to
>the
>platform hypercall so that something can be added later in a backwards
>compatible manner if there is an actual user for it.
>

Acceptable. Anyway now new platform is all expected to provide BIOS 
automatic VGA resume option before transitioning to wakeup vector.

Thanks,
Kevin

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

* Re: [PATCH 4/4] Enable ACPI sleep in XenLinux
  2007-07-19 13:17     ` Keir Fraser
  2007-07-19 13:24       ` Tian, Kevin
@ 2007-07-19 13:44       ` Alan Cox
  1 sibling, 0 replies; 6+ messages in thread
From: Alan Cox @ 2007-07-19 13:44 UTC (permalink / raw)
  To: Keir Fraser; +Cc: Tian, Kevin, xen-devel

> Doing vm86 or real-mode crap in dom0 itself is obviously not on. However,
> currently Linux will only ever regurgitate Xen's original video mode. So the
> video-mode field has no real user.

We do it all the time. In the Xen case the X server falls back to
emulation for the 16bit BIOS execution.

> 
> So... The video-mode stuff is removed for now. A flags field is added to the
> platform hypercall so that something can be added later in a backwards
> compatible manner if there is an actual user for it.

Seems sensible. And as you said earlier the kernel doesn't update its
idea of video mode. The BIOS code may update the BIOS idea of video mode
but I don't see how that matters at all.

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

end of thread, other threads:[~2007-07-19 13:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-19 10:04 [PATCH 4/4] Enable ACPI sleep in XenLinux Tian, Kevin
2007-07-19 10:29 ` Keir Fraser
2007-07-19 13:12   ` Tian, Kevin
2007-07-19 13:17     ` Keir Fraser
2007-07-19 13:24       ` Tian, Kevin
2007-07-19 13:44       ` Alan Cox

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.