WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 8/12] Enable ACPI sleep in Linux

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 8/12] Enable ACPI sleep in Linux
From: "Tian, Kevin" <kevin.tian@xxxxxxxxx>
Date: Tue, 15 May 2007 22:20:51 +0800
Delivery-date: Tue, 15 May 2007 07:19:29 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: AceW/Dzz0ZsRz4f5SR2wsybUGb5bEg==
Thread-topic: [PATCH 8/12] Enable ACPI sleep in Linux
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@xxxxxxxxx>
Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx>

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: enable_linux_acpi_sleep.patch
Description: enable_linux_acpi_sleep.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 8/12] Enable ACPI sleep in Linux, Tian, Kevin <=