aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-12-06 14:58:56 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2010-12-14 10:48:40 -0800
commit2a113c19322e91af868b5d441cef1053ee622f4e (patch)
tree86111b0267f1aa004d7a2f3cbfa56dab59e4e1a5
parentca5bf9c69938d95b0915c420351bea990d0bf5f7 (diff)
downloadmrst-s0i3-test-2a113c19322e91af868b5d441cef1053ee622f4e.tar.gz
mrst-s0i3-test-2a113c19322e91af868b5d441cef1053ee622f4e.tar.xz
mrst-s0i3-test-2a113c19322e91af868b5d441cef1053ee622f4e.zip
s0i3: Make assembly code save and restore actually match
Make sure we save and restore the same things ;) and that we actually restore what we thing we should be restoring. Remove the stack image definition in a header file; C code doesn't need to know about this stuff.
-rw-r--r--drivers/idle/mrst_s0i3.h57
-rw-r--r--drivers/idle/mrst_s0i3_asm.S97
2 files changed, 87 insertions, 67 deletions
diff --git a/drivers/idle/mrst_s0i3.h b/drivers/idle/mrst_s0i3.h
index 960b7e3210f..ee6b1b2ba74 100644
--- a/drivers/idle/mrst_s0i3.h
+++ b/drivers/idle/mrst_s0i3.h
@@ -1,12 +1,22 @@
-/* -----------------------------------------------------------------------
+/*
+ * mrst_s0i3_asm.S - super-deep sleep state for the Moorestown MID platform
*
- * Copyright 2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright (c) 2010, Intel Corporation.
+ * H. Peter Anvin <hpa@linux.intel.com>
*
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2 or (at your
- * option) any later version; incorporated herein by reference.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
- * ----------------------------------------------------------------------- */
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
#ifndef MRST_S0I3_H
#define MRST_S0I3_H
@@ -18,41 +28,6 @@
#include <linux/types.h>
-struct mrst_s0i3_resume_stack {
- u32 eflags; /* 0 - eflags */
-
- u16 pgdt_pad; /* 4 - pad */
- u16 pgdt_len; /* 6 - GDT pointer (length) */
- u32 pgdt_ptr; /* 8 - GDT pointer (base - physical) */
-
- u64 misc_enable; /* 12 - MISC_ENABLE MSR */
-
- u64 efer; /* 12 - EFER MSR */
- u32 cr4; /* 20 - %cr4 */
- u32 cr0; /* 24 - %cr0 */
-
- u16 gdt_pad; /* 28 - pad */
- u16 gdt_len; /* 30 - GDT pointer (length) */
- u32 gdt_ptr; /* 32 - GDT pointer (base - linear) */
-
- u32 cr3; /* 36 - %cr3 */
- u32 fs; /* 40 - %fs */
- u32 gs; /* 44 - %gs */
-
- u16 idt_pad; /* 48 - pad */
- u16 idt_len; /* 50 - IDT pointer (length) */
- u32 idt_ptr; /* 52 - IDT pointer (base - linear) */
-
- u32 ldtr; /* 56 - %ldtr */
-
- u32 ebx; /* 60 - %ebx */
- u32 ebp; /* 64 - %ebp */
- u32 esi; /* 68 - %esi */
- u32 edi; /* 72 - %edi */
-
- u32 ret; /* 76 - return address */
-} __attribute__((packed));
-
int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
int mrst_s0i3_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
int mrst_s0i3_entry(void);
diff --git a/drivers/idle/mrst_s0i3_asm.S b/drivers/idle/mrst_s0i3_asm.S
index 6ad08b4fac2..35259c4ac4a 100644
--- a/drivers/idle/mrst_s0i3_asm.S
+++ b/drivers/idle/mrst_s0i3_asm.S
@@ -1,12 +1,22 @@
-/* -----------------------------------------------------------------------
+/*
+ * mrst_s0i3_asm.S - super-deep sleep state for the Moorestown MID platform
+ *
+ * Copyright (c) 2010, Intel Corporation.
+ * H. Peter Anvin <hpa@linux.intel.com>
*
- * Copyright 2010 Intel Corporation; author: H. Peter Anvin
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2 or (at your
- * option) any later version; incorporated herein by reference.
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * ----------------------------------------------------------------------- */
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
#include <linux/linkage.h>
#include <asm/asm.h>
@@ -29,6 +39,9 @@ ENTRY(mrst_s0i3_entry)
movl %esp, %esi
+ sldt %eax
+ pushl %eax
+
subl $8, %esp
sidtl 2(%esp)
@@ -52,10 +65,15 @@ ENTRY(mrst_s0i3_entry)
pushl %edx
pushl %eax
- movl (32-12)(%esp), %eax /* GDT base */
+ movl $(MSR_IA32_MISC_ENABLE), %ecx
+ rdmsr
+ pushl %edx
+ pushl %eax
+
+ movl 28(%esp), %eax /* GDT base */
subl $(__PAGE_OFFSET), %eax /* Convert to a physical address */
pushl %eax
- pushl (28-8)(%esp) /* GDT length, pad */
+ pushl 28(%esp) /* GDT length, pad */
pushfl
@@ -76,6 +94,7 @@ ENTRY(mrst_s0i3_entry)
/* If MWAIT wakes us up, assume something happened... */
cli
+ jmp simulate_resume
movl %esi, %esp
xorl %eax, %eax /* Not really S0i3 */
@@ -84,17 +103,41 @@ ENTRY(mrst_s0i3_entry)
popl %esi
popl %edi
ret
-END(mrst_s0i3_entry)
+ENDPROC(mrst_s0i3_entry)
/*
+ * Hack for testing: simulate a wakeup
+ */
+simulate_resume:
+ movl $pa(initial_page_table), %eax
+ movl %eax, %cr3
+ ljmpl $(__KERNEL_CS), $pa(1f)
+1:
+ movl %cr0, %eax
+ andl $~0x80000000, %eax
+ movl %eax, %cr0 /* Disable paging */
+
+ xorl %eax, %eax
+ movl %eax, %cr3
+ movl %eax, %cr4
+
+ xorl %edx, %edx
+ movl $(MSR_EFER), %ecx
+ wrmsr
+
+ lldt %ax
+ movl %eax, %esp
+
+ /* Fall through */
+/*
* After S0i3 the MRST firmare will put us back in 32-bit flat mode
*/
ENTRY(mrst_s0i3_resume)
cli
movl pa(mrst_s0i3_resume_stack), %esp
- popfl /* 0 - %eflags */
- lgdtl 2(%esp) /* 4 - physical GDT pointer */
+ popfl
+ lgdtl 2(%esp) /* Physical GDT pointer */
addl $8, %esp
movl $(__KERNEL_DS), %eax
@@ -104,46 +147,48 @@ ENTRY(mrst_s0i3_resume)
popl %eax
popl %edx
- movl $(MSR_IA32_MISC_ENABLE), %ecx /* 12 - MISC_ENABLE MSR */
+ movl $(MSR_IA32_MISC_ENABLE), %ecx
wrmsr
- popl %eax /* 12 - EFER */
+ popl %eax
popl %edx
movl $(MSR_EFER), %ecx
wrmsr
- popl %eax /* 20 - %cr4 */
+ popl %eax
movl %eax, %cr4
movl $pa(initial_page_table), %eax
movl %eax, %cr3
- popl %eax /* 24 - %cr0 */
+ popl %eax
movl %eax, %cr0 /* Enables paging! */
ljmpl $(__KERNEL_CS), $1f
1:
addl $__PAGE_OFFSET, %esp
- lgdtl 2(%esp) /* 32 - linear GDT pointer */
- popl %ebx /* 32 - GDT length + junk */
- popl %ebx /* 32 - linear address of GDT */
+ lgdtl 2(%esp) /* Linear GDT pointer */
+ popl %eax /* GDT length + junk */
+ popl %ebx /* Linear address of GDT */
- popl %eax /* 36 - %cr3 */
+ popl %eax
movl %eax, %cr3
movl $(GDT_ENTRY_TSS*8), %eax
- andb $~0x02, (GDT_ENTRY_TSS*8+5) /* Clear the TSS busy bit */
+
+ /* Clear the TSS busy bit: %ebx == GDT.base */
+ andb $~0x02, (GDT_ENTRY_TSS*8+5)(%ebx)
ltr %ax /* Set the TSS */
- popl %fs /* 40 - %fs */
- popl %gs /* 44 - %gs */
+ popl %fs
+ popl %gs
/* x86-64 would need to restore MSR_GS_BASE too */
- lidtl 2(%esp) /* 48 - IDT pointer */
+ lidtl 2(%esp)
addl $8, %esp
- popl %eax /* 56 - %ldtr */
+ popl %eax
lldt %ax
movl $1, %eax /* Resume from actual S0i3 */
@@ -153,10 +198,10 @@ ENTRY(mrst_s0i3_resume)
popl %edi
ret
-END(mrst_s0i3_resume)
+ENDPROC(mrst_s0i3_resume)
.bss
.balign 4
-ENTRY(mrst_s0i3_resume_stack)
+mrst_s0i3_resume_stack:
.space 4
END(mrst_s0i3_resume_stack)