aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/Kbuild2
-rw-r--r--arch/x86/include/asm/acpi.h2
-rw-r--r--arch/x86/include/asm/processor.h7
-rw-r--r--arch/x86/include/asm/realmode.h62
-rw-r--r--arch/x86/include/asm/trampoline.h39
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/acpi/Makefile9
-rw-r--r--arch/x86/kernel/acpi/realmode/.gitignore3
-rw-r--r--arch/x86/kernel/acpi/realmode/Makefile59
-rw-r--r--arch/x86/kernel/acpi/realmode/bioscall.S1
-rw-r--r--arch/x86/kernel/acpi/realmode/copy.S1
-rw-r--r--arch/x86/kernel/acpi/realmode/regs.c1
-rw-r--r--arch/x86/kernel/acpi/realmode/video-bios.c1
-rw-r--r--arch/x86/kernel/acpi/realmode/video-mode.c1
-rw-r--r--arch/x86/kernel/acpi/realmode/video-vesa.c1
-rw-r--r--arch/x86/kernel/acpi/realmode/video-vga.c1
-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/head_32.S5
-rw-r--r--arch/x86/kernel/head_64.S4
-rw-r--r--arch/x86/kernel/mpparse.c1
-rw-r--r--arch/x86/kernel/reboot.c25
-rw-r--r--arch/x86/kernel/setup.c6
-rw-r--r--arch/x86/kernel/smpboot.c18
-rw-r--r--arch/x86/kernel/tboot.c7
-rw-r--r--arch/x86/kernel/trampoline.c42
-rw-r--r--arch/x86/kernel/trampoline_32.S83
-rw-r--r--arch/x86/kernel/vmlinux.lds.S12
-rw-r--r--arch/x86/realmode/Makefile18
-rw-r--r--arch/x86/realmode/init.c115
-rw-r--r--arch/x86/realmode/rm/.gitignore3
-rw-r--r--arch/x86/realmode/rm/Makefile82
-rw-r--r--arch/x86/realmode/rm/bioscall.S1
-rw-r--r--arch/x86/realmode/rm/copy.S1
-rw-r--r--arch/x86/realmode/rm/header.S41
-rw-r--r--arch/x86/realmode/rm/realmode.h21
-rw-r--r--arch/x86/realmode/rm/realmode.lds.S76
-rw-r--r--arch/x86/realmode/rm/reboot_32.S (renamed from arch/x86/kernel/reboot_32.S)89
-rw-r--r--arch/x86/realmode/rm/regs.c1
-rw-r--r--arch/x86/realmode/rm/stack.S19
-rw-r--r--arch/x86/realmode/rm/trampoline_32.S74
-rw-r--r--arch/x86/realmode/rm/trampoline_64.S (renamed from arch/x86/kernel/trampoline_64.S)148
-rw-r--r--arch/x86/realmode/rm/trampoline_common.S7
-rw-r--r--arch/x86/realmode/rm/video-bios.c1
-rw-r--r--arch/x86/realmode/rm/video-mode.c1
-rw-r--r--arch/x86/realmode/rm/video-vesa.c1
-rw-r--r--arch/x86/realmode/rm/video-vga.c1
-rw-r--r--arch/x86/realmode/rm/wakemain.c (renamed from arch/x86/kernel/acpi/realmode/wakemain.c)3
-rw-r--r--arch/x86/realmode/rm/wakeup.h (renamed from arch/x86/kernel/acpi/realmode/wakeup.h)10
-rw-r--r--arch/x86/realmode/rm/wakeup_asm.S (renamed from arch/x86/kernel/acpi/realmode/wakeup.S)131
-rw-r--r--arch/x86/realmode/rmpiggy.S20
-rw-r--r--arch/x86/tools/relocs.c7
-rw-r--r--drivers/acpi/bgrt.c1
-rw-r--r--drivers/acpi/sleep.c8
-rw-r--r--drivers/xen/xen-acpi-processor.c1
59 files changed, 774 insertions, 613 deletions
diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild
index 0e9dec6cadd1..e5287d8517aa 100644
--- a/arch/x86/Kbuild
+++ b/arch/x86/Kbuild
@@ -1,4 +1,3 @@
1
2obj-$(CONFIG_KVM) += kvm/ 1obj-$(CONFIG_KVM) += kvm/
3 2
4# Xen paravirtualization support 3# Xen paravirtualization support
@@ -7,6 +6,7 @@ obj-$(CONFIG_XEN) += xen/
7# lguest paravirtualization support 6# lguest paravirtualization support
8obj-$(CONFIG_LGUEST_GUEST) += lguest/ 7obj-$(CONFIG_LGUEST_GUEST) += lguest/
9 8
9obj-y += realmode/
10obj-y += kernel/ 10obj-y += kernel/
11obj-y += mm/ 11obj-y += mm/
12 12
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/processor.h b/arch/x86/include/asm/processor.h
index 7745b257f035..39bc5777211a 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -544,13 +544,16 @@ static inline void load_sp0(struct tss_struct *tss,
544 * enable), so that any CPU's that boot up 544 * enable), so that any CPU's that boot up
545 * after us can get the correct flags. 545 * after us can get the correct flags.
546 */ 546 */
547extern unsigned long mmu_cr4_features; 547extern unsigned long mmu_cr4_features;
548extern u32 *trampoline_cr4_features;
548 549
549static inline void set_in_cr4(unsigned long mask) 550static inline void set_in_cr4(unsigned long mask)
550{ 551{
551 unsigned long cr4; 552 unsigned long cr4;
552 553
553 mmu_cr4_features |= mask; 554 mmu_cr4_features |= mask;
555 if (trampoline_cr4_features)
556 *trampoline_cr4_features = mmu_cr4_features;
554 cr4 = read_cr4(); 557 cr4 = read_cr4();
555 cr4 |= mask; 558 cr4 |= mask;
556 write_cr4(cr4); 559 write_cr4(cr4);
@@ -561,6 +564,8 @@ static inline void clear_in_cr4(unsigned long mask)
561 unsigned long cr4; 564 unsigned long cr4;
562 565
563 mmu_cr4_features &= ~mask; 566 mmu_cr4_features &= ~mask;
567 if (trampoline_cr4_features)
568 *trampoline_cr4_features = mmu_cr4_features;
564 cr4 = read_cr4(); 569 cr4 = read_cr4();
565 cr4 &= ~mask; 570 cr4 &= ~mask;
566 write_cr4(cr4); 571 write_cr4(cr4);
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
new file mode 100644
index 000000000000..fce3f4ae5bd6
--- /dev/null
+++ b/arch/x86/include/asm/realmode.h
@@ -0,0 +1,62 @@
1#ifndef _ARCH_X86_REALMODE_H
2#define _ARCH_X86_REALMODE_H
3
4#include <linux/types.h>
5#include <asm/io.h>
6
7/* This must match data at realmode.S */
8struct real_mode_header {
9 u32 text_start;
10 u32 ro_end;
11 /* SMP trampoline */
12 u32 trampoline_start;
13 u32 trampoline_status;
14 u32 trampoline_header;
15#ifdef CONFIG_X86_64
16 u32 trampoline_pgd;
17#endif
18 /* ACPI S3 wakeup */
19#ifdef CONFIG_ACPI_SLEEP
20 u32 wakeup_start;
21 u32 wakeup_header;
22#endif
23 /* APM/BIOS reboot */
24#ifdef CONFIG_X86_32
25 u32 machine_real_restart_asm;
26#endif
27};
28
29/* This must match data at trampoline_32/64.S */
30struct trampoline_header {
31#ifdef CONFIG_X86_32
32 u32 start;
33 u16 gdt_pad;
34 u16 gdt_limit;
35 u32 gdt_base;
36#else
37 u64 start;
38 u64 efer;
39 u32 cr4;
40#endif
41};
42
43extern struct real_mode_header *real_mode_header;
44extern unsigned char real_mode_blob_end[];
45
46extern unsigned long init_rsp;
47extern unsigned long initial_code;
48extern unsigned long initial_gs;
49
50extern unsigned char real_mode_blob[];
51extern unsigned char real_mode_relocs[];
52
53#ifdef CONFIG_X86_32
54extern unsigned char startup_32_smp[];
55extern unsigned char boot_gdt[];
56#else
57extern unsigned char secondary_startup_64[];
58#endif
59
60extern void __init setup_real_mode(void);
61
62#endif /* _ARCH_X86_REALMODE_H */
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 9bba5b79902b..8215e5652d97 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 += process.o 38obj-y += process.o
40obj-y += i387.o xsave.o 39obj-y += i387.o xsave.o
41obj-y += ptrace.o 40obj-y += ptrace.o
@@ -48,7 +47,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
48obj-y += cpu/ 47obj-y += cpu/
49obj-y += acpi/ 48obj-y += acpi/
50obj-y += reboot.o 49obj-y += reboot.o
51obj-$(CONFIG_X86_32) += reboot_32.o
52obj-$(CONFIG_X86_MSR) += msr.o 50obj-$(CONFIG_X86_MSR) += msr.o
53obj-$(CONFIG_X86_CPUID) += cpuid.o 51obj-$(CONFIG_X86_CPUID) += cpuid.o
54obj-$(CONFIG_PCI) += early-quirks.o 52obj-$(CONFIG_PCI) += early-quirks.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/.gitignore b/arch/x86/kernel/acpi/realmode/.gitignore
deleted file mode 100644
index 58f1f48a58f8..000000000000
--- a/arch/x86/kernel/acpi/realmode/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
1wakeup.bin
2wakeup.elf
3wakeup.lds
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/bioscall.S b/arch/x86/kernel/acpi/realmode/bioscall.S
deleted file mode 100644
index f51eb0bb56ce..000000000000
--- a/arch/x86/kernel/acpi/realmode/bioscall.S
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../boot/bioscall.S"
diff --git a/arch/x86/kernel/acpi/realmode/copy.S b/arch/x86/kernel/acpi/realmode/copy.S
deleted file mode 100644
index dc59ebee69d8..000000000000
--- a/arch/x86/kernel/acpi/realmode/copy.S
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../boot/copy.S"
diff --git a/arch/x86/kernel/acpi/realmode/regs.c b/arch/x86/kernel/acpi/realmode/regs.c
deleted file mode 100644
index 6206033ba202..000000000000
--- a/arch/x86/kernel/acpi/realmode/regs.c
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../boot/regs.c"
diff --git a/arch/x86/kernel/acpi/realmode/video-bios.c b/arch/x86/kernel/acpi/realmode/video-bios.c
deleted file mode 100644
index 7deabc144a27..000000000000
--- a/arch/x86/kernel/acpi/realmode/video-bios.c
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../boot/video-bios.c"
diff --git a/arch/x86/kernel/acpi/realmode/video-mode.c b/arch/x86/kernel/acpi/realmode/video-mode.c
deleted file mode 100644
index 328ad209f113..000000000000
--- a/arch/x86/kernel/acpi/realmode/video-mode.c
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../boot/video-mode.c"
diff --git a/arch/x86/kernel/acpi/realmode/video-vesa.c b/arch/x86/kernel/acpi/realmode/video-vesa.c
deleted file mode 100644
index 9dbb9672226a..000000000000
--- a/arch/x86/kernel/acpi/realmode/video-vesa.c
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../boot/video-vesa.c"
diff --git a/arch/x86/kernel/acpi/realmode/video-vga.c b/arch/x86/kernel/acpi/realmode/video-vga.c
deleted file mode 100644
index bcc81255f374..000000000000
--- a/arch/x86/kernel/acpi/realmode/video-vga.c
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../boot/video-vga.c"
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..95bf99de9058 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.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/head_32.S b/arch/x86/kernel/head_32.S
index 463c9797ca6a..d42ab17b7397 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -274,10 +274,7 @@ num_subarch_entries = (. - subarch_entries) / 4
274 * If cpu hotplug is not supported then this code can go in init section 274 * If cpu hotplug is not supported then this code can go in init section
275 * which will be freed later 275 * which will be freed later
276 */ 276 */
277
278__CPUINIT 277__CPUINIT
279
280#ifdef CONFIG_SMP
281ENTRY(startup_32_smp) 278ENTRY(startup_32_smp)
282 cld 279 cld
283 movl $(__BOOT_DS),%eax 280 movl $(__BOOT_DS),%eax
@@ -288,7 +285,7 @@ ENTRY(startup_32_smp)
288 movl pa(stack_start),%ecx 285 movl pa(stack_start),%ecx
289 movl %eax,%ss 286 movl %eax,%ss
290 leal -__PAGE_OFFSET(%ecx),%esp 287 leal -__PAGE_OFFSET(%ecx),%esp
291#endif /* CONFIG_SMP */ 288
292default_entry: 289default_entry:
293 290
294/* 291/*
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 7a40f2447321..94bf9cc2c7ee 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -139,10 +139,6 @@ ident_complete:
139 /* Fixup phys_base */ 139 /* Fixup phys_base */
140 addq %rbp, phys_base(%rip) 140 addq %rbp, phys_base(%rip)
141 141
142 /* Fixup trampoline */
143 addq %rbp, trampoline_level4_pgt + 0(%rip)
144 addq %rbp, trampoline_level4_pgt + (511*8)(%rip)
145
146 /* Due to ENTRY(), sometimes the empty space gets filled with 142 /* Due to ENTRY(), sometimes the empty space gets filled with
147 * zeros. Better take a jmp than relying on empty space being 143 * zeros. Better take a jmp than relying on empty space being
148 * filled with 0x90 (nop) 144 * filled with 0x90 (nop)
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index fbca2e6223bf..d2b56489d70f 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/reboot.c b/arch/x86/kernel/reboot.c
index 77215c23fba1..79c45af81604 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -24,6 +24,7 @@
24#ifdef CONFIG_X86_32 24#ifdef CONFIG_X86_32
25# include <linux/ctype.h> 25# include <linux/ctype.h>
26# include <linux/mc146818rtc.h> 26# include <linux/mc146818rtc.h>
27# include <asm/realmode.h>
27#else 28#else
28# include <asm/x86_init.h> 29# include <asm/x86_init.h>
29#endif 30#endif
@@ -156,15 +157,10 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)
156 return 0; 157 return 0;
157} 158}
158 159
159extern const unsigned char machine_real_restart_asm[];
160extern const u64 machine_real_restart_gdt[3];
161
162void machine_real_restart(unsigned int type) 160void machine_real_restart(unsigned int type)
163{ 161{
164 void *restart_va; 162 void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int))
165 unsigned long restart_pa; 163 real_mode_header->machine_real_restart_asm;
166 void (*restart_lowmem)(unsigned int);
167 u64 *lowmem_gdt;
168 164
169 local_irq_disable(); 165 local_irq_disable();
170 166
@@ -195,21 +191,6 @@ void machine_real_restart(unsigned int type)
195 * too. */ 191 * too. */
196 *((unsigned short *)0x472) = reboot_mode; 192 *((unsigned short *)0x472) = reboot_mode;
197 193
198 /* Patch the GDT in the low memory trampoline */
199 lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
200
201 restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
202 restart_pa = virt_to_phys(restart_va);
203 restart_lowmem = (void (*)(unsigned int))restart_pa;
204
205 /* GDT[0]: GDT self-pointer */
206 lowmem_gdt[0] =
207 (u64)(sizeof(machine_real_restart_gdt) - 1) +
208 ((u64)virt_to_phys(lowmem_gdt) << 16);
209 /* GDT[1]: 64K real mode code segment */
210 lowmem_gdt[1] =
211 GDT_ENTRY(0x009b, restart_pa, 0xffff);
212
213 /* Jump to the identity-mapped low memory code */ 194 /* Jump to the identity-mapped low memory code */
214 restart_lowmem(type); 195 restart_lowmem(type);
215} 196}
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 982e44f960db..16be6dc14db1 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -73,7 +73,7 @@
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> 76#include <asm/realmode.h>
77#include <asm/e820.h> 77#include <asm/e820.h>
78#include <asm/mpspec.h> 78#include <asm/mpspec.h>
79#include <asm/setup.h> 79#include <asm/setup.h>
@@ -909,7 +909,7 @@ void __init setup_arch(char **cmdline_p)
909 printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n", 909 printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
910 (max_pfn_mapped<<PAGE_SHIFT) - 1); 910 (max_pfn_mapped<<PAGE_SHIFT) - 1);
911 911
912 setup_trampolines(); 912 setup_real_mode();
913 913
914 init_gbpages(); 914 init_gbpages();
915 915
@@ -968,6 +968,8 @@ void __init setup_arch(char **cmdline_p)
968 if (boot_cpu_data.cpuid_level >= 0) { 968 if (boot_cpu_data.cpuid_level >= 0) {
969 /* A CPU has %cr4 if and only if it has CPUID */ 969 /* A CPU has %cr4 if and only if it has CPUID */
970 mmu_cr4_features = read_cr4(); 970 mmu_cr4_features = read_cr4();
971 if (trampoline_cr4_features)
972 *trampoline_cr4_features = mmu_cr4_features;
971 } 973 }
972 974
973#ifdef CONFIG_X86_32 975#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 433529e29be4..f56f96da77f5 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -57,7 +57,7 @@
57#include <asm/nmi.h> 57#include <asm/nmi.h>
58#include <asm/irq.h> 58#include <asm/irq.h>
59#include <asm/idle.h> 59#include <asm/idle.h>
60#include <asm/trampoline.h> 60#include <asm/realmode.h>
61#include <asm/cpu.h> 61#include <asm/cpu.h>
62#include <asm/numa.h> 62#include <asm/numa.h>
63#include <asm/pgtable.h> 63#include <asm/pgtable.h>
@@ -73,6 +73,8 @@
73#include <asm/smpboot_hooks.h> 73#include <asm/smpboot_hooks.h>
74#include <asm/i8259.h> 74#include <asm/i8259.h>
75 75
76#include <asm/realmode.h>
77
76/* State of each CPU */ 78/* State of each CPU */
77DEFINE_PER_CPU(int, cpu_state) = { 0 }; 79DEFINE_PER_CPU(int, cpu_state) = { 0 };
78 80
@@ -660,8 +662,12 @@ static void __cpuinit announce_cpu(int cpu, int apicid)
660 */ 662 */
661static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) 663static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
662{ 664{
665 volatile u32 *trampoline_status =
666 (volatile u32 *) __va(real_mode_header->trampoline_status);
667 /* start_ip had better be page-aligned! */
668 unsigned long start_ip = real_mode_header->trampoline_start;
669
663 unsigned long boot_error = 0; 670 unsigned long boot_error = 0;
664 unsigned long start_ip;
665 int timeout; 671 int timeout;
666 672
667 alternatives_smp_switch(1); 673 alternatives_smp_switch(1);
@@ -684,9 +690,6 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
684 initial_code = (unsigned long)start_secondary; 690 initial_code = (unsigned long)start_secondary;
685 stack_start = idle->thread.sp; 691 stack_start = idle->thread.sp;
686 692
687 /* start_ip had better be page-aligned! */
688 start_ip = trampoline_address();
689
690 /* So we see what's up */ 693 /* So we see what's up */
691 announce_cpu(cpu, apicid); 694 announce_cpu(cpu, apicid);
692 695
@@ -749,8 +752,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
749 pr_debug("CPU%d: has booted.\n", cpu); 752 pr_debug("CPU%d: has booted.\n", cpu);
750 } else { 753 } else {
751 boot_error = 1; 754 boot_error = 1;
752 if (*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status) 755 if (*trampoline_status == 0xA5A5A5A5)
753 == 0xA5A5A5A5)
754 /* trampoline started but...? */ 756 /* trampoline started but...? */
755 pr_err("CPU%d: Stuck ??\n", cpu); 757 pr_err("CPU%d: Stuck ??\n", cpu);
756 else 758 else
@@ -776,7 +778,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
776 } 778 }
777 779
778 /* mark "stuck" area as not stuck */ 780 /* mark "stuck" area as not stuck */
779 *(volatile u32 *)TRAMPOLINE_SYM(trampoline_status) = 0; 781 *trampoline_status = 0;
780 782
781 if (get_uv_system_type() != UV_NON_UNIQUE_APIC) { 783 if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
782 /* 784 /*
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 6410744ac5cb..f84fe00fad48 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>
@@ -44,7 +44,7 @@
44#include <asm/e820.h> 44#include <asm/e820.h>
45#include <asm/io.h> 45#include <asm/io.h>
46 46
47#include "acpi/realmode/wakeup.h" 47#include "../realmode/rm/wakeup.h"
48 48
49/* Global pointer to shared data; NULL means no measured launch. */ 49/* Global pointer to shared data; NULL means no measured launch. */
50struct tboot *tboot __read_mostly; 50struct tboot *tboot __read_mostly;
@@ -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/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/Makefile b/arch/x86/realmode/Makefile
new file mode 100644
index 000000000000..94f7fbe97b08
--- /dev/null
+++ b/arch/x86/realmode/Makefile
@@ -0,0 +1,18 @@
1#
2# arch/x86/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
10subdir- := rm
11
12obj-y += init.o
13obj-y += rmpiggy.o
14
15$(obj)/rmpiggy.o: $(obj)/rm/realmode.bin
16
17$(obj)/rm/realmode.bin: FORCE
18 $(Q)$(MAKE) $(build)=$(obj)/rm $@
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
new file mode 100644
index 000000000000..cbca565af5bd
--- /dev/null
+++ b/arch/x86/realmode/init.c
@@ -0,0 +1,115 @@
1#include <linux/io.h>
2#include <linux/memblock.h>
3
4#include <asm/cacheflush.h>
5#include <asm/pgtable.h>
6#include <asm/realmode.h>
7
8struct real_mode_header *real_mode_header;
9u32 *trampoline_cr4_features;
10
11void __init setup_real_mode(void)
12{
13 phys_addr_t mem;
14 u16 real_mode_seg;
15 u32 *rel;
16 u32 count;
17 u32 *ptr;
18 u16 *seg;
19 int i;
20 unsigned char *base;
21 struct trampoline_header *trampoline_header;
22 size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
23#ifdef CONFIG_X86_64
24 u64 *trampoline_pgd;
25 u64 efer;
26#endif
27
28 /* Has to be in very low memory so we can execute real-mode AP code. */
29 mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
30 if (!mem)
31 panic("Cannot allocate trampoline\n");
32
33 base = __va(mem);
34 memblock_reserve(mem, size);
35 real_mode_header = (struct real_mode_header *) base;
36 printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
37 base, (unsigned long long)mem, size);
38
39 memcpy(base, real_mode_blob, size);
40
41 real_mode_seg = __pa(base) >> 4;
42 rel = (u32 *) real_mode_relocs;
43
44 /* 16-bit segment relocations. */
45 count = rel[0];
46 rel = &rel[1];
47 for (i = 0; i < count; i++) {
48 seg = (u16 *) (base + rel[i]);
49 *seg = real_mode_seg;
50 }
51
52 /* 32-bit linear relocations. */
53 count = rel[i];
54 rel = &rel[i + 1];
55 for (i = 0; i < count; i++) {
56 ptr = (u32 *) (base + rel[i]);
57 *ptr += __pa(base);
58 }
59
60 /* Must be perfomed *after* relocation. */
61 trampoline_header = (struct trampoline_header *)
62 __va(real_mode_header->trampoline_header);
63
64#ifdef CONFIG_X86_32
65 trampoline_header->start = __pa(startup_32_smp);
66 trampoline_header->gdt_limit = __BOOT_DS + 7;
67 trampoline_header->gdt_base = __pa(boot_gdt);
68#else
69 /*
70 * Some AMD processors will #GP(0) if EFER.LMA is set in WRMSR
71 * so we need to mask it out.
72 */
73 rdmsrl(MSR_EFER, efer);
74 trampoline_header->efer = efer & ~EFER_LMA;
75
76 trampoline_header->start = (u64) secondary_startup_64;
77 trampoline_cr4_features = &trampoline_header->cr4;
78 *trampoline_cr4_features = read_cr4();
79
80 trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
81 trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE;
82 trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE;
83#endif
84}
85
86/*
87 * set_real_mode_permissions() gets called very early, to guarantee the
88 * availability of low memory. This is before the proper kernel page
89 * tables are set up, so we cannot set page permissions in that
90 * function. Thus, we use an arch_initcall instead.
91 */
92static int __init set_real_mode_permissions(void)
93{
94 unsigned char *base = (unsigned char *) real_mode_header;
95 size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
96
97 size_t ro_size =
98 PAGE_ALIGN(real_mode_header->ro_end) -
99 __pa(base);
100
101 size_t text_size =
102 PAGE_ALIGN(real_mode_header->ro_end) -
103 real_mode_header->text_start;
104
105 unsigned long text_start =
106 (unsigned long) __va(real_mode_header->text_start);
107
108 set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
109 set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
110 set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);
111
112 return 0;
113}
114
115arch_initcall(set_real_mode_permissions);
diff --git a/arch/x86/realmode/rm/.gitignore b/arch/x86/realmode/rm/.gitignore
new file mode 100644
index 000000000000..b6ed3a2555cb
--- /dev/null
+++ b/arch/x86/realmode/rm/.gitignore
@@ -0,0 +1,3 @@
1pasyms.h
2realmode.lds
3realmode.relocs
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
new file mode 100644
index 000000000000..5b84a2d30888
--- /dev/null
+++ b/arch/x86/realmode/rm/Makefile
@@ -0,0 +1,82 @@
1#
2# arch/x86/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
10always := realmode.bin realmode.relocs
11
12wakeup-objs := wakeup_asm.o wakemain.o video-mode.o
13wakeup-objs += copy.o bioscall.o regs.o
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-objs += video-vga.o
19wakeup-objs += video-vesa.o
20wakeup-objs += video-bios.o
21
22realmode-y += header.o
23realmode-y += trampoline_$(BITS).o
24realmode-y += stack.o
25realmode-$(CONFIG_X86_32) += reboot_32.o
26realmode-$(CONFIG_ACPI_SLEEP) += $(wakeup-objs)
27
28targets += $(realmode-y)
29
30REALMODE_OBJS = $(addprefix $(obj)/,$(realmode-y))
31
32sed-pasyms := -n -r -e 's/^([0-9a-fA-F]+) [ABCDGRSTVW] (.+)$$/pa_\2 = \2;/p'
33
34quiet_cmd_pasyms = PASYMS $@
35 cmd_pasyms = $(NM) $(filter-out FORCE,$^) | \
36 sed $(sed-pasyms) | sort | uniq > $@
37
38targets += pasyms.h
39$(obj)/pasyms.h: $(REALMODE_OBJS) FORCE
40 $(call if_changed,pasyms)
41
42targets += realmode.lds
43$(obj)/realmode.lds: $(obj)/pasyms.h
44
45LDFLAGS_realmode.elf := --emit-relocs -T
46CPPFLAGS_realmode.lds += -P -C -I$(obj)
47
48targets += realmode.elf
49$(obj)/realmode.elf: $(obj)/realmode.lds $(REALMODE_OBJS) FORCE
50 $(call if_changed,ld)
51
52OBJCOPYFLAGS_realmode.bin := -O binary
53
54targets += realmode.bin
55$(obj)/realmode.bin: $(obj)/realmode.elf $(obj)/realmode.relocs
56 $(call if_changed,objcopy)
57
58quiet_cmd_relocs = RELOCS $@
59 cmd_relocs = arch/x86/tools/relocs --realmode $< > $@
60
61targets += realmode.relocs
62$(obj)/realmode.relocs: $(obj)/realmode.elf FORCE
63 $(call if_changed,relocs)
64
65# ---------------------------------------------------------------------------
66
67# How to compile the 16-bit code. Note we always compile for -march=i386,
68# that way we can complain to the user if the CPU is insufficient.
69KBUILD_CFLAGS := $(LINUXINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ -D_WAKEUP \
70 -I$(srctree)/arch/x86/boot \
71 -DDISABLE_BRANCH_PROFILING \
72 -Wall -Wstrict-prototypes \
73 -march=i386 -mregparm=3 \
74 -include $(srctree)/$(src)/../../boot/code16gcc.h \
75 -fno-strict-aliasing -fomit-frame-pointer \
76 $(call cc-option, -ffreestanding) \
77 $(call cc-option, -fno-toplevel-reorder,\
78 $(call cc-option, -fno-unit-at-a-time)) \
79 $(call cc-option, -fno-stack-protector) \
80 $(call cc-option, -mpreferred-stack-boundary=2)
81KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
82GCOV_PROFILE := n
diff --git a/arch/x86/realmode/rm/bioscall.S b/arch/x86/realmode/rm/bioscall.S
new file mode 100644
index 000000000000..16162d197918
--- /dev/null
+++ b/arch/x86/realmode/rm/bioscall.S
@@ -0,0 +1 @@
#include "../../boot/bioscall.S"
diff --git a/arch/x86/realmode/rm/copy.S b/arch/x86/realmode/rm/copy.S
new file mode 100644
index 000000000000..b785e6f38fdd
--- /dev/null
+++ b/arch/x86/realmode/rm/copy.S
@@ -0,0 +1 @@
#include "../../boot/copy.S"
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
new file mode 100644
index 000000000000..fadf48378ada
--- /dev/null
+++ b/arch/x86/realmode/rm/header.S
@@ -0,0 +1,41 @@
1/*
2 * Real-mode blob header; this should match realmode.h and be
3 * readonly; for mutable data instead add pointers into the .data
4 * or .bss sections as appropriate.
5 */
6
7#include <linux/linkage.h>
8#include <asm/page_types.h>
9
10#include "realmode.h"
11
12 .section ".header", "a"
13
14 .balign 16
15GLOBAL(real_mode_header)
16 .long pa_text_start
17 .long pa_ro_end
18 /* SMP trampoline */
19 .long pa_trampoline_start
20 .long pa_trampoline_status
21 .long pa_trampoline_header
22#ifdef CONFIG_X86_64
23 .long pa_trampoline_pgd;
24#endif
25 /* ACPI S3 wakeup */
26#ifdef CONFIG_ACPI_SLEEP
27 .long pa_wakeup_start
28 .long pa_wakeup_header
29#endif
30 /* APM/BIOS reboot */
31#ifdef CONFIG_X86_32
32 .long pa_machine_real_restart_asm
33#endif
34END(real_mode_header)
35
36 /* End signature, used to verify integrity */
37 .section ".signature","a"
38 .balign 4
39GLOBAL(end_signature)
40 .long REALMODE_END_SIGNATURE
41END(end_signature)
diff --git a/arch/x86/realmode/rm/realmode.h b/arch/x86/realmode/rm/realmode.h
new file mode 100644
index 000000000000..d74cff6350ed
--- /dev/null
+++ b/arch/x86/realmode/rm/realmode.h
@@ -0,0 +1,21 @@
1#ifndef ARCH_X86_REALMODE_RM_REALMODE_H
2#define ARCH_X86_REALMODE_RM_REALMODE_H
3
4#ifdef __ASSEMBLY__
5
6/*
7 * 16-bit ljmpw to the real_mode_seg
8 *
9 * This must be open-coded since gas will choke on using a
10 * relocatable symbol for the segment portion.
11 */
12#define LJMPW_RM(to) .byte 0xea ; .word (to), real_mode_seg
13
14#endif /* __ASSEMBLY__ */
15
16/*
17 * Signature at the end of the realmode region
18 */
19#define REALMODE_END_SIGNATURE 0x65a22c82
20
21#endif /* ARCH_X86_REALMODE_RM_REALMODE_H */
diff --git a/arch/x86/realmode/rm/realmode.lds.S b/arch/x86/realmode/rm/realmode.lds.S
new file mode 100644
index 000000000000..86b2e8d6b1f1
--- /dev/null
+++ b/arch/x86/realmode/rm/realmode.lds.S
@@ -0,0 +1,76 @@
1/*
2 * realmode.lds.S
3 *
4 * Linker script for the real-mode code
5 */
6
7#include <asm/page_types.h>
8
9#undef i386
10
11OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
12OUTPUT_ARCH(i386)
13
14SECTIONS
15{
16 real_mode_seg = 0;
17
18 . = 0;
19 .header : {
20 pa_real_mode_base = .;
21 *(.header)
22 }
23
24 . = ALIGN(4);
25 .rodata : {
26 *(.rodata)
27 *(.rodata.*)
28 . = ALIGN(16);
29 video_cards = .;
30 *(.videocards)
31 video_cards_end = .;
32 }
33
34 . = ALIGN(PAGE_SIZE);
35 pa_text_start = .;
36 .text : {
37 *(.text)
38 *(.text.*)
39 }
40
41 .text32 : {
42 *(.text32)
43 *(.text32.*)
44 }
45
46 .text64 : {
47 *(.text64)
48 *(.text64.*)
49 }
50 pa_ro_end = .;
51
52 . = ALIGN(PAGE_SIZE);
53 .data : {
54 *(.data)
55 *(.data.*)
56 }
57
58 . = ALIGN(128);
59 .bss : {
60 *(.bss*)
61 }
62
63 /* End signature for integrity checking */
64 . = ALIGN(4);
65 .signature : {
66 *(.signature)
67 }
68
69 /DISCARD/ : {
70 *(.note*)
71 *(.debug*)
72 *(.eh_frame*)
73 }
74
75#include "pasyms.h"
76}
diff --git a/arch/x86/kernel/reboot_32.S b/arch/x86/realmode/rm/reboot_32.S
index 1d5c46df0d78..114044876b3d 100644
--- a/arch/x86/kernel/reboot_32.S
+++ b/arch/x86/realmode/rm/reboot_32.S
@@ -2,6 +2,7 @@
2#include <linux/init.h> 2#include <linux/init.h>
3#include <asm/segment.h> 3#include <asm/segment.h>
4#include <asm/page_types.h> 4#include <asm/page_types.h>
5#include "realmode.h"
5 6
6/* 7/*
7 * The following code and data reboots the machine by switching to real 8 * The following code and data reboots the machine by switching to real
@@ -13,34 +14,20 @@
13 * 14 *
14 * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax. 15 * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
15 */ 16 */
16 .section ".x86_trampoline","a" 17 .section ".text32", "ax"
17 .balign 16
18 .code32 18 .code32
19ENTRY(machine_real_restart_asm)
20r_base = .
21 /* Get our own relocated address */
22 call 1f
231: popl %ebx
24 subl $(1b - r_base), %ebx
25
26 /* Compute the equivalent real-mode segment */
27 movl %ebx, %ecx
28 shrl $4, %ecx
29
30 /* Patch post-real-mode segment jump */
31 movw (dispatch_table - r_base)(%ebx,%eax,2),%ax
32 movw %ax, (101f - r_base)(%ebx)
33 movw %cx, (102f - r_base)(%ebx)
34 19
20 .balign 16
21ENTRY(machine_real_restart_asm)
35 /* Set up the IDT for real mode. */ 22 /* Set up the IDT for real mode. */
36 lidtl (machine_real_restart_idt - r_base)(%ebx) 23 lidtl pa_machine_real_restart_idt
37 24
38 /* 25 /*
39 * Set up a GDT from which we can load segment descriptors for real 26 * Set up a GDT from which we can load segment descriptors for real
40 * mode. The GDT is not used in real mode; it is just needed here to 27 * mode. The GDT is not used in real mode; it is just needed here to
41 * prepare the descriptors. 28 * prepare the descriptors.
42 */ 29 */
43 lgdtl (machine_real_restart_gdt - r_base)(%ebx) 30 lgdtl pa_machine_real_restart_gdt
44 31
45 /* 32 /*
46 * Load the data segment registers with 16-bit compatible values 33 * Load the data segment registers with 16-bit compatible values
@@ -51,7 +38,7 @@ r_base = .
51 movl %ecx, %fs 38 movl %ecx, %fs
52 movl %ecx, %gs 39 movl %ecx, %gs
53 movl %ecx, %ss 40 movl %ecx, %ss
54 ljmpl $8, $1f - r_base 41 ljmpw $8, $1f
55 42
56/* 43/*
57 * This is 16-bit protected mode code to disable paging and the cache, 44 * This is 16-bit protected mode code to disable paging and the cache,
@@ -76,27 +63,29 @@ r_base = .
76 * 63 *
77 * Most of this work is probably excessive, but it is what is tested. 64 * Most of this work is probably excessive, but it is what is tested.
78 */ 65 */
66 .text
79 .code16 67 .code16
68
69 .balign 16
70machine_real_restart_asm16:
801: 711:
81 xorl %ecx, %ecx 72 xorl %ecx, %ecx
82 movl %cr0, %eax 73 movl %cr0, %edx
83 andl $0x00000011, %eax 74 andl $0x00000011, %edx
84 orl $0x60000000, %eax 75 orl $0x60000000, %edx
85 movl %eax, %cr0 76 movl %edx, %cr0
86 movl %ecx, %cr3 77 movl %ecx, %cr3
87 movl %cr0, %edx 78 movl %cr0, %edx
88 andl $0x60000000, %edx /* If no cache bits -> no wbinvd */ 79 testl $0x60000000, %edx /* If no cache bits -> no wbinvd */
89 jz 2f 80 jz 2f
90 wbinvd 81 wbinvd
912: 822:
92 andb $0x10, %al 83 andb $0x10, %dl
93 movl %eax, %cr0 84 movl %edx, %cr0
94 .byte 0xea /* ljmpw */ 85 LJMPW_RM(3f)
95101: .word 0 /* Offset */ 863:
96102: .word 0 /* Segment */ 87 andw %ax, %ax
97 88 jz bios
98bios:
99 ljmpw $0xf000, $0xfff0
100 89
101apm: 90apm:
102 movw $0x1000, %ax 91 movw $0x1000, %ax
@@ -106,26 +95,34 @@ apm:
106 movw $0x0001, %bx 95 movw $0x0001, %bx
107 movw $0x0003, %cx 96 movw $0x0003, %cx
108 int $0x15 97 int $0x15
98 /* This should never return... */
109 99
110END(machine_real_restart_asm) 100bios:
101 ljmpw $0xf000, $0xfff0
111 102
112 .balign 16 103 .section ".rodata", "a"
113 /* These must match <asm/reboot.h */
114dispatch_table:
115 .word bios - r_base
116 .word apm - r_base
117END(dispatch_table)
118 104
119 .balign 16 105 .balign 16
120machine_real_restart_idt: 106GLOBAL(machine_real_restart_idt)
121 .word 0xffff /* Length - real mode default value */ 107 .word 0xffff /* Length - real mode default value */
122 .long 0 /* Base - real mode default value */ 108 .long 0 /* Base - real mode default value */
123END(machine_real_restart_idt) 109END(machine_real_restart_idt)
124 110
125 .balign 16 111 .balign 16
126ENTRY(machine_real_restart_gdt) 112GLOBAL(machine_real_restart_gdt)
127 .quad 0 /* Self-pointer, filled in by PM code */ 113 /* Self-pointer */
128 .quad 0 /* 16-bit code segment, filled in by PM code */ 114 .word 0xffff /* Length - real mode default value */
115 .long pa_machine_real_restart_gdt
116 .word 0
117
118 /*
119 * 16-bit code segment pointing to real_mode_seg
120 * Selector value 8
121 */
122 .word 0xffff /* Limit */
123 .long 0x9b000000 + pa_real_mode_base
124 .word 0
125
129 /* 126 /*
130 * 16-bit data segment with the selector value 16 = 0x10 and 127 * 16-bit data segment with the selector value 16 = 0x10 and
131 * base value 0x100; since this is consistent with real mode 128 * base value 0x100; since this is consistent with real mode
diff --git a/arch/x86/realmode/rm/regs.c b/arch/x86/realmode/rm/regs.c
new file mode 100644
index 000000000000..fbb15b9f9ca9
--- /dev/null
+++ b/arch/x86/realmode/rm/regs.c
@@ -0,0 +1 @@
#include "../../boot/regs.c"
diff --git a/arch/x86/realmode/rm/stack.S b/arch/x86/realmode/rm/stack.S
new file mode 100644
index 000000000000..867ae87adfae
--- /dev/null
+++ b/arch/x86/realmode/rm/stack.S
@@ -0,0 +1,19 @@
1/*
2 * Common heap and stack allocations
3 */
4
5#include <linux/linkage.h>
6
7 .data
8GLOBAL(HEAP)
9 .long rm_heap
10GLOBAL(heap_end)
11 .long rm_stack
12
13 .bss
14 .balign 16
15GLOBAL(rm_heap)
16 .space 2048
17GLOBAL(rm_stack)
18 .space 2048
19GLOBAL(rm_stack_end)
diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S
new file mode 100644
index 000000000000..c1b2791183e7
--- /dev/null
+++ b/arch/x86/realmode/rm/trampoline_32.S
@@ -0,0 +1,74 @@
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_start, 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, we load CS to the physical segment
19 * of the real mode code before doing anything further.
20 */
21
22#include <linux/linkage.h>
23#include <linux/init.h>
24#include <asm/segment.h>
25#include <asm/page_types.h>
26#include "realmode.h"
27
28 .text
29 .code16
30
31 .balign PAGE_SIZE
32ENTRY(trampoline_start)
33 wbinvd # Needed for NUMA-Q should be harmless for others
34
35 LJMPW_RM(1f)
361:
37 mov %cs, %ax # Code and data in the same place
38 mov %ax, %ds
39
40 cli # We should be safe anyway
41
42 movl tr_start, %eax # where we need to go
43
44 movl $0xA5A5A5A5, trampoline_status
45 # write marker for master knows we're running
46
47 /*
48 * GDT tables in non default location kernel can be beyond 16MB and
49 * lgdt will not be able to load the address as in real mode default
50 * operand size is 16bit. Use lgdtl instead to force operand size
51 * to 32 bit.
52 */
53 lidtl tr_idt # load idt with 0, 0
54 lgdtl tr_gdt # load gdt with whatever is appropriate
55
56 movw $1, %dx # protected mode (PE) bit
57 lmsw %dx # into protected mode
58
59 ljmpl $__BOOT_CS, $pa_startup_32
60
61 .section ".text32","ax"
62 .code32
63ENTRY(startup_32) # note: also used from wakeup_asm.S
64 jmp *%eax
65
66 .bss
67 .balign 8
68GLOBAL(trampoline_header)
69 tr_start: .space 4
70 tr_gdt_pad: .space 2
71 tr_gdt: .space 6
72END(trampoline_header)
73
74#include "trampoline_common.S"
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index 09ff51799e96..bb360dc39d21 100644
--- a/arch/x86/kernel/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -5,12 +5,12 @@
5 * 4 Jan 1997 Michael Chastain: changed to gnu as. 5 * 4 Jan 1997 Michael Chastain: changed to gnu as.
6 * 15 Sept 2005 Eric Biederman: 64bit PIC support 6 * 15 Sept 2005 Eric Biederman: 64bit PIC support
7 * 7 *
8 * Entry: CS:IP point to the start of our code, we are 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 9 * in real mode with no stack, but the rest of the
10 * trampoline page to make our stack and everything else 10 * trampoline page to make our stack and everything else
11 * is a mystery. 11 * is a mystery.
12 * 12 *
13 * On entry to trampoline_data, the processor is in real mode 13 * On entry to trampoline_start, the processor is in real mode
14 * with 16-bit addressing and 16-bit data. CS has some value 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 15 * and IP is zero. Thus, data addresses need to be absolute
16 * (no relocation) and are taken with regard to r_base. 16 * (no relocation) and are taken with regard to r_base.
@@ -31,43 +31,33 @@
31#include <asm/msr.h> 31#include <asm/msr.h>
32#include <asm/segment.h> 32#include <asm/segment.h>
33#include <asm/processor-flags.h> 33#include <asm/processor-flags.h>
34#include "realmode.h"
34 35
35 .section ".x86_trampoline","a" 36 .text
36 .balign PAGE_SIZE
37 .code16 37 .code16
38 38
39ENTRY(trampoline_data) 39 .balign PAGE_SIZE
40r_base = . 40ENTRY(trampoline_start)
41 cli # We should be safe anyway 41 cli # We should be safe anyway
42 wbinvd 42 wbinvd
43
44 LJMPW_RM(1f)
451:
43 mov %cs, %ax # Code and data in the same place 46 mov %cs, %ax # Code and data in the same place
44 mov %ax, %ds 47 mov %ax, %ds
45 mov %ax, %es 48 mov %ax, %es
46 mov %ax, %ss 49 mov %ax, %ss
47 50
51 movl $0xA5A5A5A5, trampoline_status
52 # write marker for master knows we're running
48 53
49 movl $0xA5A5A5A5, trampoline_status - r_base 54 # Setup stack
50 # write marker for master knows we're running 55 movl $rm_stack_end, %esp
51
52 # Setup stack
53 movw $(trampoline_stack_end - r_base), %sp
54 56
55 call verify_cpu # Verify the cpu supports long mode 57 call verify_cpu # Verify the cpu supports long mode
56 testl %eax, %eax # Check for return code 58 testl %eax, %eax # Check for return code
57 jnz no_longmode 59 jnz no_longmode
58 60
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 /* 61 /*
72 * GDT tables in non default location kernel can be beyond 16MB and 62 * 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 63 * lgdt will not be able to load the address as in real mode default
@@ -75,36 +65,49 @@ r_base = .
75 * to 32 bit. 65 * to 32 bit.
76 */ 66 */
77 67
78 lidtl tidt - r_base # load idt with 0, 0 68 lidtl tr_idt # load idt with 0, 0
79 lgdtl tgdt - r_base # load gdt with whatever is appropriate 69 lgdtl tr_gdt # load gdt with whatever is appropriate
70
71 movw $__KERNEL_DS, %dx # Data segment descriptor
80 72
81 mov $X86_CR0_PE, %ax # protected mode (PE) bit 73 # Enable protected mode
82 lmsw %ax # into protected mode 74 movl $X86_CR0_PE, %eax # protected mode (PE) bit
75 movl %eax, %cr0 # into protected mode
83 76
84 # flush prefetch and jump to startup_32 77 # flush prefetch and jump to startup_32
85 ljmpl *(startup_32_vector - r_base) 78 ljmpl $__KERNEL32_CS, $pa_startup_32
86 79
80no_longmode:
81 hlt
82 jmp no_longmode
83#include "../kernel/verify_cpu.S"
84
85 .section ".text32","ax"
87 .code32 86 .code32
88 .balign 4 87 .balign 4
89startup_32: 88ENTRY(startup_32)
90 movl $__KERNEL_DS, %eax # Initialize the %ds segment register 89 movl %edx, %ss
91 movl %eax, %ds 90 addl $pa_real_mode_base, %esp
92 91 movl %edx, %ds
93 movl $X86_CR4_PAE, %eax 92 movl %edx, %es
93 movl %edx, %fs
94 movl %edx, %gs
95
96 movl pa_tr_cr4, %eax
94 movl %eax, %cr4 # Enable PAE mode 97 movl %eax, %cr4 # Enable PAE mode
95 98
96 # Setup trampoline 4 level pagetables 99 # Setup trampoline 4 level pagetables
97 leal (trampoline_level4_pgt - r_base)(%esi), %eax 100 movl $pa_trampoline_pgd, %eax
98 movl %eax, %cr3 101 movl %eax, %cr3
99 102
103 # Set up EFER
104 movl pa_tr_efer, %eax
105 movl pa_tr_efer + 4, %edx
100 movl $MSR_EFER, %ecx 106 movl $MSR_EFER, %ecx
101 movl $(1 << _EFER_LME), %eax # Enable Long Mode
102 xorl %edx, %edx
103 wrmsr 107 wrmsr
104 108
105 # Enable paging and in turn activate Long Mode 109 # Enable paging and in turn activate Long Mode
106 # Enable protected mode 110 movl $(X86_CR0_PG | X86_CR0_WP | X86_CR0_PE), %eax
107 movl $(X86_CR0_PG | X86_CR0_PE), %eax
108 movl %eax, %cr0 111 movl %eax, %cr0
109 112
110 /* 113 /*
@@ -113,59 +116,38 @@ startup_32:
113 * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use 116 * 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. 117 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
115 */ 118 */
116 ljmp *(startup_64_vector - r_base)(%esi) 119 ljmpl $__KERNEL_CS, $pa_startup_64
117 120
121 .section ".text64","ax"
118 .code64 122 .code64
119 .balign 4 123 .balign 4
120startup_64: 124ENTRY(startup_64)
121 # Now jump into the kernel using virtual addresses 125 # Now jump into the kernel using virtual addresses
122 movq $secondary_startup_64, %rax 126 jmpq *tr_start(%rip)
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 127
128 .section ".rodata","a"
137 # Duplicate the global descriptor table 129 # Duplicate the global descriptor table
138 # so the kernel can live anywhere 130 # so the kernel can live anywhere
139 .balign 4 131 .balign 16
140tgdt: 132 .globl tr_gdt
141 .short tgdt_end - tgdt # gdt limit 133tr_gdt:
142 .long tgdt - r_base 134 .short tr_gdt_end - tr_gdt - 1 # gdt limit
143 .short 0 135 .long pa_tr_gdt
136 .short 0
144 .quad 0x00cf9b000000ffff # __KERNEL32_CS 137 .quad 0x00cf9b000000ffff # __KERNEL32_CS
145 .quad 0x00af9b000000ffff # __KERNEL_CS 138 .quad 0x00af9b000000ffff # __KERNEL_CS
146 .quad 0x00cf93000000ffff # __KERNEL_DS 139 .quad 0x00cf93000000ffff # __KERNEL_DS
147tgdt_end: 140tr_gdt_end:
148 141
149 .balign 4 142 .bss
150startup_32_vector: 143 .balign PAGE_SIZE
151 .long startup_32 - r_base 144GLOBAL(trampoline_pgd) .space PAGE_SIZE
152 .word __KERNEL32_CS, 0
153 145
154 .balign 4 146 .balign 8
155startup_64_vector: 147GLOBAL(trampoline_header)
156 .long startup_64 - r_base 148 tr_start: .space 8
157 .word __KERNEL_CS, 0 149 GLOBAL(tr_efer) .space 8
150 GLOBAL(tr_cr4) .space 4
151END(trampoline_header)
158 152
159 .balign 4 153#include "trampoline_common.S"
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/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S
new file mode 100644
index 000000000000..b1ecdb9692ad
--- /dev/null
+++ b/arch/x86/realmode/rm/trampoline_common.S
@@ -0,0 +1,7 @@
1 .section ".rodata","a"
2 .balign 16
3tr_idt: .fill 1, 6, 0
4
5 .bss
6 .balign 4
7GLOBAL(trampoline_status) .space 4
diff --git a/arch/x86/realmode/rm/video-bios.c b/arch/x86/realmode/rm/video-bios.c
new file mode 100644
index 000000000000..848b25aaf11b
--- /dev/null
+++ b/arch/x86/realmode/rm/video-bios.c
@@ -0,0 +1 @@
#include "../../boot/video-bios.c"
diff --git a/arch/x86/realmode/rm/video-mode.c b/arch/x86/realmode/rm/video-mode.c
new file mode 100644
index 000000000000..2a98b7e2368b
--- /dev/null
+++ b/arch/x86/realmode/rm/video-mode.c
@@ -0,0 +1 @@
#include "../../boot/video-mode.c"
diff --git a/arch/x86/realmode/rm/video-vesa.c b/arch/x86/realmode/rm/video-vesa.c
new file mode 100644
index 000000000000..413edddb51e5
--- /dev/null
+++ b/arch/x86/realmode/rm/video-vesa.c
@@ -0,0 +1 @@
#include "../../boot/video-vesa.c"
diff --git a/arch/x86/realmode/rm/video-vga.c b/arch/x86/realmode/rm/video-vga.c
new file mode 100644
index 000000000000..3085f5c9d288
--- /dev/null
+++ b/arch/x86/realmode/rm/video-vga.c
@@ -0,0 +1 @@
#include "../../boot/video-vga.c"
diff --git a/arch/x86/kernel/acpi/realmode/wakemain.c b/arch/x86/realmode/rm/wakemain.c
index 883962d9eef2..91405d515ec6 100644
--- a/arch/x86/kernel/acpi/realmode/wakemain.c
+++ b/arch/x86/realmode/rm/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.h
index 97a29e1430e3..9317e0042f24 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.h
+++ b/arch/x86/realmode/rm/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
@@ -40,7 +33,6 @@ extern struct wakeup_header wakeup_header;
40 33
41#define WAKEUP_HEADER_OFFSET 8 34#define WAKEUP_HEADER_OFFSET 8
42#define WAKEUP_HEADER_SIGNATURE 0x51ee1111 35#define WAKEUP_HEADER_SIGNATURE 0x51ee1111
43#define WAKEUP_END_SIGNATURE 0x65a22c82
44 36
45/* Wakeup behavior bits */ 37/* Wakeup behavior bits */
46#define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 38#define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/realmode/rm/wakeup_asm.S
index b4fd836e4053..8905166b0bbb 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.S
+++ b/arch/x86/realmode/rm/wakeup_asm.S
@@ -1,50 +1,47 @@
1/* 1/*
2 * ACPI wakeup real mode startup stub 2 * ACPI wakeup real mode startup stub
3 */ 3 */
4#include <linux/linkage.h>
4#include <asm/segment.h> 5#include <asm/segment.h>
5#include <asm/msr-index.h> 6#include <asm/msr-index.h>
6#include <asm/page_types.h> 7#include <asm/page_types.h>
7#include <asm/pgtable_types.h> 8#include <asm/pgtable_types.h>
8#include <asm/processor-flags.h> 9#include <asm/processor-flags.h>
10#include "realmode.h"
9#include "wakeup.h" 11#include "wakeup.h"
10 12
11 .code16 13 .code16
12 .section ".jump", "ax"
13 .globl _start
14_start:
15 cli
16 jmp wakeup_code
17 14
18/* This should match the structure in wakeup.h */ 15/* This should match the structure in wakeup.h */
19 .section ".header", "a" 16 .section ".data", "aw"
20 .globl wakeup_header 17
21wakeup_header: 18 .balign 16
22video_mode: .short 0 /* Video mode number */ 19GLOBAL(wakeup_header)
23pmode_return: .byte 0x66, 0xea /* ljmpl */ 20 video_mode: .short 0 /* Video mode number */
24 .long 0 /* offset goes here */ 21 pmode_entry: .long 0
25 .short __KERNEL_CS 22 pmode_cs: .short __KERNEL_CS
26pmode_cr0: .long 0 /* Saved %cr0 */ 23 pmode_cr0: .long 0 /* Saved %cr0 */
27pmode_cr3: .long 0 /* Saved %cr3 */ 24 pmode_cr3: .long 0 /* Saved %cr3 */
28pmode_cr4: .long 0 /* Saved %cr4 */ 25 pmode_cr4: .long 0 /* Saved %cr4 */
29pmode_efer: .quad 0 /* Saved EFER */ 26 pmode_efer: .quad 0 /* Saved EFER */
30pmode_gdt: .quad 0 27 pmode_gdt: .quad 0
31pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */ 28 pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */
32pmode_behavior: .long 0 /* Wakeup behavior flags */ 29 pmode_behavior: .long 0 /* Wakeup behavior flags */
33realmode_flags: .long 0 30 realmode_flags: .long 0
34real_magic: .long 0 31 real_magic: .long 0
35trampoline_segment: .word 0 32 signature: .long WAKEUP_HEADER_SIGNATURE
36_pad1: .byte 0 33END(wakeup_header)
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
42 34
43 .text 35 .text
44 .code16 36 .code16
45wakeup_code: 37
38 .balign 16
39ENTRY(wakeup_start)
40 cli
46 cld 41 cld
47 42
43 LJMPW_RM(3f)
443:
48 /* Apparently some dimwit BIOS programmers don't know how to 45 /* Apparently some dimwit BIOS programmers don't know how to
49 program a PM to RM transition, and we might end up here with 46 program a PM to RM transition, and we might end up here with
50 junk in the data segment descriptor registers. The only way 47 junk in the data segment descriptor registers. The only way
@@ -54,8 +51,7 @@ wakeup_code:
54 movl %cr0, %eax 51 movl %cr0, %eax
55 orb $X86_CR0_PE, %al 52 orb $X86_CR0_PE, %al
56 movl %eax, %cr0 53 movl %eax, %cr0
57 jmp 1f 54 ljmpw $8, $2f
581: ljmpw $8, $2f
592: 552:
60 movw %cx, %ds 56 movw %cx, %ds
61 movw %cx, %es 57 movw %cx, %es
@@ -65,16 +61,18 @@ wakeup_code:
65 61
66 andb $~X86_CR0_PE, %al 62 andb $~X86_CR0_PE, %al
67 movl %eax, %cr0 63 movl %eax, %cr0
68 jmp wakeup_jmp 64 LJMPW_RM(3f)
693: 653:
70 /* Set up segments */ 66 /* Set up segments */
71 movw %cs, %ax 67 movw %cs, %ax
68 movw %ax, %ss
69 movl $rm_stack_end, %esp
72 movw %ax, %ds 70 movw %ax, %ds
73 movw %ax, %es 71 movw %ax, %es
74 movw %ax, %ss 72 movw %ax, %fs
75 lidtl wakeup_idt 73 movw %ax, %gs
76 74
77 movl $wakeup_stack_end, %esp 75 lidtl wakeup_idt
78 76
79 /* Clear the EFLAGS */ 77 /* Clear the EFLAGS */
80 pushl $0 78 pushl $0
@@ -87,7 +85,7 @@ wakeup_code:
87 85
88 /* Check we really have everything... */ 86 /* Check we really have everything... */
89 movl end_signature, %eax 87 movl end_signature, %eax
90 cmpl $WAKEUP_END_SIGNATURE, %eax 88 cmpl $REALMODE_END_SIGNATURE, %eax
91 jne bogus_real_magic 89 jne bogus_real_magic
92 90
93 /* Call the C code */ 91 /* Call the C code */
@@ -128,14 +126,13 @@ wakeup_code:
128 lgdtl pmode_gdt 126 lgdtl pmode_gdt
129 127
130 /* This really couldn't... */ 128 /* This really couldn't... */
131 movl pmode_cr0, %eax 129 movl pmode_entry, %eax
132 movl %eax, %cr0 130 movl pmode_cr0, %ecx
133 jmp pmode_return 131 movl %ecx, %cr0
132 ljmpl $__KERNEL_CS, $pa_startup_32
133 /* -> jmp *%eax in trampoline_32.S */
134#else 134#else
135 pushw $0 135 jmp trampoline_start
136 pushw trampoline_segment
137 pushw $0
138 lret
139#endif 136#endif
140 137
141bogus_real_magic: 138bogus_real_magic:
@@ -143,28 +140,38 @@ bogus_real_magic:
143 hlt 140 hlt
144 jmp 1b 141 jmp 1b
145 142
146 .data 143 .section ".rodata","a"
144
145 /*
146 * Set up the wakeup GDT. We set these up as Big Real Mode,
147 * that is, with limits set to 4 GB. At least the Lenovo
148 * Thinkpad X61 is known to need this for the video BIOS
149 * initialization quirk to work; this is likely to also
150 * be the case for other laptops or integrated video devices.
151 */
152
153 .balign 16
154GLOBAL(wakeup_gdt)
155 .word 3*8-1 /* Self-descriptor */
156 .long pa_wakeup_gdt
157 .word 0
158
159 .word 0xffff /* 16-bit code segment @ real_mode_base */
160 .long 0x9b000000 + pa_real_mode_base
161 .word 0x008f /* big real mode */
162
163 .word 0xffff /* 16-bit data segment @ real_mode_base */
164 .long 0x93000000 + pa_real_mode_base
165 .word 0x008f /* big real mode */
166END(wakeup_gdt)
167
168 .section ".rodata","a"
147 .balign 8 169 .balign 8
148 170
149 /* This is the standard real-mode IDT */ 171 /* This is the standard real-mode IDT */
150wakeup_idt: 172 .balign 16
173GLOBAL(wakeup_idt)
151 .word 0xffff /* limit */ 174 .word 0xffff /* limit */
152 .long 0 /* address */ 175 .long 0 /* address */
153 .word 0 176 .word 0
154 177END(wakeup_idt)
155 .globl HEAP, heap_end
156HEAP:
157 .long wakeup_heap
158heap_end:
159 .long wakeup_stack
160
161 .bss
162wakeup_heap:
163 .space 2048
164wakeup_stack:
165 .space 2048
166wakeup_stack_end:
167
168 .section ".signature","a"
169end_signature:
170 .long WAKEUP_END_SIGNATURE
diff --git a/arch/x86/realmode/rmpiggy.S b/arch/x86/realmode/rmpiggy.S
new file mode 100644
index 000000000000..204c6ece0e97
--- /dev/null
+++ b/arch/x86/realmode/rmpiggy.S
@@ -0,0 +1,20 @@
1/*
2 * Wrapper script for the realmode binary as a transport object
3 * before copying to low memory.
4 */
5#include <linux/linkage.h>
6#include <asm/page_types.h>
7
8 .section ".init.data","aw"
9
10 .balign PAGE_SIZE
11
12GLOBAL(real_mode_blob)
13 .incbin "arch/x86/realmode/rm/realmode.bin"
14END(real_mode_blob)
15
16GLOBAL(real_mode_blob_end);
17
18GLOBAL(real_mode_relocs)
19 .incbin "arch/x86/realmode/rm/realmode.relocs"
20END(real_mode_relocs)
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index b685296d4464..5a1847d61930 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -78,6 +78,13 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
78 78
79static const char * const sym_regex_realmode[S_NSYMTYPES] = { 79static const char * const sym_regex_realmode[S_NSYMTYPES] = {
80/* 80/*
81 * These symbols are known to be relative, even if the linker marks them
82 * as absolute (typically defined outside any section in the linker script.)
83 */
84 [S_REL] =
85 "^pa_",
86
87/*
81 * These are 16-bit segment symbols when compiling 16-bit code. 88 * These are 16-bit segment symbols when compiling 16-bit code.
82 */ 89 */
83 [S_SEG] = 90 [S_SEG] =
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
index 8cf6c46e99fb..6680df36b963 100644
--- a/drivers/acpi/bgrt.c
+++ b/drivers/acpi/bgrt.c
@@ -11,6 +11,7 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/device.h> 12#include <linux/device.h>
13#include <linux/sysfs.h> 13#include <linux/sysfs.h>
14#include <linux/io.h>
14#include <acpi/acpi.h> 15#include <acpi/acpi.h>
15#include <acpi/acpi_bus.h> 16#include <acpi/acpi_bus.h>
16 17
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 06527c526618..ebaa04593236 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();
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 0b48579a9cd6..7ff2569e17ae 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -29,6 +29,7 @@
29#include <acpi/acpi_drivers.h> 29#include <acpi/acpi_drivers.h>
30#include <acpi/processor.h> 30#include <acpi/processor.h>
31 31
32#include <xen/xen.h>
32#include <xen/interface/platform.h> 33#include <xen/interface/platform.h>
33#include <asm/xen/hypercall.h> 34#include <asm/xen/hypercall.h>
34 35