diff options
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) | |||
118 | extern int acpi_suspend_lowlevel(void); | 117 | extern int acpi_suspend_lowlevel(void); |
119 | 118 | ||
120 | extern const unsigned char acpi_wakeup_code[]; | 119 | extern 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 */ |
124 | extern void acpi_reserve_wakeup_memory(void); | 122 | extern 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 | ||
29 | extern struct real_mode_header real_mode_header; | 33 | extern 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 | */ | ||
14 | extern const unsigned char x86_trampoline_start []; | ||
15 | extern const unsigned char x86_trampoline_end []; | ||
16 | extern unsigned char *x86_trampoline_base; | ||
17 | |||
18 | extern unsigned long init_rsp; | ||
19 | extern unsigned long initial_code; | ||
20 | extern unsigned long initial_gs; | ||
21 | |||
22 | extern void __init setup_trampolines(void); | ||
23 | |||
24 | extern const unsigned char trampoline_data[]; | ||
25 | extern 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 */ | ||
32 | static 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 | |||
35 | obj-y += pci-iommu_table.o | 35 | obj-y += pci-iommu_table.o |
36 | obj-y += resource.o | 36 | obj-y += resource.o |
37 | 37 | ||
38 | obj-y += trampoline.o trampoline_$(BITS).o | ||
39 | obj-y += realmode.o | 38 | obj-y += realmode.o |
40 | obj-y += process.o | 39 | obj-y += process.o |
41 | obj-y += i387.o xsave.o | 40 | obj-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 @@ | |||
1 | subdir- := realmode | ||
2 | |||
3 | obj-$(CONFIG_ACPI) += boot.o | 1 | obj-$(CONFIG_ACPI) += boot.o |
4 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o | 2 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o |
5 | 3 | ||
6 | ifneq ($(CONFIG_ACPI_PROCESSOR),) | 4 | ifneq ($(CONFIG_ACPI_PROCESSOR),) |
7 | obj-y += cstate.o | 5 | obj-y += cstate.o |
8 | endif | 6 | endif |
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 | |||
9 | always := wakeup.bin | ||
10 | targets := wakeup.elf wakeup.lds | ||
11 | |||
12 | wakeup-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. | ||
18 | wakeup-y += video-vga.o | ||
19 | wakeup-y += video-vesa.o | ||
20 | wakeup-y += video-bios.o | ||
21 | |||
22 | targets += $(wakeup-y) | ||
23 | |||
24 | bootsrc := $(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. | ||
31 | KBUILD_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) | ||
43 | KBUILD_CFLAGS += $(call cc-option, -m32) | ||
44 | KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ | ||
45 | GCOV_PROFILE := n | ||
46 | |||
47 | WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y)) | ||
48 | |||
49 | LDFLAGS_wakeup.elf := -T | ||
50 | |||
51 | CPPFLAGS_wakeup.lds += -P -C | ||
52 | |||
53 | $(obj)/wakeup.elf: $(obj)/wakeup.lds $(WAKEUP_OBJS) FORCE | ||
54 | $(call if_changed,ld) | ||
55 | |||
56 | OBJCOPYFLAGS_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 | |||
9 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | ||
10 | OUTPUT_ARCH(i386) | ||
11 | ENTRY(_start) | ||
12 | |||
13 | SECTIONS | ||
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 | ||
21 | unsigned long acpi_realmode_flags; | 22 | unsigned long acpi_realmode_flags; |
@@ -36,13 +37,9 @@ asmlinkage void acpi_enter_s3(void) | |||
36 | */ | 37 | */ |
37 | int acpi_suspend_lowlevel(void) | 38 | int 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 | ||
8 | extern unsigned long saved_video_mode; | 8 | extern unsigned long saved_video_mode; |
9 | extern long saved_magic; | 9 | extern 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 | ||
10 | acpi_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 | ||
30 | static void __init zap_identity_mappings(void) | 29 | static 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 | |||
8 | unsigned char *x86_trampoline_base; | ||
9 | |||
10 | void __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 | */ | ||
35 | static 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 | } | ||
42 | arch_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 | |||
41 | ENTRY(trampoline_data) | ||
42 | r_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 | ||
69 | boot_gdt_descr: | ||
70 | .word __BOOT_DS + 7 # gdt limit | ||
71 | .long boot_gdt - __PAGE_OFFSET # gdt base | ||
72 | |||
73 | boot_idt_descr: | ||
74 | .word 0 # idt limit = 0 | ||
75 | .long 0 # idt base = 0L | ||
76 | |||
77 | ENTRY(trampoline_status) | ||
78 | .long 0 | ||
79 | |||
80 | .globl trampoline_end | ||
81 | trampoline_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 | |||
39 | ENTRY(trampoline_data) | ||
40 | r_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 | ||
89 | startup_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 | ||
120 | startup_64: | ||
121 | # Now jump into the kernel using virtual addresses | ||
122 | movq $secondary_startup_64, %rax | ||
123 | jmp *%rax | ||
124 | |||
125 | .code16 | ||
126 | no_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; | ||
133 | tidt: | ||
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 | ||
140 | tgdt: | ||
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 | ||
147 | tgdt_end: | ||
148 | |||
149 | .balign 4 | ||
150 | startup_32_vector: | ||
151 | .long startup_32 - r_base | ||
152 | .word __KERNEL32_CS, 0 | ||
153 | |||
154 | .balign 4 | ||
155 | startup_64_vector: | ||
156 | .long startup_64 - r_base | ||
157 | .word __KERNEL_CS, 0 | ||
158 | |||
159 | .balign 4 | ||
160 | ENTRY(trampoline_status) | ||
161 | .long 0 | ||
162 | |||
163 | trampoline_stack: | ||
164 | .org 0x1000 | ||
165 | trampoline_stack_end: | ||
166 | ENTRY(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 | |||
171 | ENTRY(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 | |||
14 | realmode-y += header.o | 14 | realmode-y += header.o |
15 | realmode-$(CONFIG_X86_32) += reboot_32.o | 15 | realmode-$(CONFIG_X86_32) += reboot_32.o |
16 | realmode-y += trampoline_$(BITS).o | 16 | realmode-y += trampoline_$(BITS).o |
17 | realmode-$(CONFIG_ACPI_SLEEP) += wakeup/wakeup.o | ||
17 | 18 | ||
18 | targets += $(realmode-y) | 19 | targets += $(realmode-y) |
19 | 20 | ||
21 | $(obj)/wakeup/wakeup.o: FORCE | ||
22 | $(Q)$(MAKE) $(build)=$(obj)/wakeup $@ | ||
23 | |||
20 | REALMODE_OBJS = $(addprefix $(obj)/,$(realmode-y)) | 24 | REALMODE_OBJS = $(addprefix $(obj)/,$(realmode-y)) |
21 | 25 | ||
22 | sed-pasyms := -n -r -e 's/^([0-9a-fA-F]+) [ABCDGRSTVW] (.+)$$/pa_\2 = \2;/p' | 26 | sed-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 | ||
30 | END(real_mode_header) | 35 | END(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 | |||
9 | always := wakeup.o | ||
10 | |||
11 | wakeup-y += wakeup_asm.o wakemain.o video-mode.o | ||
12 | wakeup-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. | ||
18 | wakeup-y += video-vga.o | ||
19 | wakeup-y += video-vesa.o | ||
20 | wakeup-y += video-bios.o | ||
21 | |||
22 | targets += $(wakeup-y) | ||
23 | |||
24 | WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y)) | ||
25 | |||
26 | LDFLAGS_wakeup.o := -m elf_i386 -r | ||
27 | $(obj)/wakeup.o: $(WAKEUP_OBJS) FORCE | ||
28 | $(call if_changed,ld) | ||
29 | |||
30 | bootsrc := $(src)/../../../boot | ||
31 | |||
32 | ccflags-y += -D_WAKEUP -I$(srctree)/$(bootsrc) | ||
33 | asflags-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 */ |
13 | struct wakeup_header { | 13 | struct 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 |
21 | wakeup_header: | 16 | wakeup_header: |
22 | video_mode: .short 0 /* Video mode number */ | 17 | video_mode: .short 0 /* Video mode number */ |
23 | pmode_return: .byte 0x66, 0xea /* ljmpl */ | 18 | pmode_entry: .long 0 |
24 | .long 0 /* offset goes here */ | 19 | pmode_cs: .short __KERNEL_CS |
25 | .short __KERNEL_CS | ||
26 | pmode_cr0: .long 0 /* Saved %cr0 */ | 20 | pmode_cr0: .long 0 /* Saved %cr0 */ |
27 | pmode_cr3: .long 0 /* Saved %cr3 */ | 21 | pmode_cr3: .long 0 /* Saved %cr3 */ |
28 | pmode_cr4: .long 0 /* Saved %cr4 */ | 22 | pmode_cr4: .long 0 /* Saved %cr4 */ |
@@ -32,19 +26,20 @@ pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */ | |||
32 | pmode_behavior: .long 0 /* Wakeup behavior flags */ | 26 | pmode_behavior: .long 0 /* Wakeup behavior flags */ |
33 | realmode_flags: .long 0 | 27 | realmode_flags: .long 0 |
34 | real_magic: .long 0 | 28 | real_magic: .long 0 |
35 | trampoline_segment: .word 0 | ||
36 | _pad1: .byte 0 | ||
37 | wakeup_jmp: .byte 0xea /* ljmpw */ | ||
38 | wakeup_jmp_off: .word 3f | ||
39 | wakeup_jmp_seg: .word 0 | ||
40 | wakeup_gdt: .quad 0, 0, 0 | ||
41 | signature: .long WAKEUP_HEADER_SIGNATURE | 29 | signature: .long WAKEUP_HEADER_SIGNATURE |
30 | .size wakeup_header, .-wakeup_header | ||
42 | 31 | ||
43 | .text | 32 | .text |
44 | .code16 | 33 | .code16 |
45 | wakeup_code: | 34 | .globl wakeup_start |
35 | wakeup_start: | ||
36 | cli | ||
46 | cld | 37 | cld |
47 | 38 | ||
39 | .byte 0xea /* ljmpw */ | ||
40 | .word 3f | ||
41 | .word real_mode_seg | ||
42 | 3: | ||
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 |
58 | 1: ljmpw $8, $2f | ||
59 | 2: | 53 | 2: |
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 | ||
69 | 3: | 65 | 3: |
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 | ||
141 | bogus_real_magic: | 134 | bogus_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 | ||
151 | wakeup_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 = { | |||
91 | static int acpi_sleep_prepare(u32 acpi_state) | 93 | static 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(); |