aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/boot/Makefile2
-rw-r--r--arch/x86/boot/boot.h5
-rw-r--r--arch/x86/boot/video-bios.c6
-rw-r--r--arch/x86/boot/video-mode.c173
-rw-r--r--arch/x86/boot/video-vesa.c8
-rw-r--r--arch/x86/boot/video-vga.c12
-rw-r--r--arch/x86/boot/video.c157
-rw-r--r--arch/x86/kernel/acpi/Makefile9
-rw-r--r--arch/x86/kernel/acpi/realmode/Makefile57
-rw-r--r--arch/x86/kernel/acpi/realmode/copy.S1
-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/wakemain.c81
-rw-r--r--arch/x86/kernel/acpi/realmode/wakeup.S113
-rw-r--r--arch/x86/kernel/acpi/realmode/wakeup.h36
-rw-r--r--arch/x86/kernel/acpi/realmode/wakeup.lds.S61
-rw-r--r--arch/x86/kernel/acpi/sleep.c71
-rw-r--r--arch/x86/kernel/acpi/sleep.h16
-rw-r--r--arch/x86/kernel/acpi/sleep_32.c40
-rw-r--r--arch/x86/kernel/acpi/wakeup_32.S247
-rw-r--r--arch/x86/kernel/acpi/wakeup_64.S313
-rw-r--r--arch/x86/kernel/acpi/wakeup_rm.S10
-rw-r--r--arch/x86/kernel/e820_64.c5
-rw-r--r--arch/x86/kernel/head_64.S4
-rw-r--r--arch/x86/kernel/setup_32.c4
-rw-r--r--arch/x86/kernel/setup_64.c1
-rw-r--r--arch/x86/kernel/smpboot.c6
-rw-r--r--arch/x86/kernel/trampoline_64.S5
-rw-r--r--arch/x86/mach-voyager/voyager_smp.c1
32 files changed, 690 insertions, 760 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0a7193ae45e..4e32b6f7d31 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -181,7 +181,7 @@ config X86_BIOS_REBOOT
181 181
182config X86_TRAMPOLINE 182config X86_TRAMPOLINE
183 bool 183 bool
184 depends on X86_SMP || (X86_VOYAGER && SMP) 184 depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP)
185 default y 185 default y
186 186
187config KTIME_SCALAR 187config KTIME_SCALAR
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 9695affeb58..7ee102f9c4f 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -30,7 +30,7 @@ subdir- := compressed
30 30
31setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o 31setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
32setup-y += header.o main.o mca.o memory.o pm.o pmjump.o 32setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
33setup-y += printf.o string.o tty.o video.o version.o 33setup-y += printf.o string.o tty.o video.o video-mode.o version.o
34setup-$(CONFIG_X86_APM_BOOT) += apm.o 34setup-$(CONFIG_X86_APM_BOOT) += apm.o
35setup-$(CONFIG_X86_VOYAGER) += voyager.o 35setup-$(CONFIG_X86_VOYAGER) += voyager.o
36 36
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 7822a4983da..09578070bfb 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -286,6 +286,11 @@ int getchar_timeout(void);
286/* video.c */ 286/* video.c */
287void set_video(void); 287void set_video(void);
288 288
289/* video-mode.c */
290int set_mode(u16 mode);
291int mode_defined(u16 mode);
292void probe_cards(int unsafe);
293
289/* video-vesa.c */ 294/* video-vesa.c */
290void vesa_store_edid(void); 295void vesa_store_edid(void);
291 296
diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
index ff664a11709..39e247e9617 100644
--- a/arch/x86/boot/video-bios.c
+++ b/arch/x86/boot/video-bios.c
@@ -50,6 +50,7 @@ static int set_bios_mode(u8 mode)
50 if (new_mode == mode) 50 if (new_mode == mode)
51 return 0; /* Mode change OK */ 51 return 0; /* Mode change OK */
52 52
53#ifndef _WAKEUP
53 if (new_mode != boot_params.screen_info.orig_video_mode) { 54 if (new_mode != boot_params.screen_info.orig_video_mode) {
54 /* Mode setting failed, but we didn't end up where we 55 /* Mode setting failed, but we didn't end up where we
55 started. That's bad. Try to revert to the original 56 started. That's bad. Try to revert to the original
@@ -59,13 +60,18 @@ static int set_bios_mode(u8 mode)
59 : "+a" (ax) 60 : "+a" (ax)
60 : : "ebx", "ecx", "edx", "esi", "edi"); 61 : : "ebx", "ecx", "edx", "esi", "edi");
61 } 62 }
63#endif
62 return -1; 64 return -1;
63} 65}
64 66
65static int bios_probe(void) 67static int bios_probe(void)
66{ 68{
67 u8 mode; 69 u8 mode;
70#ifdef _WAKEUP
71 u8 saved_mode = 0x03;
72#else
68 u8 saved_mode = boot_params.screen_info.orig_video_mode; 73 u8 saved_mode = boot_params.screen_info.orig_video_mode;
74#endif
69 u16 crtc; 75 u16 crtc;
70 struct mode_info *mi; 76 struct mode_info *mi;
71 int nmodes = 0; 77 int nmodes = 0;
diff --git a/arch/x86/boot/video-mode.c b/arch/x86/boot/video-mode.c
new file mode 100644
index 00000000000..748e8d06290
--- /dev/null
+++ b/arch/x86/boot/video-mode.c
@@ -0,0 +1,173 @@
1/* -*- linux-c -*- ------------------------------------------------------- *
2 *
3 * Copyright (C) 1991, 1992 Linus Torvalds
4 * Copyright 2007-2008 rPath, Inc. - All Rights Reserved
5 *
6 * This file is part of the Linux kernel, and is made available under
7 * the terms of the GNU General Public License version 2.
8 *
9 * ----------------------------------------------------------------------- */
10
11/*
12 * arch/i386/boot/video-mode.c
13 *
14 * Set the video mode. This is separated out into a different
15 * file in order to be shared with the ACPI wakeup code.
16 */
17
18#include "boot.h"
19#include "video.h"
20#include "vesa.h"
21
22/*
23 * Common variables
24 */
25int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
26u16 video_segment;
27int force_x, force_y; /* Don't query the BIOS for cols/rows */
28
29int do_restore; /* Screen contents changed during mode flip */
30int graphic_mode; /* Graphic mode with linear frame buffer */
31
32/* Probe the video drivers and have them generate their mode lists. */
33void probe_cards(int unsafe)
34{
35 struct card_info *card;
36 static u8 probed[2];
37
38 if (probed[unsafe])
39 return;
40
41 probed[unsafe] = 1;
42
43 for (card = video_cards; card < video_cards_end; card++) {
44 if (card->unsafe == unsafe) {
45 if (card->probe)
46 card->nmodes = card->probe();
47 else
48 card->nmodes = 0;
49 }
50 }
51}
52
53/* Test if a mode is defined */
54int mode_defined(u16 mode)
55{
56 struct card_info *card;
57 struct mode_info *mi;
58 int i;
59
60 for (card = video_cards; card < video_cards_end; card++) {
61 mi = card->modes;
62 for (i = 0; i < card->nmodes; i++, mi++) {
63 if (mi->mode == mode)
64 return 1;
65 }
66 }
67
68 return 0;
69}
70
71/* Set mode (without recalc) */
72static int raw_set_mode(u16 mode, u16 *real_mode)
73{
74 int nmode, i;
75 struct card_info *card;
76 struct mode_info *mi;
77
78 /* Drop the recalc bit if set */
79 mode &= ~VIDEO_RECALC;
80
81 /* Scan for mode based on fixed ID, position, or resolution */
82 nmode = 0;
83 for (card = video_cards; card < video_cards_end; card++) {
84 mi = card->modes;
85 for (i = 0; i < card->nmodes; i++, mi++) {
86 int visible = mi->x || mi->y;
87
88 if ((mode == nmode && visible) ||
89 mode == mi->mode ||
90 mode == (mi->y << 8)+mi->x) {
91 *real_mode = mi->mode;
92 return card->set_mode(mi);
93 }
94
95 if (visible)
96 nmode++;
97 }
98 }
99
100 /* Nothing found? Is it an "exceptional" (unprobed) mode? */
101 for (card = video_cards; card < video_cards_end; card++) {
102 if (mode >= card->xmode_first &&
103 mode < card->xmode_first+card->xmode_n) {
104 struct mode_info mix;
105 *real_mode = mix.mode = mode;
106 mix.x = mix.y = 0;
107 return card->set_mode(&mix);
108 }
109 }
110
111 /* Otherwise, failure... */
112 return -1;
113}
114
115/*
116 * Recalculate the vertical video cutoff (hack!)
117 */
118static void vga_recalc_vertical(void)
119{
120 unsigned int font_size, rows;
121 u16 crtc;
122 u8 pt, ov;
123
124 set_fs(0);
125 font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
126 rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
127
128 rows *= font_size; /* Visible scan lines */
129 rows--; /* ... minus one */
130
131 crtc = vga_crtc();
132
133 pt = in_idx(crtc, 0x11);
134 pt &= ~0x80; /* Unlock CR0-7 */
135 out_idx(pt, crtc, 0x11);
136
137 out_idx((u8)rows, crtc, 0x12); /* Lower height register */
138
139 ov = in_idx(crtc, 0x07); /* Overflow register */
140 ov &= 0xbd;
141 ov |= (rows >> (8-1)) & 0x02;
142 ov |= (rows >> (9-6)) & 0x40;
143 out_idx(ov, crtc, 0x07);
144}
145
146/* Set mode (with recalc if specified) */
147int set_mode(u16 mode)
148{
149 int rv;
150 u16 real_mode;
151
152 /* Very special mode numbers... */
153 if (mode == VIDEO_CURRENT_MODE)
154 return 0; /* Nothing to do... */
155 else if (mode == NORMAL_VGA)
156 mode = VIDEO_80x25;
157 else if (mode == EXTENDED_VGA)
158 mode = VIDEO_8POINT;
159
160 rv = raw_set_mode(mode, &real_mode);
161 if (rv)
162 return rv;
163
164 if (mode & VIDEO_RECALC)
165 vga_recalc_vertical();
166
167 /* Save the canonical mode number for the kernel, not
168 an alias, size specification or menu position */
169#ifndef _WAKEUP
170 boot_params.hdr.vid_mode = real_mode;
171#endif
172 return 0;
173}
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
index 419b5c27337..5d5a3f6e8b5 100644
--- a/arch/x86/boot/video-vesa.c
+++ b/arch/x86/boot/video-vesa.c
@@ -24,7 +24,11 @@ static struct vesa_mode_info vminfo;
24 24
25__videocard video_vesa; 25__videocard video_vesa;
26 26
27#ifndef _WAKEUP
27static void vesa_store_mode_params_graphics(void); 28static void vesa_store_mode_params_graphics(void);
29#else /* _WAKEUP */
30static inline void vesa_store_mode_params_graphics(void) {}
31#endif /* _WAKEUP */
28 32
29static int vesa_probe(void) 33static int vesa_probe(void)
30{ 34{
@@ -165,6 +169,8 @@ static int vesa_set_mode(struct mode_info *mode)
165} 169}
166 170
167 171
172#ifndef _WAKEUP
173
168/* Switch DAC to 8-bit mode */ 174/* Switch DAC to 8-bit mode */
169static void vesa_dac_set_8bits(void) 175static void vesa_dac_set_8bits(void)
170{ 176{
@@ -288,6 +294,8 @@ void vesa_store_edid(void)
288#endif /* CONFIG_FIRMWARE_EDID */ 294#endif /* CONFIG_FIRMWARE_EDID */
289} 295}
290 296
297#endif /* not _WAKEUP */
298
291__videocard video_vesa = 299__videocard video_vesa =
292{ 300{
293 .card_name = "VESA", 301 .card_name = "VESA",
diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
index 7259387b7d1..330d6589a2a 100644
--- a/arch/x86/boot/video-vga.c
+++ b/arch/x86/boot/video-vga.c
@@ -210,6 +210,8 @@ static int vga_set_mode(struct mode_info *mode)
210 */ 210 */
211static int vga_probe(void) 211static int vga_probe(void)
212{ 212{
213 u16 ega_bx;
214
213 static const char *card_name[] = { 215 static const char *card_name[] = {
214 "CGA/MDA/HGC", "EGA", "VGA" 216 "CGA/MDA/HGC", "EGA", "VGA"
215 }; 217 };
@@ -226,12 +228,16 @@ static int vga_probe(void)
226 u8 vga_flag; 228 u8 vga_flag;
227 229
228 asm(INT10 230 asm(INT10
229 : "=b" (boot_params.screen_info.orig_video_ega_bx) 231 : "=b" (ega_bx)
230 : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */ 232 : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
231 : "ecx", "edx", "esi", "edi"); 233 : "ecx", "edx", "esi", "edi");
232 234
235#ifndef _WAKEUP
236 boot_params.screen_info.orig_video_ega_bx = ega_bx;
237#endif
238
233 /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ 239 /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
234 if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) { 240 if ((u8)ega_bx != 0x10) {
235 /* EGA/VGA */ 241 /* EGA/VGA */
236 asm(INT10 242 asm(INT10
237 : "=a" (vga_flag) 243 : "=a" (vga_flag)
@@ -240,7 +246,9 @@ static int vga_probe(void)
240 246
241 if (vga_flag == 0x1a) { 247 if (vga_flag == 0x1a) {
242 adapter = ADAPTER_VGA; 248 adapter = ADAPTER_VGA;
249#ifndef _WAKEUP
243 boot_params.screen_info.orig_video_isVGA = 1; 250 boot_params.screen_info.orig_video_isVGA = 1;
251#endif
244 } else { 252 } else {
245 adapter = ADAPTER_EGA; 253 adapter = ADAPTER_EGA;
246 } 254 }
diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
index 696d08f3843..c1c47ba069e 100644
--- a/arch/x86/boot/video.c
+++ b/arch/x86/boot/video.c
@@ -18,21 +18,6 @@
18#include "video.h" 18#include "video.h"
19#include "vesa.h" 19#include "vesa.h"
20 20
21/*
22 * Mode list variables
23 */
24static struct card_info cards[]; /* List of cards to probe for */
25
26/*
27 * Common variables
28 */
29int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
30u16 video_segment;
31int force_x, force_y; /* Don't query the BIOS for cols/rows */
32
33int do_restore = 0; /* Screen contents changed during mode flip */
34int graphic_mode; /* Graphic mode with linear frame buffer */
35
36static void store_cursor_position(void) 21static void store_cursor_position(void)
37{ 22{
38 u16 curpos; 23 u16 curpos;
@@ -107,147 +92,6 @@ static void store_mode_params(void)
107 boot_params.screen_info.orig_video_lines = y; 92 boot_params.screen_info.orig_video_lines = y;
108} 93}
109 94
110/* Probe the video drivers and have them generate their mode lists. */
111static void probe_cards(int unsafe)
112{
113 struct card_info *card;
114 static u8 probed[2];
115
116 if (probed[unsafe])
117 return;
118
119 probed[unsafe] = 1;
120
121 for (card = video_cards; card < video_cards_end; card++) {
122 if (card->unsafe == unsafe) {
123 if (card->probe)
124 card->nmodes = card->probe();
125 else
126 card->nmodes = 0;
127 }
128 }
129}
130
131/* Test if a mode is defined */
132int mode_defined(u16 mode)
133{
134 struct card_info *card;
135 struct mode_info *mi;
136 int i;
137
138 for (card = video_cards; card < video_cards_end; card++) {
139 mi = card->modes;
140 for (i = 0; i < card->nmodes; i++, mi++) {
141 if (mi->mode == mode)
142 return 1;
143 }
144 }
145
146 return 0;
147}
148
149/* Set mode (without recalc) */
150static int raw_set_mode(u16 mode, u16 *real_mode)
151{
152 int nmode, i;
153 struct card_info *card;
154 struct mode_info *mi;
155
156 /* Drop the recalc bit if set */
157 mode &= ~VIDEO_RECALC;
158
159 /* Scan for mode based on fixed ID, position, or resolution */
160 nmode = 0;
161 for (card = video_cards; card < video_cards_end; card++) {
162 mi = card->modes;
163 for (i = 0; i < card->nmodes; i++, mi++) {
164 int visible = mi->x || mi->y;
165
166 if ((mode == nmode && visible) ||
167 mode == mi->mode ||
168 mode == (mi->y << 8)+mi->x) {
169 *real_mode = mi->mode;
170 return card->set_mode(mi);
171 }
172
173 if (visible)
174 nmode++;
175 }
176 }
177
178 /* Nothing found? Is it an "exceptional" (unprobed) mode? */
179 for (card = video_cards; card < video_cards_end; card++) {
180 if (mode >= card->xmode_first &&
181 mode < card->xmode_first+card->xmode_n) {
182 struct mode_info mix;
183 *real_mode = mix.mode = mode;
184 mix.x = mix.y = 0;
185 return card->set_mode(&mix);
186 }
187 }
188
189 /* Otherwise, failure... */
190 return -1;
191}
192
193/*
194 * Recalculate the vertical video cutoff (hack!)
195 */
196static void vga_recalc_vertical(void)
197{
198 unsigned int font_size, rows;
199 u16 crtc;
200 u8 pt, ov;
201
202 set_fs(0);
203 font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
204 rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
205
206 rows *= font_size; /* Visible scan lines */
207 rows--; /* ... minus one */
208
209 crtc = vga_crtc();
210
211 pt = in_idx(crtc, 0x11);
212 pt &= ~0x80; /* Unlock CR0-7 */
213 out_idx(pt, crtc, 0x11);
214
215 out_idx((u8)rows, crtc, 0x12); /* Lower height register */
216
217 ov = in_idx(crtc, 0x07); /* Overflow register */
218 ov &= 0xbd;
219 ov |= (rows >> (8-1)) & 0x02;
220 ov |= (rows >> (9-6)) & 0x40;
221 out_idx(ov, crtc, 0x07);
222}
223
224/* Set mode (with recalc if specified) */
225static int set_mode(u16 mode)
226{
227 int rv;
228 u16 real_mode;
229
230 /* Very special mode numbers... */
231 if (mode == VIDEO_CURRENT_MODE)
232 return 0; /* Nothing to do... */
233 else if (mode == NORMAL_VGA)
234 mode = VIDEO_80x25;
235 else if (mode == EXTENDED_VGA)
236 mode = VIDEO_8POINT;
237
238 rv = raw_set_mode(mode, &real_mode);
239 if (rv)
240 return rv;
241
242 if (mode & VIDEO_RECALC)
243 vga_recalc_vertical();
244
245 /* Save the canonical mode number for the kernel, not
246 an alias, size specification or menu position */
247 boot_params.hdr.vid_mode = real_mode;
248 return 0;
249}
250
251static unsigned int get_entry(void) 95static unsigned int get_entry(void)
252{ 96{
253 char entry_buf[4]; 97 char entry_buf[4];
@@ -486,6 +330,7 @@ void set_video(void)
486 printf("Undefined video mode number: %x\n", mode); 330 printf("Undefined video mode number: %x\n", mode);
487 mode = ASK_VGA; 331 mode = ASK_VGA;
488 } 332 }
333 boot_params.hdr.vid_mode = mode;
489 vesa_store_edid(); 334 vesa_store_edid();
490 store_mode_params(); 335 store_mode_params();
491 336
diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
index 19d3d6e9d09..7335959b6af 100644
--- a/arch/x86/kernel/acpi/Makefile
+++ b/arch/x86/kernel/acpi/Makefile
@@ -1,7 +1,14 @@
1subdir- := realmode
2
1obj-$(CONFIG_ACPI) += boot.o 3obj-$(CONFIG_ACPI) += boot.o
2obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o 4obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o
3 5
4ifneq ($(CONFIG_ACPI_PROCESSOR),) 6ifneq ($(CONFIG_ACPI_PROCESSOR),)
5obj-y += cstate.o processor.o 7obj-y += cstate.o processor.o
6endif 8endif
7 9
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
new file mode 100644
index 00000000000..092900854ac
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/Makefile
@@ -0,0 +1,57 @@
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
9targets := wakeup.bin wakeup.elf
10
11wakeup-y += wakeup.o wakemain.o video-mode.o copy.o
12
13# The link order of the video-*.o modules can matter. In particular,
14# video-vga.o *must* be listed first, followed by video-vesa.o.
15# Hardware-specific drivers should follow in the order they should be
16# probed, and video-bios.o should typically be last.
17wakeup-y += video-vga.o
18wakeup-y += video-vesa.o
19wakeup-y += video-bios.o
20
21targets += $(wakeup-y)
22
23bootsrc := $(src)/../../../boot
24
25# ---------------------------------------------------------------------------
26
27# How to compile the 16-bit code. Note we always compile for -march=i386,
28# that way we can complain to the user if the CPU is insufficient.
29# Compile with _SETUP since this is similar to the boot-time setup code.
30KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D_WAKEUP -D__KERNEL__ \
31 -I$(srctree)/$(bootsrc) \
32 $(cflags-y) \
33 -Wall -Wstrict-prototypes \
34 -march=i386 -mregparm=3 \
35 -include $(srctree)/$(bootsrc)/code16gcc.h \
36 -fno-strict-aliasing -fomit-frame-pointer \
37 $(call cc-option, -ffreestanding) \
38 $(call cc-option, -fno-toplevel-reorder,\
39 $(call cc-option, -fno-unit-at-a-time)) \
40 $(call cc-option, -fno-stack-protector) \
41 $(call cc-option, -mpreferred-stack-boundary=2)
42KBUILD_CFLAGS += $(call cc-option, -m32)
43KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
44
45WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y))
46
47LDFLAGS_wakeup.elf := -T
48
49CPPFLAGS_wakeup.lds += -P -C
50
51$(obj)/wakeup.elf: $(src)/wakeup.lds $(WAKEUP_OBJS) FORCE
52 $(call if_changed,ld)
53
54OBJCOPYFLAGS_wakeup.bin := -O binary
55
56$(obj)/wakeup.bin: $(obj)/wakeup.elf FORCE
57 $(call if_changed,objcopy)
diff --git a/arch/x86/kernel/acpi/realmode/copy.S b/arch/x86/kernel/acpi/realmode/copy.S
new file mode 100644
index 00000000000..dc59ebee69d
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/copy.S
@@ -0,0 +1 @@
#include "../../../boot/copy.S"
diff --git a/arch/x86/kernel/acpi/realmode/video-bios.c b/arch/x86/kernel/acpi/realmode/video-bios.c
new file mode 100644
index 00000000000..7deabc144a2
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/video-bios.c
@@ -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
new file mode 100644
index 00000000000..328ad209f11
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/video-mode.c
@@ -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
new file mode 100644
index 00000000000..9dbb9672226
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/video-vesa.c
@@ -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
new file mode 100644
index 00000000000..bcc81255f37
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/video-vga.c
@@ -0,0 +1 @@
#include "../../../boot/video-vga.c"
diff --git a/arch/x86/kernel/acpi/realmode/wakemain.c b/arch/x86/kernel/acpi/realmode/wakemain.c
new file mode 100644
index 00000000000..883962d9eef
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/wakemain.c
@@ -0,0 +1,81 @@
1#include "wakeup.h"
2#include "boot.h"
3
4static void udelay(int loops)
5{
6 while (loops--)
7 io_delay(); /* Approximately 1 us */
8}
9
10static void beep(unsigned int hz)
11{
12 u8 enable;
13
14 if (!hz) {
15 enable = 0x00; /* Turn off speaker */
16 } else {
17 u16 div = 1193181/hz;
18
19 outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */
20 io_delay();
21 outb(div, 0x42); /* LSB of counter */
22 io_delay();
23 outb(div >> 8, 0x42); /* MSB of counter */
24 io_delay();
25
26 enable = 0x03; /* Turn on speaker */
27 }
28 inb(0x61); /* Dummy read of System Control Port B */
29 io_delay();
30 outb(enable, 0x61); /* Enable timer 2 output to speaker */
31 io_delay();
32}
33
34#define DOT_HZ 880
35#define DASH_HZ 587
36#define US_PER_DOT 125000
37
38/* Okay, this is totally silly, but it's kind of fun. */
39static void send_morse(const char *pattern)
40{
41 char s;
42
43 while ((s = *pattern++)) {
44 switch (s) {
45 case '.':
46 beep(DOT_HZ);
47 udelay(US_PER_DOT);
48 beep(0);
49 udelay(US_PER_DOT);
50 break;
51 case '-':
52 beep(DASH_HZ);
53 udelay(US_PER_DOT * 3);
54 beep(0);
55 udelay(US_PER_DOT);
56 break;
57 default: /* Assume it's a space */
58 udelay(US_PER_DOT * 3);
59 break;
60 }
61 }
62}
63
64void main(void)
65{
66 /* Kill machine if structures are wrong */
67 if (wakeup_header.real_magic != 0x12345678)
68 while (1);
69
70 if (wakeup_header.realmode_flags & 4)
71 send_morse("...-");
72
73 if (wakeup_header.realmode_flags & 1)
74 asm volatile("lcallw $0xc000,$3");
75
76 if (wakeup_header.realmode_flags & 2) {
77 /* Need to call BIOS */
78 probe_cards(0);
79 set_mode(wakeup_header.video_mode);
80 }
81}
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S
new file mode 100644
index 00000000000..f9b77fb37e5
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/wakeup.S
@@ -0,0 +1,113 @@
1/*
2 * ACPI wakeup real mode startup stub
3 */
4#include <asm/segment.h>
5#include <asm/msr-index.h>
6#include <asm/page.h>
7#include <asm/pgtable.h>
8
9 .code16
10 .section ".header", "a"
11
12/* This should match the structure in wakeup.h */
13 .globl wakeup_header
14wakeup_header:
15video_mode: .short 0 /* Video mode number */
16pmode_return: .byte 0x66, 0xea /* ljmpl */
17 .long 0 /* offset goes here */
18 .short __KERNEL_CS
19pmode_cr0: .long 0 /* Saved %cr0 */
20pmode_cr3: .long 0 /* Saved %cr3 */
21pmode_cr4: .long 0 /* Saved %cr4 */
22pmode_efer: .quad 0 /* Saved EFER */
23pmode_gdt: .quad 0
24realmode_flags: .long 0
25real_magic: .long 0
26trampoline_segment: .word 0
27signature: .long 0x51ee1111
28
29 .text
30 .globl _start
31 .code16
32wakeup_code:
33_start:
34 cli
35 cld
36
37 /* Set up segments */
38 movw %cs, %ax
39 movw %ax, %ds
40 movw %ax, %es
41 movw %ax, %ss
42
43 movl $wakeup_stack_end, %esp
44
45 /* Clear the EFLAGS */
46 pushl $0
47 popfl
48
49 /* Check header signature... */
50 movl signature, %eax
51 cmpl $0x51ee1111, %eax
52 jne bogus_real_magic
53
54 /* Check we really have everything... */
55 movl end_signature, %eax
56 cmpl $0x65a22c82, %eax
57 jne bogus_real_magic
58
59 /* Call the C code */
60 calll main
61
62 /* Do any other stuff... */
63
64#ifndef CONFIG_64BIT
65 /* This could also be done in C code... */
66 movl pmode_cr3, %eax
67 movl %eax, %cr3
68
69 movl pmode_cr4, %ecx
70 jecxz 1f
71 movl %ecx, %cr4
721:
73 movl pmode_efer, %eax
74 movl pmode_efer + 4, %edx
75 movl %eax, %ecx
76 orl %edx, %ecx
77 jz 1f
78 movl $0xc0000080, %ecx
79 wrmsr
801:
81
82 lgdtl pmode_gdt
83
84 /* This really couldn't... */
85 movl pmode_cr0, %eax
86 movl %eax, %cr0
87 jmp pmode_return
88#else
89 pushw $0
90 pushw trampoline_segment
91 pushw $0
92 lret
93#endif
94
95bogus_real_magic:
961:
97 hlt
98 jmp 1b
99
100 .data
101 .balign 4
102 .globl HEAP, heap_end
103HEAP:
104 .long wakeup_heap
105heap_end:
106 .long wakeup_stack
107
108 .bss
109wakeup_heap:
110 .space 2048
111wakeup_stack:
112 .space 2048
113wakeup_stack_end:
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h
new file mode 100644
index 00000000000..ef8166fe802
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/wakeup.h
@@ -0,0 +1,36 @@
1/*
2 * Definitions for the wakeup data structure at the head of the
3 * wakeup code.
4 */
5
6#ifndef ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
7#define ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
8
9#ifndef __ASSEMBLY__
10#include <linux/types.h>
11
12/* This must match data at wakeup.S */
13struct wakeup_header {
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 */
17 u16 _jmp2; /* CS value, 32-bit only */
18 u32 pmode_cr0; /* Protected mode cr0 */
19 u32 pmode_cr3; /* Protected mode cr3 */
20 u32 pmode_cr4; /* Protected mode cr4 */
21 u32 pmode_efer_low; /* Protected mode EFER */
22 u32 pmode_efer_high;
23 u64 pmode_gdt;
24 u32 realmode_flags;
25 u32 real_magic;
26 u16 trampoline_segment; /* segment with trampoline code, 64-bit only */
27 u32 signature; /* To check we have correct structure */
28} __attribute__((__packed__));
29
30extern struct wakeup_header wakeup_header;
31#endif
32
33#define HEADER_OFFSET 0x3f00
34#define WAKEUP_SIZE 0x4000
35
36#endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
new file mode 100644
index 00000000000..22fab6c4be1
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
@@ -0,0 +1,61 @@
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 . = HEADER_OFFSET;
16 .header : {
17 *(.header)
18 }
19
20 . = 0;
21 .text : {
22 *(.text*)
23 }
24
25 . = ALIGN(16);
26 .rodata : {
27 *(.rodata*)
28 }
29
30 .videocards : {
31 video_cards = .;
32 *(.videocards)
33 video_cards_end = .;
34 }
35
36 . = ALIGN(16);
37 .data : {
38 *(.data*)
39 }
40
41 .signature : {
42 end_signature = .;
43 LONG(0x65a22c82)
44 }
45
46 . = ALIGN(16);
47 .bss : {
48 __bss_start = .;
49 *(.bss)
50 __bss_end = .;
51 }
52
53 . = ALIGN(16);
54 _end = .;
55
56 /DISCARD/ : {
57 *(.note*)
58 }
59
60 . = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!");
61}
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index dd78326ae47..afc25ee9964 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -10,30 +10,72 @@
10#include <linux/dmi.h> 10#include <linux/dmi.h>
11#include <linux/cpumask.h> 11#include <linux/cpumask.h>
12 12
13#include <asm/smp.h> 13#include "realmode/wakeup.h"
14#include "sleep.h"
14 15
15/* address in low memory of the wakeup routine. */
16unsigned long acpi_wakeup_address; 16unsigned long acpi_wakeup_address;
17unsigned long acpi_realmode_flags; 17unsigned long acpi_realmode_flags;
18extern char wakeup_start, wakeup_end;
19 18
20extern unsigned long acpi_copy_wakeup_routine(unsigned long); 19/* address in low memory of the wakeup routine. */
20static unsigned long acpi_realmode;
21
22#ifdef CONFIG_64BIT
23static char temp_stack[10240];
24#endif
21 25
22/** 26/**
23 * acpi_save_state_mem - save kernel state 27 * acpi_save_state_mem - save kernel state
24 * 28 *
25 * Create an identity mapped page table and copy the wakeup routine to 29 * Create an identity mapped page table and copy the wakeup routine to
26 * low memory. 30 * low memory.
31 *
32 * Note that this is too late to change acpi_wakeup_address.
27 */ 33 */
28int acpi_save_state_mem(void) 34int acpi_save_state_mem(void)
29{ 35{
30 if (!acpi_wakeup_address) { 36 struct wakeup_header *header;
31 printk(KERN_ERR "Could not allocate memory during boot, S3 disabled\n"); 37
38 if (!acpi_realmode) {
39 printk(KERN_ERR "Could not allocate memory during boot, "
40 "S3 disabled\n");
32 return -ENOMEM; 41 return -ENOMEM;
33 } 42 }
34 memcpy((void *)acpi_wakeup_address, &wakeup_start, 43 memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
35 &wakeup_end - &wakeup_start); 44
36 acpi_copy_wakeup_routine(acpi_wakeup_address); 45 header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
46 if (header->signature != 0x51ee1111) {
47 printk(KERN_ERR "wakeup header does not match\n");
48 return -EINVAL;
49 }
50
51 header->video_mode = saved_video_mode;
52
53#ifndef CONFIG_64BIT
54 store_gdt((struct desc_ptr *)&header->pmode_gdt);
55
56 header->pmode_efer_low = nx_enabled;
57 if (header->pmode_efer_low & 1) {
58 /* This is strange, why not save efer, always? */
59 rdmsr(MSR_EFER, header->pmode_efer_low,
60 header->pmode_efer_high);
61 }
62#endif /* !CONFIG_64BIT */
63
64 header->pmode_cr0 = read_cr0();
65 header->pmode_cr4 = read_cr4();
66 header->realmode_flags = acpi_realmode_flags;
67 header->real_magic = 0x12345678;
68
69#ifndef CONFIG_64BIT
70 header->pmode_entry = (u32)&wakeup_pmode_return;
71 header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
72 saved_magic = 0x12345678;
73#else /* CONFIG_64BIT */
74 header->trampoline_segment = setup_trampoline() >> 4;
75 init_rsp = (unsigned long)temp_stack + 4096;
76 initial_code = (unsigned long)wakeup_long64;
77 saved_magic = 0x123456789abcdef0;
78#endif /* CONFIG_64BIT */
37 79
38 return 0; 80 return 0;
39} 81}
@@ -56,15 +98,20 @@ void acpi_restore_state_mem(void)
56 */ 98 */
57void __init acpi_reserve_bootmem(void) 99void __init acpi_reserve_bootmem(void)
58{ 100{
59 if ((&wakeup_end - &wakeup_start) > PAGE_SIZE*2) { 101 if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
60 printk(KERN_ERR 102 printk(KERN_ERR
61 "ACPI: Wakeup code way too big, S3 disabled.\n"); 103 "ACPI: Wakeup code way too big, S3 disabled.\n");
62 return; 104 return;
63 } 105 }
64 106
65 acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2); 107 acpi_realmode = (unsigned long)alloc_bootmem_low(WAKEUP_SIZE);
66 if (!acpi_wakeup_address) 108
109 if (!acpi_realmode) {
67 printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n"); 110 printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
111 return;
112 }
113
114 acpi_wakeup_address = acpi_realmode;
68} 115}
69 116
70 117
diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h
new file mode 100644
index 00000000000..adbcbaa6f1d
--- /dev/null
+++ b/arch/x86/kernel/acpi/sleep.h
@@ -0,0 +1,16 @@
1/*
2 * Variables and functions used by the code in sleep.c
3 */
4
5#include <asm/trampoline.h>
6
7extern char wakeup_code_start, wakeup_code_end;
8
9extern unsigned long saved_video_mode;
10extern long saved_magic;
11
12extern int wakeup_pmode_return;
13extern char swsusp_pg_dir[PAGE_SIZE];
14
15extern unsigned long acpi_copy_wakeup_routine(unsigned long);
16extern void wakeup_long64(void);
diff --git a/arch/x86/kernel/acpi/sleep_32.c b/arch/x86/kernel/acpi/sleep_32.c
deleted file mode 100644
index 63fe5525e02..00000000000
--- a/arch/x86/kernel/acpi/sleep_32.c
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * sleep.c - x86-specific ACPI sleep support.
3 *
4 * Copyright (C) 2001-2003 Patrick Mochel
5 * Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz>
6 */
7
8#include <linux/acpi.h>
9#include <linux/bootmem.h>
10#include <linux/dmi.h>
11#include <linux/cpumask.h>
12
13#include <asm/smp.h>
14
15/* Ouch, we want to delete this. We already have better version in userspace, in
16 s2ram from suspend.sf.net project */
17static __init int reset_videomode_after_s3(const struct dmi_system_id *d)
18{
19 acpi_realmode_flags |= 2;
20 return 0;
21}
22
23static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
24 { /* Reset video mode after returning from ACPI S3 sleep */
25 .callback = reset_videomode_after_s3,
26 .ident = "Toshiba Satellite 4030cdt",
27 .matches = {
28 DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
29 },
30 },
31 {}
32};
33
34static int __init acpisleep_dmi_init(void)
35{
36 dmi_check_system(acpisleep_dmi_table);
37 return 0;
38}
39
40core_initcall(acpisleep_dmi_init);
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
index f53e3277f8e..a12e6a9fb65 100644
--- a/arch/x86/kernel/acpi/wakeup_32.S
+++ b/arch/x86/kernel/acpi/wakeup_32.S
@@ -3,178 +3,12 @@
3#include <asm/segment.h> 3#include <asm/segment.h>
4#include <asm/page.h> 4#include <asm/page.h>
5 5
6# 6# Copyright 2003, 2008 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
7# wakeup_code runs in real mode, and at unknown address (determined at run-time).
8# Therefore it must only use relative jumps/calls.
9#
10# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
11#
12# If physical address of wakeup_code is 0x12345, BIOS should call us with
13# cs = 0x1234, eip = 0x05
14#
15
16#define BEEP \
17 inb $97, %al; \
18 outb %al, $0x80; \
19 movb $3, %al; \
20 outb %al, $97; \
21 outb %al, $0x80; \
22 movb $-74, %al; \
23 outb %al, $67; \
24 outb %al, $0x80; \
25 movb $-119, %al; \
26 outb %al, $66; \
27 outb %al, $0x80; \
28 movb $15, %al; \
29 outb %al, $66;
30
31ALIGN
32 .align 4096
33ENTRY(wakeup_start)
34wakeup_code:
35 wakeup_code_start = .
36 .code16
37
38 cli
39 cld
40
41 # setup data segment
42 movw %cs, %ax
43 movw %ax, %ds # Make ds:0 point to wakeup_start
44 movw %ax, %ss
45
46 testl $4, realmode_flags - wakeup_code
47 jz 1f
48 BEEP
491:
50 mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board
51
52 pushl $0 # Kill any dangerous flags
53 popfl
54
55 movl real_magic - wakeup_code, %eax
56 cmpl $0x12345678, %eax
57 jne bogus_real_magic
58
59 testl $1, realmode_flags - wakeup_code
60 jz 1f
61 lcall $0xc000,$3
62 movw %cs, %ax
63 movw %ax, %ds # Bios might have played with that
64 movw %ax, %ss
651:
66
67 testl $2, realmode_flags - wakeup_code
68 jz 1f
69 mov video_mode - wakeup_code, %ax
70 call mode_set
711:
72
73 # set up page table
74 movl $swsusp_pg_dir-__PAGE_OFFSET, %eax
75 movl %eax, %cr3
76
77 testl $1, real_efer_save_restore - wakeup_code
78 jz 4f
79 # restore efer setting
80 movl real_save_efer_edx - wakeup_code, %edx
81 movl real_save_efer_eax - wakeup_code, %eax
82 mov $0xc0000080, %ecx
83 wrmsr
844:
85 # make sure %cr4 is set correctly (features, etc)
86 movl real_save_cr4 - wakeup_code, %eax
87 movl %eax, %cr4
88
89 # need a gdt -- use lgdtl to force 32-bit operands, in case
90 # the GDT is located past 16 megabytes.
91 lgdtl real_save_gdt - wakeup_code
92
93 movl real_save_cr0 - wakeup_code, %eax
94 movl %eax, %cr0
95 jmp 1f
961:
97 movl real_magic - wakeup_code, %eax
98 cmpl $0x12345678, %eax
99 jne bogus_real_magic
100
101 testl $8, realmode_flags - wakeup_code
102 jz 1f
103 BEEP
1041:
105 ljmpl $__KERNEL_CS, $wakeup_pmode_return
106
107real_save_gdt: .word 0
108 .long 0
109real_save_cr0: .long 0
110real_save_cr3: .long 0
111real_save_cr4: .long 0
112real_magic: .long 0
113video_mode: .long 0
114realmode_flags: .long 0
115real_efer_save_restore: .long 0
116real_save_efer_edx: .long 0
117real_save_efer_eax: .long 0
118
119bogus_real_magic:
120 jmp bogus_real_magic
121
122/* This code uses an extended set of video mode numbers. These include:
123 * Aliases for standard modes
124 * NORMAL_VGA (-1)
125 * EXTENDED_VGA (-2)
126 * ASK_VGA (-3)
127 * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
128 * of compatibility when extending the table. These are between 0x00 and 0xff.
129 */
130#define VIDEO_FIRST_MENU 0x0000
131
132/* Standard BIOS video modes (BIOS number + 0x0100) */
133#define VIDEO_FIRST_BIOS 0x0100
134
135/* VESA BIOS video modes (VESA number + 0x0200) */
136#define VIDEO_FIRST_VESA 0x0200
137
138/* Video7 special modes (BIOS number + 0x0900) */
139#define VIDEO_FIRST_V7 0x0900
140
141# Setting of user mode (AX=mode ID) => CF=success
142
143# For now, we only handle VESA modes (0x0200..0x03ff). To handle other
144# modes, we should probably compile in the video code from the boot
145# directory.
146mode_set:
147 movw %ax, %bx
148 subb $VIDEO_FIRST_VESA>>8, %bh
149 cmpb $2, %bh
150 jb check_vesa
151
152setbad:
153 clc
154 ret
155
156check_vesa:
157 orw $0x4000, %bx # Use linear frame buffer
158 movw $0x4f02, %ax # VESA BIOS mode set call
159 int $0x10
160 cmpw $0x004f, %ax # AL=4f if implemented
161 jnz setbad # AH=0 if OK
162
163 stc
164 ret
165 7
166 .code32 8 .code32
167 ALIGN 9 ALIGN
168 10
169.org 0x800 11ENTRY(wakeup_pmode_return)
170wakeup_stack_begin: # Stack grows down
171
172.org 0xff0 # Just below end of page
173wakeup_stack:
174ENTRY(wakeup_end)
175
176.org 0x1000
177
178wakeup_pmode_return: 12wakeup_pmode_return:
179 movw $__KERNEL_DS, %ax 13 movw $__KERNEL_DS, %ax
180 movw %ax, %ss 14 movw %ax, %ss
@@ -187,7 +21,7 @@ wakeup_pmode_return:
187 lgdt saved_gdt 21 lgdt saved_gdt
188 lidt saved_idt 22 lidt saved_idt
189 lldt saved_ldt 23 lldt saved_ldt
190 ljmp $(__KERNEL_CS),$1f 24 ljmp $(__KERNEL_CS), $1f
1911: 251:
192 movl %cr3, %eax 26 movl %cr3, %eax
193 movl %eax, %cr3 27 movl %eax, %cr3
@@ -201,82 +35,41 @@ wakeup_pmode_return:
201 jne bogus_magic 35 jne bogus_magic
202 36
203 # jump to place where we left off 37 # jump to place where we left off
204 movl saved_eip,%eax 38 movl saved_eip, %eax
205 jmp *%eax 39 jmp *%eax
206 40
207bogus_magic: 41bogus_magic:
208 jmp bogus_magic 42 jmp bogus_magic
209 43
210 44
211##
212# acpi_copy_wakeup_routine
213#
214# Copy the above routine to low memory.
215#
216# Parameters:
217# %eax: place to copy wakeup routine to
218#
219# Returned address is location of code in low memory (past data and stack)
220#
221ENTRY(acpi_copy_wakeup_routine)
222 45
223 pushl %ebx 46save_registers:
224 sgdt saved_gdt 47 sgdt saved_gdt
225 sidt saved_idt 48 sidt saved_idt
226 sldt saved_ldt 49 sldt saved_ldt
227 str saved_tss 50 str saved_tss
228 51
229 movl nx_enabled, %edx
230 movl %edx, real_efer_save_restore - wakeup_start (%eax)
231 testl $1, real_efer_save_restore - wakeup_start (%eax)
232 jz 2f
233 # save efer setting
234 pushl %eax
235 movl %eax, %ebx
236 mov $0xc0000080, %ecx
237 rdmsr
238 movl %edx, real_save_efer_edx - wakeup_start (%ebx)
239 movl %eax, real_save_efer_eax - wakeup_start (%ebx)
240 popl %eax
2412:
242
243 movl %cr3, %edx
244 movl %edx, real_save_cr3 - wakeup_start (%eax)
245 movl %cr4, %edx
246 movl %edx, real_save_cr4 - wakeup_start (%eax)
247 movl %cr0, %edx
248 movl %edx, real_save_cr0 - wakeup_start (%eax)
249 sgdt real_save_gdt - wakeup_start (%eax)
250
251 movl saved_videomode, %edx
252 movl %edx, video_mode - wakeup_start (%eax)
253 movl acpi_realmode_flags, %edx
254 movl %edx, realmode_flags - wakeup_start (%eax)
255 movl $0x12345678, real_magic - wakeup_start (%eax)
256 movl $0x12345678, saved_magic
257 popl %ebx
258 ret
259
260save_registers:
261 leal 4(%esp), %eax 52 leal 4(%esp), %eax
262 movl %eax, saved_context_esp 53 movl %eax, saved_context_esp
263 movl %ebx, saved_context_ebx 54 movl %ebx, saved_context_ebx
264 movl %ebp, saved_context_ebp 55 movl %ebp, saved_context_ebp
265 movl %esi, saved_context_esi 56 movl %esi, saved_context_esi
266 movl %edi, saved_context_edi 57 movl %edi, saved_context_edi
267 pushfl ; popl saved_context_eflags 58 pushfl
268 59 popl saved_context_eflags
269 movl $ret_point, saved_eip 60
61 movl $ret_point, saved_eip
270 ret 62 ret
271 63
272 64
273restore_registers: 65restore_registers:
274 movl saved_context_ebp, %ebp 66 movl saved_context_ebp, %ebp
275 movl saved_context_ebx, %ebx 67 movl saved_context_ebx, %ebx
276 movl saved_context_esi, %esi 68 movl saved_context_esi, %esi
277 movl saved_context_edi, %edi 69 movl saved_context_edi, %edi
278 pushl saved_context_eflags ; popfl 70 pushl saved_context_eflags
279 ret 71 popfl
72 ret
280 73
281ENTRY(do_suspend_lowlevel) 74ENTRY(do_suspend_lowlevel)
282 call save_processor_state 75 call save_processor_state
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 2e1b9e0d076..bcc293423a7 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -7,191 +7,18 @@
7#include <asm/asm-offsets.h> 7#include <asm/asm-offsets.h>
8 8
9# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2 9# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
10#
11# wakeup_code runs in real mode, and at unknown address (determined at run-time).
12# Therefore it must only use relative jumps/calls.
13#
14# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
15#
16# If physical address of wakeup_code is 0x12345, BIOS should call us with
17# cs = 0x1234, eip = 0x05
18#
19
20#define BEEP \
21 inb $97, %al; \
22 outb %al, $0x80; \
23 movb $3, %al; \
24 outb %al, $97; \
25 outb %al, $0x80; \
26 movb $-74, %al; \
27 outb %al, $67; \
28 outb %al, $0x80; \
29 movb $-119, %al; \
30 outb %al, $66; \
31 outb %al, $0x80; \
32 movb $15, %al; \
33 outb %al, $66;
34
35
36ALIGN
37 .align 16
38ENTRY(wakeup_start)
39wakeup_code:
40 wakeup_code_start = .
41 .code16
42
43# Running in *copy* of this code, somewhere in low 1MB.
44
45 cli
46 cld
47 # setup data segment
48 movw %cs, %ax
49 movw %ax, %ds # Make ds:0 point to wakeup_start
50 movw %ax, %ss
51
52 # Data segment must be set up before we can see whether to beep.
53 testl $4, realmode_flags - wakeup_code
54 jz 1f
55 BEEP
561:
57
58 # Private stack is needed for ASUS board
59 mov $(wakeup_stack - wakeup_code), %sp
60
61 pushl $0 # Kill any dangerous flags
62 popfl
63
64 movl real_magic - wakeup_code, %eax
65 cmpl $0x12345678, %eax
66 jne bogus_real_magic
67
68 testl $1, realmode_flags - wakeup_code
69 jz 1f
70 lcall $0xc000,$3
71 movw %cs, %ax
72 movw %ax, %ds # Bios might have played with that
73 movw %ax, %ss
741:
75
76 testl $2, realmode_flags - wakeup_code
77 jz 1f
78 mov video_mode - wakeup_code, %ax
79 call mode_set
801:
81
82 mov %ds, %ax # Find 32bit wakeup_code addr
83 movzx %ax, %esi # (Convert %ds:gdt to a liner ptr)
84 shll $4, %esi
85 # Fix up the vectors
86 addl %esi, wakeup_32_vector - wakeup_code
87 addl %esi, wakeup_long64_vector - wakeup_code
88 addl %esi, gdt_48a + 2 - wakeup_code # Fixup the gdt pointer
89
90 lidtl %ds:idt_48a - wakeup_code
91 lgdtl %ds:gdt_48a - wakeup_code # load gdt with whatever is
92 # appropriate
93
94 movl $1, %eax # protected mode (PE) bit
95 lmsw %ax # This is it!
96 jmp 1f
971:
98
99 ljmpl *(wakeup_32_vector - wakeup_code)
100
101 .balign 4
102wakeup_32_vector:
103 .long wakeup_32 - wakeup_code
104 .word __KERNEL32_CS, 0
105
106 .code32
107wakeup_32:
108# Running in this code, but at low address; paging is not yet turned on.
109
110 movl $__KERNEL_DS, %eax
111 movl %eax, %ds
112
113 /*
114 * Prepare for entering 64bits mode
115 */
116
117 /* Enable PAE */
118 xorl %eax, %eax
119 btsl $5, %eax
120 movl %eax, %cr4
121
122 /* Setup early boot stage 4 level pagetables */
123 leal (wakeup_level4_pgt - wakeup_code)(%esi), %eax
124 movl %eax, %cr3
125
126 /* Check if nx is implemented */
127 movl $0x80000001, %eax
128 cpuid
129 movl %edx,%edi
130
131 /* Enable Long Mode */
132 xorl %eax, %eax
133 btsl $_EFER_LME, %eax
134
135 /* No Execute supported? */
136 btl $20,%edi
137 jnc 1f
138 btsl $_EFER_NX, %eax
139
140 /* Make changes effective */
1411: movl $MSR_EFER, %ecx
142 xorl %edx, %edx
143 wrmsr
144
145 xorl %eax, %eax
146 btsl $31, %eax /* Enable paging and in turn activate Long Mode */
147 btsl $0, %eax /* Enable protected mode */
148
149 /* Make changes effective */
150 movl %eax, %cr0
151
152 /* At this point:
153 CR4.PAE must be 1
154 CS.L must be 0
155 CR3 must point to PML4
156 Next instruction must be a branch
157 This must be on identity-mapped page
158 */
159 /*
160 * At this point we're in long mode but in 32bit compatibility mode
161 * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
162 * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we load
163 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
164 */
165
166 /* Finally jump in 64bit mode */
167 ljmp *(wakeup_long64_vector - wakeup_code)(%esi)
168
169 .balign 4
170wakeup_long64_vector:
171 .long wakeup_long64 - wakeup_code
172 .word __KERNEL_CS, 0
173 10
174.code64 11.code64
175
176 /* Hooray, we are in Long 64-bit mode (but still running in
177 * low memory)
178 */
179wakeup_long64:
180 /* 12 /*
181 * We must switch to a new descriptor in kernel space for the GDT 13 * Hooray, we are in Long 64-bit mode (but still running in low memory)
182 * because soon the kernel won't have access anymore to the userspace
183 * addresses where we're currently running on. We have to do that here
184 * because in 32bit we couldn't load a 64bit linear address.
185 */ 14 */
186 lgdt cpu_gdt_descr 15ENTRY(wakeup_long64)
187 16wakeup_long64:
188 movq saved_magic, %rax 17 movq saved_magic, %rax
189 movq $0x123456789abcdef0, %rdx 18 movq $0x123456789abcdef0, %rdx
190 cmpq %rdx, %rax 19 cmpq %rdx, %rax
191 jne bogus_64_magic 20 jne bogus_64_magic
192 21
193 nop
194 nop
195 movw $__KERNEL_DS, %ax 22 movw $__KERNEL_DS, %ax
196 movw %ax, %ss 23 movw %ax, %ss
197 movw %ax, %ds 24 movw %ax, %ds
@@ -208,130 +35,8 @@ wakeup_long64:
208 movq saved_rip, %rax 35 movq saved_rip, %rax
209 jmp *%rax 36 jmp *%rax
210 37
211.code32
212
213 .align 64
214gdta:
215 /* Its good to keep gdt in sync with one in trampoline.S */
216 .word 0, 0, 0, 0 # dummy
217 /* ??? Why I need the accessed bit set in order for this to work? */
218 .quad 0x00cf9b000000ffff # __KERNEL32_CS
219 .quad 0x00af9b000000ffff # __KERNEL_CS
220 .quad 0x00cf93000000ffff # __KERNEL_DS
221
222idt_48a:
223 .word 0 # idt limit = 0
224 .word 0, 0 # idt base = 0L
225
226gdt_48a:
227 .word 0x800 # gdt limit=2048,
228 # 256 GDT entries
229 .long gdta - wakeup_code # gdt base (relocated in later)
230
231real_magic: .quad 0
232video_mode: .quad 0
233realmode_flags: .quad 0
234
235.code16
236bogus_real_magic:
237 jmp bogus_real_magic
238
239.code64
240bogus_64_magic: 38bogus_64_magic:
241 jmp bogus_64_magic 39 jmp bogus_64_magic
242
243/* This code uses an extended set of video mode numbers. These include:
244 * Aliases for standard modes
245 * NORMAL_VGA (-1)
246 * EXTENDED_VGA (-2)
247 * ASK_VGA (-3)
248 * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
249 * of compatibility when extending the table. These are between 0x00 and 0xff.
250 */
251#define VIDEO_FIRST_MENU 0x0000
252
253/* Standard BIOS video modes (BIOS number + 0x0100) */
254#define VIDEO_FIRST_BIOS 0x0100
255
256/* VESA BIOS video modes (VESA number + 0x0200) */
257#define VIDEO_FIRST_VESA 0x0200
258
259/* Video7 special modes (BIOS number + 0x0900) */
260#define VIDEO_FIRST_V7 0x0900
261
262# Setting of user mode (AX=mode ID) => CF=success
263
264# For now, we only handle VESA modes (0x0200..0x03ff). To handle other
265# modes, we should probably compile in the video code from the boot
266# directory.
267.code16
268mode_set:
269 movw %ax, %bx
270 subb $VIDEO_FIRST_VESA>>8, %bh
271 cmpb $2, %bh
272 jb check_vesa
273
274setbad:
275 clc
276 ret
277
278check_vesa:
279 orw $0x4000, %bx # Use linear frame buffer
280 movw $0x4f02, %ax # VESA BIOS mode set call
281 int $0x10
282 cmpw $0x004f, %ax # AL=4f if implemented
283 jnz setbad # AH=0 if OK
284
285 stc
286 ret
287
288wakeup_stack_begin: # Stack grows down
289
290.org 0xff0
291wakeup_stack: # Just below end of page
292
293.org 0x1000
294ENTRY(wakeup_level4_pgt)
295 .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
296 .fill 510,8,0
297 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
298 .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
299
300ENTRY(wakeup_end)
301
302##
303# acpi_copy_wakeup_routine
304#
305# Copy the above routine to low memory.
306#
307# Parameters:
308# %rdi: place to copy wakeup routine to
309#
310# Returned address is location of code in low memory (past data and stack)
311#
312 .code64
313ENTRY(acpi_copy_wakeup_routine)
314 pushq %rax
315 pushq %rdx
316
317 movl saved_video_mode, %edx
318 movl %edx, video_mode - wakeup_start (,%rdi)
319 movl acpi_realmode_flags, %edx
320 movl %edx, realmode_flags - wakeup_start (,%rdi)
321 movq $0x12345678, real_magic - wakeup_start (,%rdi)
322 movq $0x123456789abcdef0, %rdx
323 movq %rdx, saved_magic
324
325 movq saved_magic, %rax
326 movq $0x123456789abcdef0, %rdx
327 cmpq %rdx, %rax
328 jne bogus_64_magic
329
330 # restore the regs we used
331 popq %rdx
332 popq %rax
333ENTRY(do_suspend_lowlevel_s4bios)
334 ret
335 40
336 .align 2 41 .align 2
337 .p2align 4,,15 42 .p2align 4,,15
@@ -414,7 +119,7 @@ do_suspend_lowlevel:
414 jmp restore_processor_state 119 jmp restore_processor_state
415.LFE5: 120.LFE5:
416.Lfe5: 121.Lfe5:
417 .size do_suspend_lowlevel,.Lfe5-do_suspend_lowlevel 122 .size do_suspend_lowlevel, .Lfe5-do_suspend_lowlevel
418 123
419.data 124.data
420ALIGN 125ALIGN
diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S
new file mode 100644
index 00000000000..6ff3b573057
--- /dev/null
+++ b/arch/x86/kernel/acpi/wakeup_rm.S
@@ -0,0 +1,10 @@
1/*
2 * Wrapper script for the realmode binary as a transport object
3 * before copying to low memory.
4 */
5 .section ".rodata","a"
6 .globl wakeup_code_start, wakeup_code_end
7wakeup_code_start:
8 .incbin "arch/x86/kernel/acpi/realmode/wakeup.bin"
9wakeup_code_end:
10 .size wakeup_code_start, .-wakeup_code_start
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
index a720f3d5ed9..7f6c0c85c8f 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -27,6 +27,7 @@
27#include <asm/setup.h> 27#include <asm/setup.h>
28#include <asm/sections.h> 28#include <asm/sections.h>
29#include <asm/kdebug.h> 29#include <asm/kdebug.h>
30#include <asm/trampoline.h>
30 31
31struct e820map e820; 32struct e820map e820;
32 33
@@ -58,8 +59,8 @@ struct early_res {
58}; 59};
59static struct early_res early_res[MAX_EARLY_RES] __initdata = { 60static struct early_res early_res[MAX_EARLY_RES] __initdata = {
60 { 0, PAGE_SIZE, "BIOS data page" }, /* BIOS data page */ 61 { 0, PAGE_SIZE, "BIOS data page" }, /* BIOS data page */
61#ifdef CONFIG_SMP 62#ifdef CONFIG_X86_TRAMPOLINE
62 { SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE, "SMP_TRAMPOLINE" }, 63 { TRAMPOLINE_BASE, TRAMPOLINE_BASE + 2 * PAGE_SIZE, "TRAMPOLINE" },
63#endif 64#endif
64 {} 65 {}
65}; 66};
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index c1d7a877d81..10a1955bb1d 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -132,10 +132,6 @@ ident_complete:
132 addq %rbp, trampoline_level4_pgt + 0(%rip) 132 addq %rbp, trampoline_level4_pgt + 0(%rip)
133 addq %rbp, trampoline_level4_pgt + (511*8)(%rip) 133 addq %rbp, trampoline_level4_pgt + (511*8)(%rip)
134#endif 134#endif
135#ifdef CONFIG_ACPI_SLEEP
136 addq %rbp, wakeup_level4_pgt + 0(%rip)
137 addq %rbp, wakeup_level4_pgt + (511*8)(%rip)
138#endif
139 135
140 /* Due to ENTRY(), sometimes the empty space gets filled with 136 /* Due to ENTRY(), sometimes the empty space gets filled with
141 * zeros. Better take a jmp than relying on empty space being 137 * zeros. Better take a jmp than relying on empty space being
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index 4b198d9d0de..5b0bffb7fcc 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -192,7 +192,7 @@ EXPORT_SYMBOL(ist_info);
192extern void early_cpu_init(void); 192extern void early_cpu_init(void);
193extern int root_mountflags; 193extern int root_mountflags;
194 194
195unsigned long saved_videomode; 195unsigned long saved_video_mode;
196 196
197#define RAMDISK_IMAGE_START_MASK 0x07FF 197#define RAMDISK_IMAGE_START_MASK 0x07FF
198#define RAMDISK_PROMPT_FLAG 0x8000 198#define RAMDISK_PROMPT_FLAG 0x8000
@@ -763,7 +763,7 @@ void __init setup_arch(char **cmdline_p)
763 edid_info = boot_params.edid_info; 763 edid_info = boot_params.edid_info;
764 apm_info.bios = boot_params.apm_bios_info; 764 apm_info.bios = boot_params.apm_bios_info;
765 ist_info = boot_params.ist_info; 765 ist_info = boot_params.ist_info;
766 saved_videomode = boot_params.hdr.vid_mode; 766 saved_video_mode = boot_params.hdr.vid_mode;
767 if( boot_params.sys_desc_table.length != 0 ) { 767 if( boot_params.sys_desc_table.length != 0 ) {
768 set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2); 768 set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
769 machine_id = boot_params.sys_desc_table.table[0]; 769 machine_id = boot_params.sys_desc_table.table[0];
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index b80300710c0..674ef3510cd 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -65,6 +65,7 @@
65#include <asm/mce.h> 65#include <asm/mce.h>
66#include <asm/ds.h> 66#include <asm/ds.h>
67#include <asm/topology.h> 67#include <asm/topology.h>
68#include <asm/trampoline.h>
68 69
69#include <mach_apic.h> 70#include <mach_apic.h>
70#ifdef CONFIG_PARAVIRT 71#ifdef CONFIG_PARAVIRT
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index ca3929b1604..424600e671b 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -53,6 +53,7 @@
53#include <asm/nmi.h> 53#include <asm/nmi.h>
54#include <asm/irq.h> 54#include <asm/irq.h>
55#include <asm/smp.h> 55#include <asm/smp.h>
56#include <asm/trampoline.h>
56#include <asm/cpu.h> 57#include <asm/cpu.h>
57#include <asm/numa.h> 58#include <asm/numa.h>
58#include <asm/pgtable.h> 59#include <asm/pgtable.h>
@@ -140,7 +141,7 @@ static atomic_t init_deasserted;
140static int boot_cpu_logical_apicid; 141static int boot_cpu_logical_apicid;
141 142
142/* ready for x86_64, no harm for x86, since it will overwrite after alloc */ 143/* ready for x86_64, no harm for x86, since it will overwrite after alloc */
143unsigned char *trampoline_base = __va(SMP_TRAMPOLINE_BASE); 144unsigned char *trampoline_base = __va(TRAMPOLINE_BASE);
144 145
145/* representing cpus for which sibling maps can be computed */ 146/* representing cpus for which sibling maps can be computed */
146static cpumask_t cpu_sibling_setup_map; 147static cpumask_t cpu_sibling_setup_map;
@@ -554,8 +555,7 @@ cpumask_t cpu_coregroup_map(int cpu)
554 * bootstrap into the page concerned. The caller 555 * bootstrap into the page concerned. The caller
555 * has made sure it's suitably aligned. 556 * has made sure it's suitably aligned.
556 */ 557 */
557 558unsigned long setup_trampoline(void)
558unsigned long __cpuinit setup_trampoline(void)
559{ 559{
560 memcpy(trampoline_base, trampoline_data, 560 memcpy(trampoline_base, trampoline_data,
561 trampoline_end - trampoline_data); 561 trampoline_end - trampoline_data);
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
index 2a07e67d669..894293c598d 100644
--- a/arch/x86/kernel/trampoline_64.S
+++ b/arch/x86/kernel/trampoline_64.S
@@ -30,12 +30,7 @@
30#include <asm/msr.h> 30#include <asm/msr.h>
31#include <asm/segment.h> 31#include <asm/segment.h>
32 32
33/* We can free up trampoline after bootup if cpu hotplug is not supported. */
34#ifndef CONFIG_HOTPLUG_CPU
35.section .cpuinit.data, "aw", @progbits
36#else
37.section .rodata, "a", @progbits 33.section .rodata, "a", @progbits
38#endif
39 34
40.code16 35.code16
41 36
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
index 4397235c2e3..be7235bf105 100644
--- a/arch/x86/mach-voyager/voyager_smp.c
+++ b/arch/x86/mach-voyager/voyager_smp.c
@@ -27,6 +27,7 @@
27#include <asm/pgalloc.h> 27#include <asm/pgalloc.h>
28#include <asm/tlbflush.h> 28#include <asm/tlbflush.h>
29#include <asm/arch_hooks.h> 29#include <asm/arch_hooks.h>
30#include <asm/trampoline.h>
30 31
31/* TLB state -- visible externally, indexed physically */ 32/* TLB state -- visible externally, indexed physically */
32DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0 }; 33DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0 };