aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/acpi.h2
-rw-r--r--arch/x86/include/asm/realmode.h4
-rw-r--r--arch/x86/include/asm/trampoline.h39
-rw-r--r--arch/x86/kernel/Makefile1
-rw-r--r--arch/x86/kernel/acpi/Makefile9
-rw-r--r--arch/x86/kernel/acpi/realmode/Makefile59
-rw-r--r--arch/x86/kernel/acpi/realmode/wakeup.lds.S62
-rw-r--r--arch/x86/kernel/acpi/sleep.c33
-rw-r--r--arch/x86/kernel/acpi/sleep.h2
-rw-r--r--arch/x86/kernel/acpi/wakeup_rm.S12
-rw-r--r--arch/x86/kernel/head32.c1
-rw-r--r--arch/x86/kernel/head64.c1
-rw-r--r--arch/x86/kernel/mpparse.c1
-rw-r--r--arch/x86/kernel/setup.c2
-rw-r--r--arch/x86/kernel/tboot.c5
-rw-r--r--arch/x86/kernel/trampoline.c42
-rw-r--r--arch/x86/kernel/trampoline_32.S83
-rw-r--r--arch/x86/kernel/trampoline_64.S171
-rw-r--r--arch/x86/kernel/vmlinux.lds.S12
-rw-r--r--arch/x86/realmode/rm/Makefile4
-rw-r--r--arch/x86/realmode/rm/header.S5
-rw-r--r--arch/x86/realmode/rm/realmode.lds.S4
-rw-r--r--arch/x86/realmode/rm/wakeup/.gitignore (renamed from arch/x86/kernel/acpi/realmode/.gitignore)0
-rw-r--r--arch/x86/realmode/rm/wakeup/Makefile33
-rw-r--r--arch/x86/realmode/rm/wakeup/bioscall.S (renamed from arch/x86/kernel/acpi/realmode/bioscall.S)0
-rw-r--r--arch/x86/realmode/rm/wakeup/copy.S (renamed from arch/x86/kernel/acpi/realmode/copy.S)0
-rw-r--r--arch/x86/realmode/rm/wakeup/regs.c (renamed from arch/x86/kernel/acpi/realmode/regs.c)0
-rw-r--r--arch/x86/realmode/rm/wakeup/video-bios.c (renamed from arch/x86/kernel/acpi/realmode/video-bios.c)0
-rw-r--r--arch/x86/realmode/rm/wakeup/video-mode.c (renamed from arch/x86/kernel/acpi/realmode/video-mode.c)0
-rw-r--r--arch/x86/realmode/rm/wakeup/video-vesa.c (renamed from arch/x86/kernel/acpi/realmode/video-vesa.c)0
-rw-r--r--arch/x86/realmode/rm/wakeup/video-vga.c (renamed from arch/x86/kernel/acpi/realmode/video-vga.c)0
-rw-r--r--arch/x86/realmode/rm/wakeup/wakemain.c (renamed from arch/x86/kernel/acpi/realmode/wakemain.c)3
-rw-r--r--arch/x86/realmode/rm/wakeup/wakeup.h (renamed from arch/x86/kernel/acpi/realmode/wakeup.h)9
-rw-r--r--arch/x86/realmode/rm/wakeup/wakeup_asm.S (renamed from arch/x86/kernel/acpi/realmode/wakeup.S)69
-rw-r--r--drivers/acpi/sleep.c8
35 files changed, 111 insertions, 565 deletions
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 610001d385dd..724aa441de7d 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -29,7 +29,6 @@
29#include <asm/processor.h> 29#include <asm/processor.h>
30#include <asm/mmu.h> 30#include <asm/mmu.h>
31#include <asm/mpspec.h> 31#include <asm/mpspec.h>
32#include <asm/trampoline.h>
33 32
34#define COMPILER_DEPENDENT_INT64 long long 33#define COMPILER_DEPENDENT_INT64 long long
35#define COMPILER_DEPENDENT_UINT64 unsigned long long 34#define COMPILER_DEPENDENT_UINT64 unsigned long long
@@ -118,7 +117,6 @@ static inline void acpi_disable_pci(void)
118extern int acpi_suspend_lowlevel(void); 117extern int acpi_suspend_lowlevel(void);
119 118
120extern const unsigned char acpi_wakeup_code[]; 119extern const unsigned char acpi_wakeup_code[];
121#define acpi_wakeup_address (__pa(TRAMPOLINE_SYM(acpi_wakeup_code)))
122 120
123/* early initialization routine */ 121/* early initialization routine */
124extern void acpi_reserve_wakeup_memory(void); 122extern void acpi_reserve_wakeup_memory(void);
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 9b4a5da5e22e..1bfc74d213a4 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -24,6 +24,10 @@ struct real_mode_header {
24 u32 level3_ident_pgt; 24 u32 level3_ident_pgt;
25 u32 level3_kernel_pgt; 25 u32 level3_kernel_pgt;
26#endif 26#endif
27#ifdef CONFIG_ACPI_SLEEP
28 u32 wakeup_start;
29 u32 wakeup_header;
30#endif
27} __attribute__((__packed__)); 31} __attribute__((__packed__));
28 32
29extern struct real_mode_header real_mode_header; 33extern struct real_mode_header real_mode_header;
diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h
deleted file mode 100644
index feca3118a73b..000000000000
--- a/arch/x86/include/asm/trampoline.h
+++ /dev/null
@@ -1,39 +0,0 @@
1#ifndef _ASM_X86_TRAMPOLINE_H
2#define _ASM_X86_TRAMPOLINE_H
3
4#ifndef __ASSEMBLY__
5
6#include <linux/types.h>
7#include <asm/io.h>
8
9/*
10 * Trampoline 80x86 program as an array. These are in the init rodata
11 * segment, but that's okay, because we only care about the relative
12 * addresses of the symbols.
13 */
14extern const unsigned char x86_trampoline_start [];
15extern const unsigned char x86_trampoline_end [];
16extern unsigned char *x86_trampoline_base;
17
18extern unsigned long init_rsp;
19extern unsigned long initial_code;
20extern unsigned long initial_gs;
21
22extern void __init setup_trampolines(void);
23
24extern const unsigned char trampoline_data[];
25extern const unsigned char trampoline_status[];
26
27#define TRAMPOLINE_SYM(x) \
28 ((void *)(x86_trampoline_base + \
29 ((const unsigned char *)(x) - x86_trampoline_start)))
30
31/* Address of the SMP trampoline */
32static inline unsigned long trampoline_address(void)
33{
34 return virt_to_phys(TRAMPOLINE_SYM(trampoline_data));
35}
36
37#endif /* __ASSEMBLY__ */
38
39#endif /* _ASM_X86_TRAMPOLINE_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index b71ef35c7d77..4a20f4441ffe 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -35,7 +35,6 @@ obj-y += tsc.o io_delay.o rtc.o
35obj-y += pci-iommu_table.o 35obj-y += pci-iommu_table.o
36obj-y += resource.o 36obj-y += resource.o
37 37
38obj-y += trampoline.o trampoline_$(BITS).o
39obj-y += realmode.o 38obj-y += realmode.o
40obj-y += process.o 39obj-y += process.o
41obj-y += i387.o xsave.o 40obj-y += i387.o xsave.o
diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
index 6f35260bb3ef..163b22581472 100644
--- a/arch/x86/kernel/acpi/Makefile
+++ b/arch/x86/kernel/acpi/Makefile
@@ -1,14 +1,7 @@
1subdir- := realmode
2
3obj-$(CONFIG_ACPI) += boot.o 1obj-$(CONFIG_ACPI) += boot.o
4obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o 2obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o
5 3
6ifneq ($(CONFIG_ACPI_PROCESSOR),) 4ifneq ($(CONFIG_ACPI_PROCESSOR),)
7obj-y += cstate.o 5obj-y += cstate.o
8endif 6endif
9 7
10$(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin
11
12$(obj)/realmode/wakeup.bin: FORCE
13 $(Q)$(MAKE) $(build)=$(obj)/realmode
14
diff --git a/arch/x86/kernel/acpi/realmode/Makefile b/arch/x86/kernel/acpi/realmode/Makefile
deleted file mode 100644
index 6a564ac67ef5..000000000000
--- a/arch/x86/kernel/acpi/realmode/Makefile
+++ /dev/null
@@ -1,59 +0,0 @@
1#
2# arch/x86/kernel/acpi/realmode/Makefile
3#
4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive
6# for more details.
7#
8
9always := wakeup.bin
10targets := wakeup.elf wakeup.lds
11
12wakeup-y += wakeup.o wakemain.o video-mode.o copy.o bioscall.o regs.o
13
14# The link order of the video-*.o modules can matter. In particular,
15# video-vga.o *must* be listed first, followed by video-vesa.o.
16# Hardware-specific drivers should follow in the order they should be
17# probed, and video-bios.o should typically be last.
18wakeup-y += video-vga.o
19wakeup-y += video-vesa.o
20wakeup-y += video-bios.o
21
22targets += $(wakeup-y)
23
24bootsrc := $(src)/../../../boot
25
26# ---------------------------------------------------------------------------
27
28# How to compile the 16-bit code. Note we always compile for -march=i386,
29# that way we can complain to the user if the CPU is insufficient.
30# Compile with _SETUP since this is similar to the boot-time setup code.
31KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D_WAKEUP -D__KERNEL__ \
32 -I$(srctree)/$(bootsrc) \
33 $(cflags-y) \
34 -Wall -Wstrict-prototypes \
35 -march=i386 -mregparm=3 \
36 -include $(srctree)/$(bootsrc)/code16gcc.h \
37 -fno-strict-aliasing -fomit-frame-pointer \
38 $(call cc-option, -ffreestanding) \
39 $(call cc-option, -fno-toplevel-reorder,\
40 $(call cc-option, -fno-unit-at-a-time)) \
41 $(call cc-option, -fno-stack-protector) \
42 $(call cc-option, -mpreferred-stack-boundary=2)
43KBUILD_CFLAGS += $(call cc-option, -m32)
44KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
45GCOV_PROFILE := n
46
47WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y))
48
49LDFLAGS_wakeup.elf := -T
50
51CPPFLAGS_wakeup.lds += -P -C
52
53$(obj)/wakeup.elf: $(obj)/wakeup.lds $(WAKEUP_OBJS) FORCE
54 $(call if_changed,ld)
55
56OBJCOPYFLAGS_wakeup.bin := -O binary
57
58$(obj)/wakeup.bin: $(obj)/wakeup.elf FORCE
59 $(call if_changed,objcopy)
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
deleted file mode 100644
index d4f8010a5b1b..000000000000
--- a/arch/x86/kernel/acpi/realmode/wakeup.lds.S
+++ /dev/null
@@ -1,62 +0,0 @@
1/*
2 * wakeup.ld
3 *
4 * Linker script for the real-mode wakeup code
5 */
6#undef i386
7#include "wakeup.h"
8
9OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
10OUTPUT_ARCH(i386)
11ENTRY(_start)
12
13SECTIONS
14{
15 . = 0;
16 .jump : {
17 *(.jump)
18 } = 0x90909090
19
20 . = WAKEUP_HEADER_OFFSET;
21 .header : {
22 *(.header)
23 }
24
25 . = ALIGN(16);
26 .text : {
27 *(.text*)
28 } = 0x90909090
29
30 . = ALIGN(16);
31 .rodata : {
32 *(.rodata*)
33 }
34
35 .videocards : {
36 video_cards = .;
37 *(.videocards)
38 video_cards_end = .;
39 }
40
41 . = ALIGN(16);
42 .data : {
43 *(.data*)
44 }
45
46 . = ALIGN(16);
47 .bss : {
48 __bss_start = .;
49 *(.bss)
50 __bss_end = .;
51 }
52
53 .signature : {
54 *(.signature)
55 }
56
57 _end = .;
58
59 /DISCARD/ : {
60 *(.note*)
61 }
62}
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 146a49c763a4..d941b62da4b6 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -14,8 +14,9 @@
14#include <asm/desc.h> 14#include <asm/desc.h>
15#include <asm/pgtable.h> 15#include <asm/pgtable.h>
16#include <asm/cacheflush.h> 16#include <asm/cacheflush.h>
17#include <asm/realmode.h>
17 18
18#include "realmode/wakeup.h" 19#include "../../realmode/rm/wakeup/wakeup.h"
19#include "sleep.h" 20#include "sleep.h"
20 21
21unsigned long acpi_realmode_flags; 22unsigned long acpi_realmode_flags;
@@ -36,13 +37,9 @@ asmlinkage void acpi_enter_s3(void)
36 */ 37 */
37int acpi_suspend_lowlevel(void) 38int acpi_suspend_lowlevel(void)
38{ 39{
39 struct wakeup_header *header; 40 struct wakeup_header *header =
40 /* address in low memory of the wakeup routine. */ 41 (struct wakeup_header *) __va(real_mode_header.wakeup_header);
41 char *acpi_realmode;
42 42
43 acpi_realmode = TRAMPOLINE_SYM(acpi_wakeup_code);
44
45 header = (struct wakeup_header *)(acpi_realmode + WAKEUP_HEADER_OFFSET);
46 if (header->signature != WAKEUP_HEADER_SIGNATURE) { 43 if (header->signature != WAKEUP_HEADER_SIGNATURE) {
47 printk(KERN_ERR "wakeup header does not match\n"); 44 printk(KERN_ERR "wakeup header does not match\n");
48 return -EINVAL; 45 return -EINVAL;
@@ -50,27 +47,6 @@ int acpi_suspend_lowlevel(void)
50 47
51 header->video_mode = saved_video_mode; 48 header->video_mode = saved_video_mode;
52 49
53 header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
54
55 /*
56 * Set up the wakeup GDT. We set these up as Big Real Mode,
57 * that is, with limits set to 4 GB. At least the Lenovo
58 * Thinkpad X61 is known to need this for the video BIOS
59 * initialization quirk to work; this is likely to also
60 * be the case for other laptops or integrated video devices.
61 */
62
63 /* GDT[0]: GDT self-pointer */
64 header->wakeup_gdt[0] =
65 (u64)(sizeof(header->wakeup_gdt) - 1) +
66 ((u64)__pa(&header->wakeup_gdt) << 16);
67 /* GDT[1]: big real mode-like code segment */
68 header->wakeup_gdt[1] =
69 GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
70 /* GDT[2]: big real mode-like data segment */
71 header->wakeup_gdt[2] =
72 GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff);
73
74#ifndef CONFIG_64BIT 50#ifndef CONFIG_64BIT
75 store_gdt((struct desc_ptr *)&header->pmode_gdt); 51 store_gdt((struct desc_ptr *)&header->pmode_gdt);
76 52
@@ -95,7 +71,6 @@ int acpi_suspend_lowlevel(void)
95 header->pmode_cr3 = (u32)__pa(&initial_page_table); 71 header->pmode_cr3 = (u32)__pa(&initial_page_table);
96 saved_magic = 0x12345678; 72 saved_magic = 0x12345678;
97#else /* CONFIG_64BIT */ 73#else /* CONFIG_64BIT */
98 header->trampoline_segment = trampoline_address() >> 4;
99#ifdef CONFIG_SMP 74#ifdef CONFIG_SMP
100 stack_start = (unsigned long)temp_stack + sizeof(temp_stack); 75 stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
101 early_gdt_descr.address = 76 early_gdt_descr.address =
diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h
index d68677a2a010..5653a5791ec9 100644
--- a/arch/x86/kernel/acpi/sleep.h
+++ b/arch/x86/kernel/acpi/sleep.h
@@ -2,8 +2,8 @@
2 * Variables and functions used by the code in sleep.c 2 * Variables and functions used by the code in sleep.c
3 */ 3 */
4 4
5#include <asm/trampoline.h>
6#include <linux/linkage.h> 5#include <linux/linkage.h>
6#include <asm/realmode.h>
7 7
8extern unsigned long saved_video_mode; 8extern unsigned long saved_video_mode;
9extern long saved_magic; 9extern long saved_magic;
diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S
deleted file mode 100644
index 63b8ab524f2c..000000000000
--- a/arch/x86/kernel/acpi/wakeup_rm.S
+++ /dev/null
@@ -1,12 +0,0 @@
1/*
2 * Wrapper script for the realmode binary as a transport object
3 * before copying to low memory.
4 */
5#include <asm/page_types.h>
6
7 .section ".x86_trampoline","a"
8 .balign PAGE_SIZE
9 .globl acpi_wakeup_code
10acpi_wakeup_code:
11 .incbin "arch/x86/kernel/acpi/realmode/wakeup.bin"
12 .size acpi_wakeup_code, .-acpi_wakeup_code
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 51ff18616d50..c18f59d10101 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -14,7 +14,6 @@
14#include <asm/sections.h> 14#include <asm/sections.h>
15#include <asm/e820.h> 15#include <asm/e820.h>
16#include <asm/page.h> 16#include <asm/page.h>
17#include <asm/trampoline.h>
18#include <asm/apic.h> 17#include <asm/apic.h>
19#include <asm/io_apic.h> 18#include <asm/io_apic.h>
20#include <asm/bios_ebda.h> 19#include <asm/bios_ebda.h>
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 3a3b779f41d3..037df57a99ac 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -24,7 +24,6 @@
24#include <asm/sections.h> 24#include <asm/sections.h>
25#include <asm/kdebug.h> 25#include <asm/kdebug.h>
26#include <asm/e820.h> 26#include <asm/e820.h>
27#include <asm/trampoline.h>
28#include <asm/bios_ebda.h> 27#include <asm/bios_ebda.h>
29 28
30static void __init zap_identity_mappings(void) 29static void __init zap_identity_mappings(void)
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index ca470e4c92dc..f44d31157353 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -27,7 +27,6 @@
27#include <asm/proto.h> 27#include <asm/proto.h>
28#include <asm/bios_ebda.h> 28#include <asm/bios_ebda.h>
29#include <asm/e820.h> 29#include <asm/e820.h>
30#include <asm/trampoline.h>
31#include <asm/setup.h> 30#include <asm/setup.h>
32#include <asm/smp.h> 31#include <asm/smp.h>
33 32
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 56e41242a6b8..7a14fece9cfc 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -73,7 +73,6 @@
73 73
74#include <asm/mtrr.h> 74#include <asm/mtrr.h>
75#include <asm/apic.h> 75#include <asm/apic.h>
76#include <asm/trampoline.h>
77#include <asm/realmode.h> 76#include <asm/realmode.h>
78#include <asm/e820.h> 77#include <asm/e820.h>
79#include <asm/mpspec.h> 78#include <asm/mpspec.h>
@@ -918,7 +917,6 @@ void __init setup_arch(char **cmdline_p)
918 printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n", 917 printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
919 max_pfn_mapped<<PAGE_SHIFT); 918 max_pfn_mapped<<PAGE_SHIFT);
920 919
921 setup_trampolines();
922 setup_real_mode(); 920 setup_real_mode();
923 921
924 init_gbpages(); 922 init_gbpages();
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 6410744ac5cb..c136e2325062 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -32,7 +32,7 @@
32#include <linux/mm.h> 32#include <linux/mm.h>
33#include <linux/tboot.h> 33#include <linux/tboot.h>
34 34
35#include <asm/trampoline.h> 35#include <asm/realmode.h>
36#include <asm/processor.h> 36#include <asm/processor.h>
37#include <asm/bootparam.h> 37#include <asm/bootparam.h>
38#include <asm/pgtable.h> 38#include <asm/pgtable.h>
@@ -201,7 +201,8 @@ static int tboot_setup_sleep(void)
201 add_mac_region(e820.map[i].addr, e820.map[i].size); 201 add_mac_region(e820.map[i].addr, e820.map[i].size);
202 } 202 }
203 203
204 tboot->acpi_sinfo.kernel_s3_resume_vector = acpi_wakeup_address; 204 tboot->acpi_sinfo.kernel_s3_resume_vector =
205 real_mode_header.wakeup_start;
205 206
206 return 0; 207 return 0;
207} 208}
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
deleted file mode 100644
index a73b61055ad6..000000000000
--- a/arch/x86/kernel/trampoline.c
+++ /dev/null
@@ -1,42 +0,0 @@
1#include <linux/io.h>
2#include <linux/memblock.h>
3
4#include <asm/trampoline.h>
5#include <asm/cacheflush.h>
6#include <asm/pgtable.h>
7
8unsigned char *x86_trampoline_base;
9
10void __init setup_trampolines(void)
11{
12 phys_addr_t mem;
13 size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
14
15 /* Has to be in very low memory so we can execute real-mode AP code. */
16 mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
17 if (!mem)
18 panic("Cannot allocate trampoline\n");
19
20 x86_trampoline_base = __va(mem);
21 memblock_reserve(mem, size);
22
23 printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
24 x86_trampoline_base, (unsigned long long)mem, size);
25
26 memcpy(x86_trampoline_base, x86_trampoline_start, size);
27}
28
29/*
30 * setup_trampolines() gets called very early, to guarantee the
31 * availability of low memory. This is before the proper kernel page
32 * tables are set up, so we cannot set page permissions in that
33 * function. Thus, we use an arch_initcall instead.
34 */
35static int __init configure_trampolines(void)
36{
37 size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
38
39 set_memory_x((unsigned long)x86_trampoline_base, size >> PAGE_SHIFT);
40 return 0;
41}
42arch_initcall(configure_trampolines);
diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
deleted file mode 100644
index 451c0a7ef7fd..000000000000
--- a/arch/x86/kernel/trampoline_32.S
+++ /dev/null
@@ -1,83 +0,0 @@
1/*
2 *
3 * Trampoline.S Derived from Setup.S by Linus Torvalds
4 *
5 * 4 Jan 1997 Michael Chastain: changed to gnu as.
6 *
7 * This is only used for booting secondary CPUs in SMP machine
8 *
9 * Entry: CS:IP point to the start of our code, we are
10 * in real mode with no stack, but the rest of the
11 * trampoline page to make our stack and everything else
12 * is a mystery.
13 *
14 * We jump into arch/x86/kernel/head_32.S.
15 *
16 * On entry to trampoline_data, the processor is in real mode
17 * with 16-bit addressing and 16-bit data. CS has some value
18 * and IP is zero. Thus, data addresses need to be absolute
19 * (no relocation) and are taken with regard to r_base.
20 *
21 * If you work on this file, check the object module with
22 * objdump --reloc to make sure there are no relocation
23 * entries except for:
24 *
25 * TYPE VALUE
26 * R_386_32 startup_32_smp
27 * R_386_32 boot_gdt
28 */
29
30#include <linux/linkage.h>
31#include <linux/init.h>
32#include <asm/segment.h>
33#include <asm/page_types.h>
34
35#ifdef CONFIG_SMP
36
37 .section ".x86_trampoline","a"
38 .balign PAGE_SIZE
39 .code16
40
41ENTRY(trampoline_data)
42r_base = .
43 wbinvd # Needed for NUMA-Q should be harmless for others
44 mov %cs, %ax # Code and data in the same place
45 mov %ax, %ds
46
47 cli # We should be safe anyway
48
49 movl $0xA5A5A5A5, trampoline_status - r_base
50 # write marker for master knows we're running
51
52 /* GDT tables in non default location kernel can be beyond 16MB and
53 * lgdt will not be able to load the address as in real mode default
54 * operand size is 16bit. Use lgdtl instead to force operand size
55 * to 32 bit.
56 */
57
58 lidtl boot_idt_descr - r_base # load idt with 0, 0
59 lgdtl boot_gdt_descr - r_base # load gdt with whatever is appropriate
60
61 xor %ax, %ax
62 inc %ax # protected mode (PE) bit
63 lmsw %ax # into protected mode
64 # flush prefetch and jump to startup_32_smp in arch/i386/kernel/head.S
65 ljmpl $__BOOT_CS, $(startup_32_smp-__PAGE_OFFSET)
66
67 # These need to be in the same 64K segment as the above;
68 # hence we don't use the boot_gdt_descr defined in head.S
69boot_gdt_descr:
70 .word __BOOT_DS + 7 # gdt limit
71 .long boot_gdt - __PAGE_OFFSET # gdt base
72
73boot_idt_descr:
74 .word 0 # idt limit = 0
75 .long 0 # idt base = 0L
76
77ENTRY(trampoline_status)
78 .long 0
79
80.globl trampoline_end
81trampoline_end:
82
83#endif /* CONFIG_SMP */
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
deleted file mode 100644
index 09ff51799e96..000000000000
--- a/arch/x86/kernel/trampoline_64.S
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 *
3 * Trampoline.S Derived from Setup.S by Linus Torvalds
4 *
5 * 4 Jan 1997 Michael Chastain: changed to gnu as.
6 * 15 Sept 2005 Eric Biederman: 64bit PIC support
7 *
8 * Entry: CS:IP point to the start of our code, we are
9 * in real mode with no stack, but the rest of the
10 * trampoline page to make our stack and everything else
11 * is a mystery.
12 *
13 * On entry to trampoline_data, the processor is in real mode
14 * with 16-bit addressing and 16-bit data. CS has some value
15 * and IP is zero. Thus, data addresses need to be absolute
16 * (no relocation) and are taken with regard to r_base.
17 *
18 * With the addition of trampoline_level4_pgt this code can
19 * now enter a 64bit kernel that lives at arbitrary 64bit
20 * physical addresses.
21 *
22 * If you work on this file, check the object module with objdump
23 * --full-contents --reloc to make sure there are no relocation
24 * entries.
25 */
26
27#include <linux/linkage.h>
28#include <linux/init.h>
29#include <asm/pgtable_types.h>
30#include <asm/page_types.h>
31#include <asm/msr.h>
32#include <asm/segment.h>
33#include <asm/processor-flags.h>
34
35 .section ".x86_trampoline","a"
36 .balign PAGE_SIZE
37 .code16
38
39ENTRY(trampoline_data)
40r_base = .
41 cli # We should be safe anyway
42 wbinvd
43 mov %cs, %ax # Code and data in the same place
44 mov %ax, %ds
45 mov %ax, %es
46 mov %ax, %ss
47
48
49 movl $0xA5A5A5A5, trampoline_status - r_base
50 # write marker for master knows we're running
51
52 # Setup stack
53 movw $(trampoline_stack_end - r_base), %sp
54
55 call verify_cpu # Verify the cpu supports long mode
56 testl %eax, %eax # Check for return code
57 jnz no_longmode
58
59 mov %cs, %ax
60 movzx %ax, %esi # Find the 32bit trampoline location
61 shll $4, %esi
62
63 # Fixup the absolute vectors
64 leal (startup_32 - r_base)(%esi), %eax
65 movl %eax, startup_32_vector - r_base
66 leal (startup_64 - r_base)(%esi), %eax
67 movl %eax, startup_64_vector - r_base
68 leal (tgdt - r_base)(%esi), %eax
69 movl %eax, (tgdt + 2 - r_base)
70
71 /*
72 * GDT tables in non default location kernel can be beyond 16MB and
73 * lgdt will not be able to load the address as in real mode default
74 * operand size is 16bit. Use lgdtl instead to force operand size
75 * to 32 bit.
76 */
77
78 lidtl tidt - r_base # load idt with 0, 0
79 lgdtl tgdt - r_base # load gdt with whatever is appropriate
80
81 mov $X86_CR0_PE, %ax # protected mode (PE) bit
82 lmsw %ax # into protected mode
83
84 # flush prefetch and jump to startup_32
85 ljmpl *(startup_32_vector - r_base)
86
87 .code32
88 .balign 4
89startup_32:
90 movl $__KERNEL_DS, %eax # Initialize the %ds segment register
91 movl %eax, %ds
92
93 movl $X86_CR4_PAE, %eax
94 movl %eax, %cr4 # Enable PAE mode
95
96 # Setup trampoline 4 level pagetables
97 leal (trampoline_level4_pgt - r_base)(%esi), %eax
98 movl %eax, %cr3
99
100 movl $MSR_EFER, %ecx
101 movl $(1 << _EFER_LME), %eax # Enable Long Mode
102 xorl %edx, %edx
103 wrmsr
104
105 # Enable paging and in turn activate Long Mode
106 # Enable protected mode
107 movl $(X86_CR0_PG | X86_CR0_PE), %eax
108 movl %eax, %cr0
109
110 /*
111 * At this point we're in long mode but in 32bit compatibility mode
112 * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
113 * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use
114 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
115 */
116 ljmp *(startup_64_vector - r_base)(%esi)
117
118 .code64
119 .balign 4
120startup_64:
121 # Now jump into the kernel using virtual addresses
122 movq $secondary_startup_64, %rax
123 jmp *%rax
124
125 .code16
126no_longmode:
127 hlt
128 jmp no_longmode
129#include "verify_cpu.S"
130
131 .balign 4
132 # Careful these need to be in the same 64K segment as the above;
133tidt:
134 .word 0 # idt limit = 0
135 .word 0, 0 # idt base = 0L
136
137 # Duplicate the global descriptor table
138 # so the kernel can live anywhere
139 .balign 4
140tgdt:
141 .short tgdt_end - tgdt # gdt limit
142 .long tgdt - r_base
143 .short 0
144 .quad 0x00cf9b000000ffff # __KERNEL32_CS
145 .quad 0x00af9b000000ffff # __KERNEL_CS
146 .quad 0x00cf93000000ffff # __KERNEL_DS
147tgdt_end:
148
149 .balign 4
150startup_32_vector:
151 .long startup_32 - r_base
152 .word __KERNEL32_CS, 0
153
154 .balign 4
155startup_64_vector:
156 .long startup_64 - r_base
157 .word __KERNEL_CS, 0
158
159 .balign 4
160ENTRY(trampoline_status)
161 .long 0
162
163trampoline_stack:
164 .org 0x1000
165trampoline_stack_end:
166ENTRY(trampoline_level4_pgt)
167 .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
168 .fill 510,8,0
169 .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
170
171ENTRY(trampoline_end)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 0f703f10901a..22a1530146a8 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -197,18 +197,6 @@ SECTIONS
197 197
198 INIT_DATA_SECTION(16) 198 INIT_DATA_SECTION(16)
199 199
200 /*
201 * Code and data for a variety of lowlevel trampolines, to be
202 * copied into base memory (< 1 MiB) during initialization.
203 * Since it is copied early, the main copy can be discarded
204 * afterwards.
205 */
206 .x86_trampoline : AT(ADDR(.x86_trampoline) - LOAD_OFFSET) {
207 x86_trampoline_start = .;
208 *(.x86_trampoline)
209 x86_trampoline_end = .;
210 }
211
212 .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { 200 .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
213 __x86_cpu_dev_start = .; 201 __x86_cpu_dev_start = .;
214 *(.x86_cpu_dev.init) 202 *(.x86_cpu_dev.init)
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
index 56ec64f94e69..2432acb6b04f 100644
--- a/arch/x86/realmode/rm/Makefile
+++ b/arch/x86/realmode/rm/Makefile
@@ -14,9 +14,13 @@ always := realmode.bin
14realmode-y += header.o 14realmode-y += header.o
15realmode-$(CONFIG_X86_32) += reboot_32.o 15realmode-$(CONFIG_X86_32) += reboot_32.o
16realmode-y += trampoline_$(BITS).o 16realmode-y += trampoline_$(BITS).o
17realmode-$(CONFIG_ACPI_SLEEP) += wakeup/wakeup.o
17 18
18targets += $(realmode-y) 19targets += $(realmode-y)
19 20
21$(obj)/wakeup/wakeup.o: FORCE
22 $(Q)$(MAKE) $(build)=$(obj)/wakeup $@
23
20REALMODE_OBJS = $(addprefix $(obj)/,$(realmode-y)) 24REALMODE_OBJS = $(addprefix $(obj)/,$(realmode-y))
21 25
22sed-pasyms := -n -r -e 's/^([0-9a-fA-F]+) [ABCDGRSTVW] (.+)$$/pa_\2 = \2;/p' 26sed-pasyms := -n -r -e 's/^([0-9a-fA-F]+) [ABCDGRSTVW] (.+)$$/pa_\2 = \2;/p'
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
index a97900409c61..730b1316c099 100644
--- a/arch/x86/realmode/rm/header.S
+++ b/arch/x86/realmode/rm/header.S
@@ -27,4 +27,9 @@ ENTRY(real_mode_header)
27 .long pa_level3_ident_pgt 27 .long pa_level3_ident_pgt
28 .long pa_level3_kernel_pgt 28 .long pa_level3_kernel_pgt
29#endif 29#endif
30 /* ACPI sleep */
31#ifdef CONFIG_ACPI_SLEEP
32 .long pa_wakeup_start
33 .long pa_wakeup_header
34#endif
30END(real_mode_header) 35END(real_mode_header)
diff --git a/arch/x86/realmode/rm/realmode.lds.S b/arch/x86/realmode/rm/realmode.lds.S
index c5b8a4f31ba3..91b83ea55c37 100644
--- a/arch/x86/realmode/rm/realmode.lds.S
+++ b/arch/x86/realmode/rm/realmode.lds.S
@@ -25,6 +25,10 @@ SECTIONS
25 .rodata : { 25 .rodata : {
26 *(.rodata) 26 *(.rodata)
27 *(.rodata.*) 27 *(.rodata.*)
28 . = ALIGN(16);
29 video_cards = .;
30 *(.videocards)
31 video_cards_end = .;
28 } 32 }
29 33
30 . = ALIGN(PAGE_SIZE); 34 . = ALIGN(PAGE_SIZE);
diff --git a/arch/x86/kernel/acpi/realmode/.gitignore b/arch/x86/realmode/rm/wakeup/.gitignore
index 58f1f48a58f8..58f1f48a58f8 100644
--- a/arch/x86/kernel/acpi/realmode/.gitignore
+++ b/arch/x86/realmode/rm/wakeup/.gitignore
diff --git a/arch/x86/realmode/rm/wakeup/Makefile b/arch/x86/realmode/rm/wakeup/Makefile
new file mode 100644
index 000000000000..4c8533240cdd
--- /dev/null
+++ b/arch/x86/realmode/rm/wakeup/Makefile
@@ -0,0 +1,33 @@
1#
2# arch/x86/kernel/acpi/realmode/Makefile
3#
4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive
6# for more details.
7#
8
9always := wakeup.o
10
11wakeup-y += wakeup_asm.o wakemain.o video-mode.o
12wakeup-y += copy.o bioscall.o regs.o
13
14# The link order of the video-*.o modules can matter. In particular,
15# video-vga.o *must* be listed first, followed by video-vesa.o.
16# Hardware-specific drivers should follow in the order they should be
17# probed, and video-bios.o should typically be last.
18wakeup-y += video-vga.o
19wakeup-y += video-vesa.o
20wakeup-y += video-bios.o
21
22targets += $(wakeup-y)
23
24WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y))
25
26LDFLAGS_wakeup.o := -m elf_i386 -r
27$(obj)/wakeup.o: $(WAKEUP_OBJS) FORCE
28 $(call if_changed,ld)
29
30bootsrc := $(src)/../../../boot
31
32ccflags-y += -D_WAKEUP -I$(srctree)/$(bootsrc)
33asflags-y += -D_WAKEUP -I$(srctree)/$(bootsrc)
diff --git a/arch/x86/kernel/acpi/realmode/bioscall.S b/arch/x86/realmode/rm/wakeup/bioscall.S
index f51eb0bb56ce..f51eb0bb56ce 100644
--- a/arch/x86/kernel/acpi/realmode/bioscall.S
+++ b/arch/x86/realmode/rm/wakeup/bioscall.S
diff --git a/arch/x86/kernel/acpi/realmode/copy.S b/arch/x86/realmode/rm/wakeup/copy.S
index dc59ebee69d8..dc59ebee69d8 100644
--- a/arch/x86/kernel/acpi/realmode/copy.S
+++ b/arch/x86/realmode/rm/wakeup/copy.S
diff --git a/arch/x86/kernel/acpi/realmode/regs.c b/arch/x86/realmode/rm/wakeup/regs.c
index 6206033ba202..6206033ba202 100644
--- a/arch/x86/kernel/acpi/realmode/regs.c
+++ b/arch/x86/realmode/rm/wakeup/regs.c
diff --git a/arch/x86/kernel/acpi/realmode/video-bios.c b/arch/x86/realmode/rm/wakeup/video-bios.c
index 7deabc144a27..7deabc144a27 100644
--- a/arch/x86/kernel/acpi/realmode/video-bios.c
+++ b/arch/x86/realmode/rm/wakeup/video-bios.c
diff --git a/arch/x86/kernel/acpi/realmode/video-mode.c b/arch/x86/realmode/rm/wakeup/video-mode.c
index 328ad209f113..328ad209f113 100644
--- a/arch/x86/kernel/acpi/realmode/video-mode.c
+++ b/arch/x86/realmode/rm/wakeup/video-mode.c
diff --git a/arch/x86/kernel/acpi/realmode/video-vesa.c b/arch/x86/realmode/rm/wakeup/video-vesa.c
index 9dbb9672226a..9dbb9672226a 100644
--- a/arch/x86/kernel/acpi/realmode/video-vesa.c
+++ b/arch/x86/realmode/rm/wakeup/video-vesa.c
diff --git a/arch/x86/kernel/acpi/realmode/video-vga.c b/arch/x86/realmode/rm/wakeup/video-vga.c
index bcc81255f374..bcc81255f374 100644
--- a/arch/x86/kernel/acpi/realmode/video-vga.c
+++ b/arch/x86/realmode/rm/wakeup/video-vga.c
diff --git a/arch/x86/kernel/acpi/realmode/wakemain.c b/arch/x86/realmode/rm/wakeup/wakemain.c
index 883962d9eef2..91405d515ec6 100644
--- a/arch/x86/kernel/acpi/realmode/wakemain.c
+++ b/arch/x86/realmode/rm/wakeup/wakemain.c
@@ -65,7 +65,8 @@ void main(void)
65{ 65{
66 /* Kill machine if structures are wrong */ 66 /* Kill machine if structures are wrong */
67 if (wakeup_header.real_magic != 0x12345678) 67 if (wakeup_header.real_magic != 0x12345678)
68 while (1); 68 while (1)
69 ;
69 70
70 if (wakeup_header.realmode_flags & 4) 71 if (wakeup_header.realmode_flags & 4)
71 send_morse("...-"); 72 send_morse("...-");
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/realmode/rm/wakeup/wakeup.h
index 97a29e1430e3..2dfaf06b8af1 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.h
+++ b/arch/x86/realmode/rm/wakeup/wakeup.h
@@ -12,9 +12,8 @@
12/* This must match data at wakeup.S */ 12/* This must match data at wakeup.S */
13struct wakeup_header { 13struct wakeup_header {
14 u16 video_mode; /* Video mode number */ 14 u16 video_mode; /* Video mode number */
15 u16 _jmp1; /* ljmpl opcode, 32-bit only */
16 u32 pmode_entry; /* Protected mode resume point, 32-bit only */ 15 u32 pmode_entry; /* Protected mode resume point, 32-bit only */
17 u16 _jmp2; /* CS value, 32-bit only */ 16 u16 pmode_cs;
18 u32 pmode_cr0; /* Protected mode cr0 */ 17 u32 pmode_cr0; /* Protected mode cr0 */
19 u32 pmode_cr3; /* Protected mode cr3 */ 18 u32 pmode_cr3; /* Protected mode cr3 */
20 u32 pmode_cr4; /* Protected mode cr4 */ 19 u32 pmode_cr4; /* Protected mode cr4 */
@@ -26,12 +25,6 @@ struct wakeup_header {
26 u32 pmode_behavior; /* Wakeup routine behavior flags */ 25 u32 pmode_behavior; /* Wakeup routine behavior flags */
27 u32 realmode_flags; 26 u32 realmode_flags;
28 u32 real_magic; 27 u32 real_magic;
29 u16 trampoline_segment; /* segment with trampoline code, 64-bit only */
30 u8 _pad1;
31 u8 wakeup_jmp;
32 u16 wakeup_jmp_off;
33 u16 wakeup_jmp_seg;
34 u64 wakeup_gdt[3];
35 u32 signature; /* To check we have correct structure */ 28 u32 signature; /* To check we have correct structure */
36} __attribute__((__packed__)); 29} __attribute__((__packed__));
37 30
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/realmode/rm/wakeup/wakeup_asm.S
index b4fd836e4053..b61126cb599e 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.S
+++ b/arch/x86/realmode/rm/wakeup/wakeup_asm.S
@@ -8,21 +8,15 @@
8#include <asm/processor-flags.h> 8#include <asm/processor-flags.h>
9#include "wakeup.h" 9#include "wakeup.h"
10 10
11 .code16 11 .code16
12 .section ".jump", "ax"
13 .globl _start
14_start:
15 cli
16 jmp wakeup_code
17 12
18/* This should match the structure in wakeup.h */ 13/* This should match the structure in wakeup.h */
19 .section ".header", "a" 14 .section ".data", "aw"
20 .globl wakeup_header 15 .globl wakeup_header
21wakeup_header: 16wakeup_header:
22video_mode: .short 0 /* Video mode number */ 17video_mode: .short 0 /* Video mode number */
23pmode_return: .byte 0x66, 0xea /* ljmpl */ 18pmode_entry: .long 0
24 .long 0 /* offset goes here */ 19pmode_cs: .short __KERNEL_CS
25 .short __KERNEL_CS
26pmode_cr0: .long 0 /* Saved %cr0 */ 20pmode_cr0: .long 0 /* Saved %cr0 */
27pmode_cr3: .long 0 /* Saved %cr3 */ 21pmode_cr3: .long 0 /* Saved %cr3 */
28pmode_cr4: .long 0 /* Saved %cr4 */ 22pmode_cr4: .long 0 /* Saved %cr4 */
@@ -32,19 +26,20 @@ pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */
32pmode_behavior: .long 0 /* Wakeup behavior flags */ 26pmode_behavior: .long 0 /* Wakeup behavior flags */
33realmode_flags: .long 0 27realmode_flags: .long 0
34real_magic: .long 0 28real_magic: .long 0
35trampoline_segment: .word 0
36_pad1: .byte 0
37wakeup_jmp: .byte 0xea /* ljmpw */
38wakeup_jmp_off: .word 3f
39wakeup_jmp_seg: .word 0
40wakeup_gdt: .quad 0, 0, 0
41signature: .long WAKEUP_HEADER_SIGNATURE 29signature: .long WAKEUP_HEADER_SIGNATURE
30 .size wakeup_header, .-wakeup_header
42 31
43 .text 32 .text
44 .code16 33 .code16
45wakeup_code: 34 .globl wakeup_start
35wakeup_start:
36 cli
46 cld 37 cld
47 38
39 .byte 0xea /* ljmpw */
40 .word 3f
41 .word real_mode_seg
423:
48 /* Apparently some dimwit BIOS programmers don't know how to 43 /* Apparently some dimwit BIOS programmers don't know how to
49 program a PM to RM transition, and we might end up here with 44 program a PM to RM transition, and we might end up here with
50 junk in the data segment descriptor registers. The only way 45 junk in the data segment descriptor registers. The only way
@@ -54,8 +49,7 @@ wakeup_code:
54 movl %cr0, %eax 49 movl %cr0, %eax
55 orb $X86_CR0_PE, %al 50 orb $X86_CR0_PE, %al
56 movl %eax, %cr0 51 movl %eax, %cr0
57 jmp 1f 52 ljmpw $8, $2f
581: ljmpw $8, $2f
592: 532:
60 movw %cx, %ds 54 movw %cx, %ds
61 movw %cx, %es 55 movw %cx, %es
@@ -65,7 +59,9 @@ wakeup_code:
65 59
66 andb $~X86_CR0_PE, %al 60 andb $~X86_CR0_PE, %al
67 movl %eax, %cr0 61 movl %eax, %cr0
68 jmp wakeup_jmp 62 .byte 0xea /* ljmpw */
63 .word 3f
64 .word real_mode_seg
693: 653:
70 /* Set up segments */ 66 /* Set up segments */
71 movw %cs, %ax 67 movw %cs, %ax
@@ -130,12 +126,9 @@ wakeup_code:
130 /* This really couldn't... */ 126 /* This really couldn't... */
131 movl pmode_cr0, %eax 127 movl pmode_cr0, %eax
132 movl %eax, %cr0 128 movl %eax, %cr0
133 jmp pmode_return 129 ljmpl *pmode_entry
134#else 130#else
135 pushw $0 131 jmp trampoline_data
136 pushw trampoline_segment
137 pushw $0
138 lret
139#endif 132#endif
140 133
141bogus_real_magic: 134bogus_real_magic:
@@ -143,6 +136,32 @@ bogus_real_magic:
143 hlt 136 hlt
144 jmp 1b 137 jmp 1b
145 138
139 .section ".rodata","a"
140
141 /*
142 * Set up the wakeup GDT. We set these up as Big Real Mode,
143 * that is, with limits set to 4 GB. At least the Lenovo
144 * Thinkpad X61 is known to need this for the video BIOS
145 * initialization quirk to work; this is likely to also
146 * be the case for other laptops or integrated video devices.
147 */
148
149 .globl wakeup_gdt
150 .balign 16
151wakeup_gdt:
152 .word 3*8-1 /* Self-descriptor */
153 .long pa_wakeup_gdt
154 .word 0
155
156 .word 0xffff /* 16-bit code segment @ real_mode_base */
157 .long 0x9b000000 + pa_real_mode_base
158 .word 0x008f /* big real mode */
159
160 .word 0xffff /* 16-bit data segment @ real_mode_base */
161 .long 0x93000000 + pa_real_mode_base
162 .word 0x008f /* big real mode */
163 .size wakeup_gdt, .-wakeup_gdt
164
146 .data 165 .data
147 .balign 8 166 .balign 8
148 167
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index eb6fd233764b..e77aa4a1c9f6 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -25,6 +25,8 @@
25#include <acpi/acpi_bus.h> 25#include <acpi/acpi_bus.h>
26#include <acpi/acpi_drivers.h> 26#include <acpi/acpi_drivers.h>
27 27
28#include <asm/realmode.h>
29
28#include "internal.h" 30#include "internal.h"
29#include "sleep.h" 31#include "sleep.h"
30 32
@@ -91,13 +93,13 @@ static struct notifier_block tts_notifier = {
91static int acpi_sleep_prepare(u32 acpi_state) 93static int acpi_sleep_prepare(u32 acpi_state)
92{ 94{
93#ifdef CONFIG_ACPI_SLEEP 95#ifdef CONFIG_ACPI_SLEEP
96 unsigned long wakeup_pa = real_mode_header.wakeup_start;
94 /* do we have a wakeup address for S2 and S3? */ 97 /* do we have a wakeup address for S2 and S3? */
95 if (acpi_state == ACPI_STATE_S3) { 98 if (acpi_state == ACPI_STATE_S3) {
96 if (!acpi_wakeup_address) { 99 if (!wakeup_pa)
97 return -EFAULT; 100 return -EFAULT;
98 }
99 acpi_set_firmware_waking_vector( 101 acpi_set_firmware_waking_vector(
100 (acpi_physical_address)acpi_wakeup_address); 102 (acpi_physical_address)wakeup_pa);
101 103
102 } 104 }
103 ACPI_FLUSH_CPU_CACHE(); 105 ACPI_FLUSH_CPU_CACHE();