diff options
author | H. Peter Anvin <hpa@zytor.com> | 2012-05-30 15:11:26 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2012-05-30 15:11:32 -0400 |
commit | bbd771474ec44b516107685d77e1c80bbe09f141 (patch) | |
tree | 0cb15781539a68f27b4ea6c89f827282630cbce6 /arch/x86/kernel | |
parent | 403e1c5b7495d7b80fae9fc4d0a7a6f5abdc3307 (diff) | |
parent | 319b6ffc6df892e4ccffff823cc5521a4a5d2dca (diff) |
Merge branch 'x86/trampoline' into x86/urgent
x86/trampoline contains an urgent commit which is necessarily on a
newer baseline.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel')
39 files changed, 149 insertions, 1030 deletions
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 | |||
35 | obj-y += pci-iommu_table.o | 35 | obj-y += pci-iommu_table.o |
36 | obj-y += resource.o | 36 | obj-y += resource.o |
37 | 37 | ||
38 | obj-y += trampoline.o trampoline_$(BITS).o | ||
39 | obj-y += process.o | 38 | obj-y += process.o |
40 | obj-y += i387.o xsave.o | 39 | obj-y += i387.o xsave.o |
41 | obj-y += ptrace.o | 40 | obj-y += ptrace.o |
@@ -48,7 +47,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o | |||
48 | obj-y += cpu/ | 47 | obj-y += cpu/ |
49 | obj-y += acpi/ | 48 | obj-y += acpi/ |
50 | obj-y += reboot.o | 49 | obj-y += reboot.o |
51 | obj-$(CONFIG_X86_32) += reboot_32.o | ||
52 | obj-$(CONFIG_X86_MSR) += msr.o | 50 | obj-$(CONFIG_X86_MSR) += msr.o |
53 | obj-$(CONFIG_X86_CPUID) += cpuid.o | 51 | obj-$(CONFIG_X86_CPUID) += cpuid.o |
54 | obj-$(CONFIG_PCI) += early-quirks.o | 52 | obj-$(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 @@ | |||
1 | subdir- := realmode | ||
2 | |||
3 | obj-$(CONFIG_ACPI) += boot.o | 1 | obj-$(CONFIG_ACPI) += boot.o |
4 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o | 2 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o |
5 | 3 | ||
6 | ifneq ($(CONFIG_ACPI_PROCESSOR),) | 4 | ifneq ($(CONFIG_ACPI_PROCESSOR),) |
7 | obj-y += cstate.o | 5 | obj-y += cstate.o |
8 | endif | 6 | endif |
9 | 7 | ||
10 | $(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin | ||
11 | |||
12 | $(obj)/realmode/wakeup.bin: FORCE | ||
13 | $(Q)$(MAKE) $(build)=$(obj)/realmode | ||
14 | |||
diff --git a/arch/x86/kernel/acpi/realmode/.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 @@ | |||
1 | wakeup.bin | ||
2 | wakeup.elf | ||
3 | wakeup.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 | |||
9 | always := wakeup.bin | ||
10 | targets := wakeup.elf wakeup.lds | ||
11 | |||
12 | wakeup-y += wakeup.o wakemain.o video-mode.o copy.o bioscall.o regs.o | ||
13 | |||
14 | # The link order of the video-*.o modules can matter. In particular, | ||
15 | # video-vga.o *must* be listed first, followed by video-vesa.o. | ||
16 | # Hardware-specific drivers should follow in the order they should be | ||
17 | # probed, and video-bios.o should typically be last. | ||
18 | wakeup-y += video-vga.o | ||
19 | wakeup-y += video-vesa.o | ||
20 | wakeup-y += video-bios.o | ||
21 | |||
22 | targets += $(wakeup-y) | ||
23 | |||
24 | bootsrc := $(src)/../../../boot | ||
25 | |||
26 | # --------------------------------------------------------------------------- | ||
27 | |||
28 | # How to compile the 16-bit code. Note we always compile for -march=i386, | ||
29 | # that way we can complain to the user if the CPU is insufficient. | ||
30 | # Compile with _SETUP since this is similar to the boot-time setup code. | ||
31 | KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D_WAKEUP -D__KERNEL__ \ | ||
32 | -I$(srctree)/$(bootsrc) \ | ||
33 | $(cflags-y) \ | ||
34 | -Wall -Wstrict-prototypes \ | ||
35 | -march=i386 -mregparm=3 \ | ||
36 | -include $(srctree)/$(bootsrc)/code16gcc.h \ | ||
37 | -fno-strict-aliasing -fomit-frame-pointer \ | ||
38 | $(call cc-option, -ffreestanding) \ | ||
39 | $(call cc-option, -fno-toplevel-reorder,\ | ||
40 | $(call cc-option, -fno-unit-at-a-time)) \ | ||
41 | $(call cc-option, -fno-stack-protector) \ | ||
42 | $(call cc-option, -mpreferred-stack-boundary=2) | ||
43 | KBUILD_CFLAGS += $(call cc-option, -m32) | ||
44 | KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ | ||
45 | GCOV_PROFILE := n | ||
46 | |||
47 | WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y)) | ||
48 | |||
49 | LDFLAGS_wakeup.elf := -T | ||
50 | |||
51 | CPPFLAGS_wakeup.lds += -P -C | ||
52 | |||
53 | $(obj)/wakeup.elf: $(obj)/wakeup.lds $(WAKEUP_OBJS) FORCE | ||
54 | $(call if_changed,ld) | ||
55 | |||
56 | OBJCOPYFLAGS_wakeup.bin := -O binary | ||
57 | |||
58 | $(obj)/wakeup.bin: $(obj)/wakeup.elf FORCE | ||
59 | $(call if_changed,objcopy) | ||
diff --git a/arch/x86/kernel/acpi/realmode/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/wakemain.c b/arch/x86/kernel/acpi/realmode/wakemain.c deleted file mode 100644 index 883962d9eef2..000000000000 --- a/arch/x86/kernel/acpi/realmode/wakemain.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | #include "wakeup.h" | ||
2 | #include "boot.h" | ||
3 | |||
4 | static void udelay(int loops) | ||
5 | { | ||
6 | while (loops--) | ||
7 | io_delay(); /* Approximately 1 us */ | ||
8 | } | ||
9 | |||
10 | static 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. */ | ||
39 | static 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 | |||
64 | void 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 deleted file mode 100644 index b4fd836e4053..000000000000 --- a/arch/x86/kernel/acpi/realmode/wakeup.S +++ /dev/null | |||
@@ -1,170 +0,0 @@ | |||
1 | /* | ||
2 | * ACPI wakeup real mode startup stub | ||
3 | */ | ||
4 | #include <asm/segment.h> | ||
5 | #include <asm/msr-index.h> | ||
6 | #include <asm/page_types.h> | ||
7 | #include <asm/pgtable_types.h> | ||
8 | #include <asm/processor-flags.h> | ||
9 | #include "wakeup.h" | ||
10 | |||
11 | .code16 | ||
12 | .section ".jump", "ax" | ||
13 | .globl _start | ||
14 | _start: | ||
15 | cli | ||
16 | jmp wakeup_code | ||
17 | |||
18 | /* This should match the structure in wakeup.h */ | ||
19 | .section ".header", "a" | ||
20 | .globl wakeup_header | ||
21 | wakeup_header: | ||
22 | video_mode: .short 0 /* Video mode number */ | ||
23 | pmode_return: .byte 0x66, 0xea /* ljmpl */ | ||
24 | .long 0 /* offset goes here */ | ||
25 | .short __KERNEL_CS | ||
26 | pmode_cr0: .long 0 /* Saved %cr0 */ | ||
27 | pmode_cr3: .long 0 /* Saved %cr3 */ | ||
28 | pmode_cr4: .long 0 /* Saved %cr4 */ | ||
29 | pmode_efer: .quad 0 /* Saved EFER */ | ||
30 | pmode_gdt: .quad 0 | ||
31 | pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */ | ||
32 | pmode_behavior: .long 0 /* Wakeup behavior flags */ | ||
33 | realmode_flags: .long 0 | ||
34 | real_magic: .long 0 | ||
35 | trampoline_segment: .word 0 | ||
36 | _pad1: .byte 0 | ||
37 | wakeup_jmp: .byte 0xea /* ljmpw */ | ||
38 | wakeup_jmp_off: .word 3f | ||
39 | wakeup_jmp_seg: .word 0 | ||
40 | wakeup_gdt: .quad 0, 0, 0 | ||
41 | signature: .long WAKEUP_HEADER_SIGNATURE | ||
42 | |||
43 | .text | ||
44 | .code16 | ||
45 | wakeup_code: | ||
46 | cld | ||
47 | |||
48 | /* Apparently some dimwit BIOS programmers don't know how to | ||
49 | program a PM to RM transition, and we might end up here with | ||
50 | junk in the data segment descriptor registers. The only way | ||
51 | to repair that is to go into PM and fix it ourselves... */ | ||
52 | movw $16, %cx | ||
53 | lgdtl %cs:wakeup_gdt | ||
54 | movl %cr0, %eax | ||
55 | orb $X86_CR0_PE, %al | ||
56 | movl %eax, %cr0 | ||
57 | jmp 1f | ||
58 | 1: ljmpw $8, $2f | ||
59 | 2: | ||
60 | movw %cx, %ds | ||
61 | movw %cx, %es | ||
62 | movw %cx, %ss | ||
63 | movw %cx, %fs | ||
64 | movw %cx, %gs | ||
65 | |||
66 | andb $~X86_CR0_PE, %al | ||
67 | movl %eax, %cr0 | ||
68 | jmp wakeup_jmp | ||
69 | 3: | ||
70 | /* Set up segments */ | ||
71 | movw %cs, %ax | ||
72 | movw %ax, %ds | ||
73 | movw %ax, %es | ||
74 | movw %ax, %ss | ||
75 | lidtl wakeup_idt | ||
76 | |||
77 | movl $wakeup_stack_end, %esp | ||
78 | |||
79 | /* Clear the EFLAGS */ | ||
80 | pushl $0 | ||
81 | popfl | ||
82 | |||
83 | /* Check header signature... */ | ||
84 | movl signature, %eax | ||
85 | cmpl $WAKEUP_HEADER_SIGNATURE, %eax | ||
86 | jne bogus_real_magic | ||
87 | |||
88 | /* Check we really have everything... */ | ||
89 | movl end_signature, %eax | ||
90 | cmpl $WAKEUP_END_SIGNATURE, %eax | ||
91 | jne bogus_real_magic | ||
92 | |||
93 | /* Call the C code */ | ||
94 | calll main | ||
95 | |||
96 | /* Restore MISC_ENABLE before entering protected mode, in case | ||
97 | BIOS decided to clear XD_DISABLE during S3. */ | ||
98 | movl pmode_behavior, %eax | ||
99 | btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax | ||
100 | jnc 1f | ||
101 | |||
102 | movl pmode_misc_en, %eax | ||
103 | movl pmode_misc_en + 4, %edx | ||
104 | movl $MSR_IA32_MISC_ENABLE, %ecx | ||
105 | wrmsr | ||
106 | 1: | ||
107 | |||
108 | /* Do any other stuff... */ | ||
109 | |||
110 | #ifndef CONFIG_64BIT | ||
111 | /* This could also be done in C code... */ | ||
112 | movl pmode_cr3, %eax | ||
113 | movl %eax, %cr3 | ||
114 | |||
115 | movl pmode_cr4, %ecx | ||
116 | jecxz 1f | ||
117 | movl %ecx, %cr4 | ||
118 | 1: | ||
119 | movl pmode_efer, %eax | ||
120 | movl pmode_efer + 4, %edx | ||
121 | movl %eax, %ecx | ||
122 | orl %edx, %ecx | ||
123 | jz 1f | ||
124 | movl $MSR_EFER, %ecx | ||
125 | wrmsr | ||
126 | 1: | ||
127 | |||
128 | lgdtl pmode_gdt | ||
129 | |||
130 | /* This really couldn't... */ | ||
131 | movl pmode_cr0, %eax | ||
132 | movl %eax, %cr0 | ||
133 | jmp pmode_return | ||
134 | #else | ||
135 | pushw $0 | ||
136 | pushw trampoline_segment | ||
137 | pushw $0 | ||
138 | lret | ||
139 | #endif | ||
140 | |||
141 | bogus_real_magic: | ||
142 | 1: | ||
143 | hlt | ||
144 | jmp 1b | ||
145 | |||
146 | .data | ||
147 | .balign 8 | ||
148 | |||
149 | /* This is the standard real-mode IDT */ | ||
150 | wakeup_idt: | ||
151 | .word 0xffff /* limit */ | ||
152 | .long 0 /* address */ | ||
153 | .word 0 | ||
154 | |||
155 | .globl HEAP, heap_end | ||
156 | HEAP: | ||
157 | .long wakeup_heap | ||
158 | heap_end: | ||
159 | .long wakeup_stack | ||
160 | |||
161 | .bss | ||
162 | wakeup_heap: | ||
163 | .space 2048 | ||
164 | wakeup_stack: | ||
165 | .space 2048 | ||
166 | wakeup_stack_end: | ||
167 | |||
168 | .section ".signature","a" | ||
169 | end_signature: | ||
170 | .long WAKEUP_END_SIGNATURE | ||
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h deleted file mode 100644 index 97a29e1430e3..000000000000 --- a/arch/x86/kernel/acpi/realmode/wakeup.h +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
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 */ | ||
13 | struct 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 pmode_misc_en_low; /* Protected mode MISC_ENABLE */ | ||
25 | u32 pmode_misc_en_high; | ||
26 | u32 pmode_behavior; /* Wakeup routine behavior flags */ | ||
27 | u32 realmode_flags; | ||
28 | 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 */ | ||
36 | } __attribute__((__packed__)); | ||
37 | |||
38 | extern struct wakeup_header wakeup_header; | ||
39 | #endif | ||
40 | |||
41 | #define WAKEUP_HEADER_OFFSET 8 | ||
42 | #define WAKEUP_HEADER_SIGNATURE 0x51ee1111 | ||
43 | #define WAKEUP_END_SIGNATURE 0x65a22c82 | ||
44 | |||
45 | /* Wakeup behavior bits */ | ||
46 | #define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 | ||
47 | |||
48 | #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 deleted file mode 100644 index d4f8010a5b1b..000000000000 --- a/arch/x86/kernel/acpi/realmode/wakeup.lds.S +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /* | ||
2 | * wakeup.ld | ||
3 | * | ||
4 | * Linker script for the real-mode wakeup code | ||
5 | */ | ||
6 | #undef i386 | ||
7 | #include "wakeup.h" | ||
8 | |||
9 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | ||
10 | OUTPUT_ARCH(i386) | ||
11 | ENTRY(_start) | ||
12 | |||
13 | SECTIONS | ||
14 | { | ||
15 | . = 0; | ||
16 | .jump : { | ||
17 | *(.jump) | ||
18 | } = 0x90909090 | ||
19 | |||
20 | . = WAKEUP_HEADER_OFFSET; | ||
21 | .header : { | ||
22 | *(.header) | ||
23 | } | ||
24 | |||
25 | . = ALIGN(16); | ||
26 | .text : { | ||
27 | *(.text*) | ||
28 | } = 0x90909090 | ||
29 | |||
30 | . = ALIGN(16); | ||
31 | .rodata : { | ||
32 | *(.rodata*) | ||
33 | } | ||
34 | |||
35 | .videocards : { | ||
36 | video_cards = .; | ||
37 | *(.videocards) | ||
38 | video_cards_end = .; | ||
39 | } | ||
40 | |||
41 | . = ALIGN(16); | ||
42 | .data : { | ||
43 | *(.data*) | ||
44 | } | ||
45 | |||
46 | . = ALIGN(16); | ||
47 | .bss : { | ||
48 | __bss_start = .; | ||
49 | *(.bss) | ||
50 | __bss_end = .; | ||
51 | } | ||
52 | |||
53 | .signature : { | ||
54 | *(.signature) | ||
55 | } | ||
56 | |||
57 | _end = .; | ||
58 | |||
59 | /DISCARD/ : { | ||
60 | *(.note*) | ||
61 | } | ||
62 | } | ||
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 146a49c763a4..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 | ||
21 | unsigned long acpi_realmode_flags; | 22 | unsigned long acpi_realmode_flags; |
@@ -36,13 +37,9 @@ asmlinkage void acpi_enter_s3(void) | |||
36 | */ | 37 | */ |
37 | int acpi_suspend_lowlevel(void) | 38 | int acpi_suspend_lowlevel(void) |
38 | { | 39 | { |
39 | struct wakeup_header *header; | 40 | struct wakeup_header *header = |
40 | /* address in low memory of the wakeup routine. */ | 41 | (struct wakeup_header *) __va(real_mode_header->wakeup_header); |
41 | char *acpi_realmode; | ||
42 | 42 | ||
43 | acpi_realmode = TRAMPOLINE_SYM(acpi_wakeup_code); | ||
44 | |||
45 | header = (struct wakeup_header *)(acpi_realmode + WAKEUP_HEADER_OFFSET); | ||
46 | if (header->signature != WAKEUP_HEADER_SIGNATURE) { | 43 | if (header->signature != WAKEUP_HEADER_SIGNATURE) { |
47 | printk(KERN_ERR "wakeup header does not match\n"); | 44 | printk(KERN_ERR "wakeup header does not match\n"); |
48 | return -EINVAL; | 45 | return -EINVAL; |
@@ -50,27 +47,6 @@ int acpi_suspend_lowlevel(void) | |||
50 | 47 | ||
51 | header->video_mode = saved_video_mode; | 48 | header->video_mode = saved_video_mode; |
52 | 49 | ||
53 | header->wakeup_jmp_seg = acpi_wakeup_address >> 4; | ||
54 | |||
55 | /* | ||
56 | * Set up the wakeup GDT. We set these up as Big Real Mode, | ||
57 | * that is, with limits set to 4 GB. At least the Lenovo | ||
58 | * Thinkpad X61 is known to need this for the video BIOS | ||
59 | * initialization quirk to work; this is likely to also | ||
60 | * be the case for other laptops or integrated video devices. | ||
61 | */ | ||
62 | |||
63 | /* GDT[0]: GDT self-pointer */ | ||
64 | header->wakeup_gdt[0] = | ||
65 | (u64)(sizeof(header->wakeup_gdt) - 1) + | ||
66 | ((u64)__pa(&header->wakeup_gdt) << 16); | ||
67 | /* GDT[1]: big real mode-like code segment */ | ||
68 | header->wakeup_gdt[1] = | ||
69 | GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff); | ||
70 | /* GDT[2]: big real mode-like data segment */ | ||
71 | header->wakeup_gdt[2] = | ||
72 | GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff); | ||
73 | |||
74 | #ifndef CONFIG_64BIT | 50 | #ifndef CONFIG_64BIT |
75 | store_gdt((struct desc_ptr *)&header->pmode_gdt); | 51 | store_gdt((struct desc_ptr *)&header->pmode_gdt); |
76 | 52 | ||
@@ -95,7 +71,6 @@ int acpi_suspend_lowlevel(void) | |||
95 | header->pmode_cr3 = (u32)__pa(&initial_page_table); | 71 | header->pmode_cr3 = (u32)__pa(&initial_page_table); |
96 | saved_magic = 0x12345678; | 72 | saved_magic = 0x12345678; |
97 | #else /* CONFIG_64BIT */ | 73 | #else /* CONFIG_64BIT */ |
98 | header->trampoline_segment = trampoline_address() >> 4; | ||
99 | #ifdef CONFIG_SMP | 74 | #ifdef CONFIG_SMP |
100 | stack_start = (unsigned long)temp_stack + sizeof(temp_stack); | 75 | stack_start = (unsigned long)temp_stack + sizeof(temp_stack); |
101 | early_gdt_descr.address = | 76 | early_gdt_descr.address = |
diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index d68677a2a010..5653a5791ec9 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h | |||
@@ -2,8 +2,8 @@ | |||
2 | * Variables and functions used by the code in sleep.c | 2 | * Variables and functions used by the code in sleep.c |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <asm/trampoline.h> | ||
6 | #include <linux/linkage.h> | 5 | #include <linux/linkage.h> |
6 | #include <asm/realmode.h> | ||
7 | 7 | ||
8 | extern unsigned long saved_video_mode; | 8 | extern unsigned long saved_video_mode; |
9 | extern long saved_magic; | 9 | extern long saved_magic; |
diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S deleted file mode 100644 index 63b8ab524f2c..000000000000 --- a/arch/x86/kernel/acpi/wakeup_rm.S +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | /* | ||
2 | * Wrapper script for the realmode binary as a transport object | ||
3 | * before copying to low memory. | ||
4 | */ | ||
5 | #include <asm/page_types.h> | ||
6 | |||
7 | .section ".x86_trampoline","a" | ||
8 | .balign PAGE_SIZE | ||
9 | .globl acpi_wakeup_code | ||
10 | acpi_wakeup_code: | ||
11 | .incbin "arch/x86/kernel/acpi/realmode/wakeup.bin" | ||
12 | .size acpi_wakeup_code, .-acpi_wakeup_code | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-apei.c b/arch/x86/kernel/cpu/mcheck/mce-apei.c index 507ea58688e2..cd8b166a1735 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-apei.c +++ b/arch/x86/kernel/cpu/mcheck/mce-apei.c | |||
@@ -42,7 +42,8 @@ void apei_mce_report_mem_error(int corrected, struct cper_sec_mem_err *mem_err) | |||
42 | struct mce m; | 42 | struct mce m; |
43 | 43 | ||
44 | /* Only corrected MC is reported */ | 44 | /* Only corrected MC is reported */ |
45 | if (!corrected) | 45 | if (!corrected || !(mem_err->validation_bits & |
46 | CPER_MEM_VALID_PHYSICAL_ADDRESS)) | ||
46 | return; | 47 | return; |
47 | 48 | ||
48 | mce_setup(&m); | 49 | mce_setup(&m); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 0c82091b1652..413c2ced887c 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c | |||
@@ -126,6 +126,16 @@ static struct severity { | |||
126 | SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA), | 126 | SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA), |
127 | USER | 127 | USER |
128 | ), | 128 | ), |
129 | MCESEV( | ||
130 | KEEP, "HT thread notices Action required: instruction fetch error", | ||
131 | SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR), | ||
132 | MCGMASK(MCG_STATUS_EIPV, 0) | ||
133 | ), | ||
134 | MCESEV( | ||
135 | AR, "Action required: instruction fetch error", | ||
136 | SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR), | ||
137 | USER | ||
138 | ), | ||
129 | #endif | 139 | #endif |
130 | MCESEV( | 140 | MCESEV( |
131 | PANIC, "Action required: unknown MCACOD", | 141 | PANIC, "Action required: unknown MCACOD", |
@@ -165,15 +175,19 @@ static struct severity { | |||
165 | }; | 175 | }; |
166 | 176 | ||
167 | /* | 177 | /* |
168 | * If the EIPV bit is set, it means the saved IP is the | 178 | * If mcgstatus indicated that ip/cs on the stack were |
169 | * instruction which caused the MCE. | 179 | * no good, then "m->cs" will be zero and we will have |
180 | * to assume the worst case (IN_KERNEL) as we actually | ||
181 | * have no idea what we were executing when the machine | ||
182 | * check hit. | ||
183 | * If we do have a good "m->cs" (or a faked one in the | ||
184 | * case we were executing in VM86 mode) we can use it to | ||
185 | * distinguish an exception taken in user from from one | ||
186 | * taken in the kernel. | ||
170 | */ | 187 | */ |
171 | static int error_context(struct mce *m) | 188 | static int error_context(struct mce *m) |
172 | { | 189 | { |
173 | if (m->mcgstatus & MCG_STATUS_EIPV) | 190 | return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL; |
174 | return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL; | ||
175 | /* Unknown, assume kernel */ | ||
176 | return IN_KERNEL; | ||
177 | } | 191 | } |
178 | 192 | ||
179 | int mce_severity(struct mce *m, int tolerant, char **msg) | 193 | int mce_severity(struct mce *m, int tolerant, char **msg) |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index aaa056f31693..b4180f425fb8 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -437,6 +437,14 @@ static inline void mce_gather_info(struct mce *m, struct pt_regs *regs) | |||
437 | if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) { | 437 | if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) { |
438 | m->ip = regs->ip; | 438 | m->ip = regs->ip; |
439 | m->cs = regs->cs; | 439 | m->cs = regs->cs; |
440 | |||
441 | /* | ||
442 | * When in VM86 mode make the cs look like ring 3 | ||
443 | * always. This is a lie, but it's better than passing | ||
444 | * the additional vm86 bit around everywhere. | ||
445 | */ | ||
446 | if (v8086_mode(regs)) | ||
447 | m->cs |= 3; | ||
440 | } | 448 | } |
441 | /* Use accurate RIP reporting if available. */ | 449 | /* Use accurate RIP reporting if available. */ |
442 | if (rip_msr) | 450 | if (rip_msr) |
@@ -641,16 +649,18 @@ EXPORT_SYMBOL_GPL(machine_check_poll); | |||
641 | * Do a quick check if any of the events requires a panic. | 649 | * Do a quick check if any of the events requires a panic. |
642 | * This decides if we keep the events around or clear them. | 650 | * This decides if we keep the events around or clear them. |
643 | */ | 651 | */ |
644 | static int mce_no_way_out(struct mce *m, char **msg) | 652 | static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp) |
645 | { | 653 | { |
646 | int i; | 654 | int i, ret = 0; |
647 | 655 | ||
648 | for (i = 0; i < banks; i++) { | 656 | for (i = 0; i < banks; i++) { |
649 | m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); | 657 | m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); |
658 | if (m->status & MCI_STATUS_VAL) | ||
659 | __set_bit(i, validp); | ||
650 | if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) | 660 | if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) |
651 | return 1; | 661 | ret = 1; |
652 | } | 662 | } |
653 | return 0; | 663 | return ret; |
654 | } | 664 | } |
655 | 665 | ||
656 | /* | 666 | /* |
@@ -1013,6 +1023,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1013 | */ | 1023 | */ |
1014 | int kill_it = 0; | 1024 | int kill_it = 0; |
1015 | DECLARE_BITMAP(toclear, MAX_NR_BANKS); | 1025 | DECLARE_BITMAP(toclear, MAX_NR_BANKS); |
1026 | DECLARE_BITMAP(valid_banks, MAX_NR_BANKS); | ||
1016 | char *msg = "Unknown"; | 1027 | char *msg = "Unknown"; |
1017 | 1028 | ||
1018 | atomic_inc(&mce_entry); | 1029 | atomic_inc(&mce_entry); |
@@ -1027,7 +1038,8 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1027 | final = &__get_cpu_var(mces_seen); | 1038 | final = &__get_cpu_var(mces_seen); |
1028 | *final = m; | 1039 | *final = m; |
1029 | 1040 | ||
1030 | no_way_out = mce_no_way_out(&m, &msg); | 1041 | memset(valid_banks, 0, sizeof(valid_banks)); |
1042 | no_way_out = mce_no_way_out(&m, &msg, valid_banks); | ||
1031 | 1043 | ||
1032 | barrier(); | 1044 | barrier(); |
1033 | 1045 | ||
@@ -1047,6 +1059,8 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1047 | order = mce_start(&no_way_out); | 1059 | order = mce_start(&no_way_out); |
1048 | for (i = 0; i < banks; i++) { | 1060 | for (i = 0; i < banks; i++) { |
1049 | __clear_bit(i, toclear); | 1061 | __clear_bit(i, toclear); |
1062 | if (!test_bit(i, valid_banks)) | ||
1063 | continue; | ||
1050 | if (!mce_banks[i].ctl) | 1064 | if (!mce_banks[i].ctl) |
1051 | continue; | 1065 | continue; |
1052 | 1066 | ||
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 62d61e9976eb..41857970517f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -113,7 +113,9 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size, | |||
113 | int x = e820x->nr_map; | 113 | int x = e820x->nr_map; |
114 | 114 | ||
115 | if (x >= ARRAY_SIZE(e820x->map)) { | 115 | if (x >= ARRAY_SIZE(e820x->map)) { |
116 | printk(KERN_ERR "Ooops! Too many entries in the memory map!\n"); | 116 | printk(KERN_ERR "e820: too many entries; ignoring [mem %#010llx-%#010llx]\n", |
117 | (unsigned long long) start, | ||
118 | (unsigned long long) (start + size - 1)); | ||
117 | return; | 119 | return; |
118 | } | 120 | } |
119 | 121 | ||
@@ -133,19 +135,19 @@ static void __init e820_print_type(u32 type) | |||
133 | switch (type) { | 135 | switch (type) { |
134 | case E820_RAM: | 136 | case E820_RAM: |
135 | case E820_RESERVED_KERN: | 137 | case E820_RESERVED_KERN: |
136 | printk(KERN_CONT "(usable)"); | 138 | printk(KERN_CONT "usable"); |
137 | break; | 139 | break; |
138 | case E820_RESERVED: | 140 | case E820_RESERVED: |
139 | printk(KERN_CONT "(reserved)"); | 141 | printk(KERN_CONT "reserved"); |
140 | break; | 142 | break; |
141 | case E820_ACPI: | 143 | case E820_ACPI: |
142 | printk(KERN_CONT "(ACPI data)"); | 144 | printk(KERN_CONT "ACPI data"); |
143 | break; | 145 | break; |
144 | case E820_NVS: | 146 | case E820_NVS: |
145 | printk(KERN_CONT "(ACPI NVS)"); | 147 | printk(KERN_CONT "ACPI NVS"); |
146 | break; | 148 | break; |
147 | case E820_UNUSABLE: | 149 | case E820_UNUSABLE: |
148 | printk(KERN_CONT "(unusable)"); | 150 | printk(KERN_CONT "unusable"); |
149 | break; | 151 | break; |
150 | default: | 152 | default: |
151 | printk(KERN_CONT "type %u", type); | 153 | printk(KERN_CONT "type %u", type); |
@@ -158,10 +160,10 @@ void __init e820_print_map(char *who) | |||
158 | int i; | 160 | int i; |
159 | 161 | ||
160 | for (i = 0; i < e820.nr_map; i++) { | 162 | for (i = 0; i < e820.nr_map; i++) { |
161 | printk(KERN_INFO " %s: %016Lx - %016Lx ", who, | 163 | printk(KERN_INFO "%s: [mem %#018Lx-%#018Lx] ", who, |
162 | (unsigned long long) e820.map[i].addr, | 164 | (unsigned long long) e820.map[i].addr, |
163 | (unsigned long long) | 165 | (unsigned long long) |
164 | (e820.map[i].addr + e820.map[i].size)); | 166 | (e820.map[i].addr + e820.map[i].size - 1)); |
165 | e820_print_type(e820.map[i].type); | 167 | e820_print_type(e820.map[i].type); |
166 | printk(KERN_CONT "\n"); | 168 | printk(KERN_CONT "\n"); |
167 | } | 169 | } |
@@ -428,9 +430,8 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start, | |||
428 | size = ULLONG_MAX - start; | 430 | size = ULLONG_MAX - start; |
429 | 431 | ||
430 | end = start + size; | 432 | end = start + size; |
431 | printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ", | 433 | printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", |
432 | (unsigned long long) start, | 434 | (unsigned long long) start, (unsigned long long) (end - 1)); |
433 | (unsigned long long) end); | ||
434 | e820_print_type(old_type); | 435 | e820_print_type(old_type); |
435 | printk(KERN_CONT " ==> "); | 436 | printk(KERN_CONT " ==> "); |
436 | e820_print_type(new_type); | 437 | e820_print_type(new_type); |
@@ -509,9 +510,8 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type, | |||
509 | size = ULLONG_MAX - start; | 510 | size = ULLONG_MAX - start; |
510 | 511 | ||
511 | end = start + size; | 512 | end = start + size; |
512 | printk(KERN_DEBUG "e820 remove range: %016Lx - %016Lx ", | 513 | printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ", |
513 | (unsigned long long) start, | 514 | (unsigned long long) start, (unsigned long long) (end - 1)); |
514 | (unsigned long long) end); | ||
515 | if (checktype) | 515 | if (checktype) |
516 | e820_print_type(old_type); | 516 | e820_print_type(old_type); |
517 | printk(KERN_CONT "\n"); | 517 | printk(KERN_CONT "\n"); |
@@ -567,7 +567,7 @@ void __init update_e820(void) | |||
567 | if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map)) | 567 | if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map)) |
568 | return; | 568 | return; |
569 | e820.nr_map = nr_map; | 569 | e820.nr_map = nr_map; |
570 | printk(KERN_INFO "modified physical RAM map:\n"); | 570 | printk(KERN_INFO "e820: modified physical RAM map:\n"); |
571 | e820_print_map("modified"); | 571 | e820_print_map("modified"); |
572 | } | 572 | } |
573 | static void __init update_e820_saved(void) | 573 | static void __init update_e820_saved(void) |
@@ -637,8 +637,8 @@ __init void e820_setup_gap(void) | |||
637 | if (!found) { | 637 | if (!found) { |
638 | gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024; | 638 | gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024; |
639 | printk(KERN_ERR | 639 | printk(KERN_ERR |
640 | "PCI: Warning: Cannot find a gap in the 32bit address range\n" | 640 | "e820: cannot find a gap in the 32bit address range\n" |
641 | "PCI: Unassigned devices with 32bit resource registers may break!\n"); | 641 | "e820: PCI devices with unassigned 32bit BARs may break!\n"); |
642 | } | 642 | } |
643 | #endif | 643 | #endif |
644 | 644 | ||
@@ -648,8 +648,8 @@ __init void e820_setup_gap(void) | |||
648 | pci_mem_start = gapstart; | 648 | pci_mem_start = gapstart; |
649 | 649 | ||
650 | printk(KERN_INFO | 650 | printk(KERN_INFO |
651 | "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", | 651 | "e820: [mem %#010lx-%#010lx] available for PCI devices\n", |
652 | pci_mem_start, gapstart, gapsize); | 652 | gapstart, gapstart + gapsize - 1); |
653 | } | 653 | } |
654 | 654 | ||
655 | /** | 655 | /** |
@@ -667,7 +667,7 @@ void __init parse_e820_ext(struct setup_data *sdata) | |||
667 | extmap = (struct e820entry *)(sdata->data); | 667 | extmap = (struct e820entry *)(sdata->data); |
668 | __append_e820_map(extmap, entries); | 668 | __append_e820_map(extmap, entries); |
669 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | 669 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); |
670 | printk(KERN_INFO "extended physical RAM map:\n"); | 670 | printk(KERN_INFO "e820: extended physical RAM map:\n"); |
671 | e820_print_map("extended"); | 671 | e820_print_map("extended"); |
672 | } | 672 | } |
673 | 673 | ||
@@ -734,7 +734,7 @@ u64 __init early_reserve_e820(u64 size, u64 align) | |||
734 | addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); | 734 | addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); |
735 | if (addr) { | 735 | if (addr) { |
736 | e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED); | 736 | e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED); |
737 | printk(KERN_INFO "update e820_saved for early_reserve_e820\n"); | 737 | printk(KERN_INFO "e820: update e820_saved for early_reserve_e820\n"); |
738 | update_e820_saved(); | 738 | update_e820_saved(); |
739 | } | 739 | } |
740 | 740 | ||
@@ -784,7 +784,7 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) | |||
784 | if (last_pfn > max_arch_pfn) | 784 | if (last_pfn > max_arch_pfn) |
785 | last_pfn = max_arch_pfn; | 785 | last_pfn = max_arch_pfn; |
786 | 786 | ||
787 | printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n", | 787 | printk(KERN_INFO "e820: last_pfn = %#lx max_arch_pfn = %#lx\n", |
788 | last_pfn, max_arch_pfn); | 788 | last_pfn, max_arch_pfn); |
789 | return last_pfn; | 789 | return last_pfn; |
790 | } | 790 | } |
@@ -888,7 +888,7 @@ void __init finish_e820_parsing(void) | |||
888 | early_panic("Invalid user supplied memory map"); | 888 | early_panic("Invalid user supplied memory map"); |
889 | e820.nr_map = nr; | 889 | e820.nr_map = nr; |
890 | 890 | ||
891 | printk(KERN_INFO "user-defined physical RAM map:\n"); | 891 | printk(KERN_INFO "e820: user-defined physical RAM map:\n"); |
892 | e820_print_map("user"); | 892 | e820_print_map("user"); |
893 | } | 893 | } |
894 | } | 894 | } |
@@ -996,8 +996,9 @@ void __init e820_reserve_resources_late(void) | |||
996 | end = MAX_RESOURCE_SIZE; | 996 | end = MAX_RESOURCE_SIZE; |
997 | if (start >= end) | 997 | if (start >= end) |
998 | continue; | 998 | continue; |
999 | printk(KERN_DEBUG "reserve RAM buffer: %016llx - %016llx ", | 999 | printk(KERN_DEBUG |
1000 | start, end); | 1000 | "e820: reserve RAM buffer [mem %#010llx-%#010llx]\n", |
1001 | start, end); | ||
1001 | reserve_region_with_split(&iomem_resource, start, end, | 1002 | reserve_region_with_split(&iomem_resource, start, end, |
1002 | "RAM buffer"); | 1003 | "RAM buffer"); |
1003 | } | 1004 | } |
@@ -1047,7 +1048,7 @@ void __init setup_memory_map(void) | |||
1047 | 1048 | ||
1048 | who = x86_init.resources.memory_setup(); | 1049 | who = x86_init.resources.memory_setup(); |
1049 | memcpy(&e820_saved, &e820, sizeof(struct e820map)); | 1050 | memcpy(&e820_saved, &e820, sizeof(struct e820map)); |
1050 | printk(KERN_INFO "BIOS-provided physical RAM map:\n"); | 1051 | printk(KERN_INFO "e820: BIOS-provided physical RAM map:\n"); |
1051 | e820_print_map(who); | 1052 | e820_print_map(who); |
1052 | } | 1053 | } |
1053 | 1054 | ||
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 51ff18616d50..c18f59d10101 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <asm/sections.h> | 14 | #include <asm/sections.h> |
15 | #include <asm/e820.h> | 15 | #include <asm/e820.h> |
16 | #include <asm/page.h> | 16 | #include <asm/page.h> |
17 | #include <asm/trampoline.h> | ||
18 | #include <asm/apic.h> | 17 | #include <asm/apic.h> |
19 | #include <asm/io_apic.h> | 18 | #include <asm/io_apic.h> |
20 | #include <asm/bios_ebda.h> | 19 | #include <asm/bios_ebda.h> |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 3a3b779f41d3..037df57a99ac 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <asm/sections.h> | 24 | #include <asm/sections.h> |
25 | #include <asm/kdebug.h> | 25 | #include <asm/kdebug.h> |
26 | #include <asm/e820.h> | 26 | #include <asm/e820.h> |
27 | #include <asm/trampoline.h> | ||
28 | #include <asm/bios_ebda.h> | 27 | #include <asm/bios_ebda.h> |
29 | 28 | ||
30 | static void __init zap_identity_mappings(void) | 29 | static void __init zap_identity_mappings(void) |
diff --git a/arch/x86/kernel/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 | ||
281 | ENTRY(startup_32_smp) | 278 | ENTRY(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 | |
292 | default_entry: | 289 | default_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/kvmclock.c b/arch/x86/kernel/kvmclock.c index f8492da65bfc..086eb58c6e80 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/msr.h> | 22 | #include <asm/msr.h> |
23 | #include <asm/apic.h> | 23 | #include <asm/apic.h> |
24 | #include <linux/percpu.h> | 24 | #include <linux/percpu.h> |
25 | #include <linux/hardirq.h> | ||
25 | 26 | ||
26 | #include <asm/x86_init.h> | 27 | #include <asm/x86_init.h> |
27 | #include <asm/reboot.h> | 28 | #include <asm/reboot.h> |
@@ -114,6 +115,25 @@ static void kvm_get_preset_lpj(void) | |||
114 | preset_lpj = lpj; | 115 | preset_lpj = lpj; |
115 | } | 116 | } |
116 | 117 | ||
118 | bool kvm_check_and_clear_guest_paused(void) | ||
119 | { | ||
120 | bool ret = false; | ||
121 | struct pvclock_vcpu_time_info *src; | ||
122 | |||
123 | /* | ||
124 | * per_cpu() is safe here because this function is only called from | ||
125 | * timer functions where preemption is already disabled. | ||
126 | */ | ||
127 | WARN_ON(!in_atomic()); | ||
128 | src = &__get_cpu_var(hv_clock); | ||
129 | if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) { | ||
130 | __this_cpu_and(hv_clock.flags, ~PVCLOCK_GUEST_STOPPED); | ||
131 | ret = true; | ||
132 | } | ||
133 | |||
134 | return ret; | ||
135 | } | ||
136 | |||
117 | static struct clocksource kvm_clock = { | 137 | static struct clocksource kvm_clock = { |
118 | .name = "kvm-clock", | 138 | .name = "kvm-clock", |
119 | .read = kvm_clock_get_cycles, | 139 | .read = kvm_clock_get_cycles, |
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index b02d4dd6b8a3..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 | ||
@@ -568,8 +567,8 @@ static int __init smp_scan_config(unsigned long base, unsigned long length) | |||
568 | struct mpf_intel *mpf; | 567 | struct mpf_intel *mpf; |
569 | unsigned long mem; | 568 | unsigned long mem; |
570 | 569 | ||
571 | apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n", | 570 | apic_printk(APIC_VERBOSE, "Scan for SMP in [mem %#010lx-%#010lx]\n", |
572 | bp, length); | 571 | base, base + length - 1); |
573 | BUILD_BUG_ON(sizeof(*mpf) != 16); | 572 | BUILD_BUG_ON(sizeof(*mpf) != 16); |
574 | 573 | ||
575 | while (length > 0) { | 574 | while (length > 0) { |
@@ -584,8 +583,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length) | |||
584 | #endif | 583 | #endif |
585 | mpf_found = mpf; | 584 | mpf_found = mpf; |
586 | 585 | ||
587 | printk(KERN_INFO "found SMP MP-table at [%p] %llx\n", | 586 | printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n", |
588 | mpf, (u64)virt_to_phys(mpf)); | 587 | (unsigned long long) virt_to_phys(mpf), |
588 | (unsigned long long) virt_to_phys(mpf) + | ||
589 | sizeof(*mpf) - 1, mpf); | ||
589 | 590 | ||
590 | mem = virt_to_phys(mpf); | 591 | mem = virt_to_phys(mpf); |
591 | memblock_reserve(mem, sizeof(*mpf)); | 592 | memblock_reserve(mem, sizeof(*mpf)); |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 3003250ac51d..62c9457ccd2f 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -100,14 +100,18 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, | |||
100 | struct dma_attrs *attrs) | 100 | struct dma_attrs *attrs) |
101 | { | 101 | { |
102 | unsigned long dma_mask; | 102 | unsigned long dma_mask; |
103 | struct page *page; | 103 | struct page *page = NULL; |
104 | unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
104 | dma_addr_t addr; | 105 | dma_addr_t addr; |
105 | 106 | ||
106 | dma_mask = dma_alloc_coherent_mask(dev, flag); | 107 | dma_mask = dma_alloc_coherent_mask(dev, flag); |
107 | 108 | ||
108 | flag |= __GFP_ZERO; | 109 | flag |= __GFP_ZERO; |
109 | again: | 110 | again: |
110 | page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); | 111 | if (!(flag & GFP_ATOMIC)) |
112 | page = dma_alloc_from_contiguous(dev, count, get_order(size)); | ||
113 | if (!page) | ||
114 | page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); | ||
111 | if (!page) | 115 | if (!page) |
112 | return NULL; | 116 | return NULL; |
113 | 117 | ||
@@ -127,6 +131,16 @@ again: | |||
127 | return page_address(page); | 131 | return page_address(page); |
128 | } | 132 | } |
129 | 133 | ||
134 | void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, | ||
135 | dma_addr_t dma_addr, struct dma_attrs *attrs) | ||
136 | { | ||
137 | unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
138 | struct page *page = virt_to_page(vaddr); | ||
139 | |||
140 | if (!dma_release_from_contiguous(dev, page, count)) | ||
141 | free_pages((unsigned long)vaddr, get_order(size)); | ||
142 | } | ||
143 | |||
130 | /* | 144 | /* |
131 | * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel | 145 | * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel |
132 | * parameter documentation. | 146 | * parameter documentation. |
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index f96050685b46..871be4a84c7d 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c | |||
@@ -74,12 +74,6 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, | |||
74 | return nents; | 74 | return nents; |
75 | } | 75 | } |
76 | 76 | ||
77 | static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, | ||
78 | dma_addr_t dma_addr, struct dma_attrs *attrs) | ||
79 | { | ||
80 | free_pages((unsigned long)vaddr, get_order(size)); | ||
81 | } | ||
82 | |||
83 | static void nommu_sync_single_for_device(struct device *dev, | 77 | static void nommu_sync_single_for_device(struct device *dev, |
84 | dma_addr_t addr, size_t size, | 78 | dma_addr_t addr, size_t size, |
85 | enum dma_data_direction dir) | 79 | enum dma_data_direction dir) |
@@ -97,7 +91,7 @@ static void nommu_sync_sg_for_device(struct device *dev, | |||
97 | 91 | ||
98 | struct dma_map_ops nommu_dma_ops = { | 92 | struct dma_map_ops nommu_dma_ops = { |
99 | .alloc = dma_generic_alloc_coherent, | 93 | .alloc = dma_generic_alloc_coherent, |
100 | .free = nommu_free_coherent, | 94 | .free = dma_generic_free_coherent, |
101 | .map_sg = nommu_map_sg, | 95 | .map_sg = nommu_map_sg, |
102 | .map_page = nommu_map_page, | 96 | .map_page = nommu_map_page, |
103 | .sync_single_for_device = nommu_sync_single_for_device, | 97 | .sync_single_for_device = nommu_sync_single_for_device, |
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 | ||
159 | extern const unsigned char machine_real_restart_asm[]; | ||
160 | extern const u64 machine_real_restart_gdt[3]; | ||
161 | |||
162 | void machine_real_restart(unsigned int type) | 160 | void 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/reboot_32.S b/arch/x86/kernel/reboot_32.S deleted file mode 100644 index 1d5c46df0d78..000000000000 --- a/arch/x86/kernel/reboot_32.S +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | #include <linux/linkage.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <asm/segment.h> | ||
4 | #include <asm/page_types.h> | ||
5 | |||
6 | /* | ||
7 | * The following code and data reboots the machine by switching to real | ||
8 | * mode and jumping to the BIOS reset entry point, as if the CPU has | ||
9 | * really been reset. The previous version asked the keyboard | ||
10 | * controller to pulse the CPU reset line, which is more thorough, but | ||
11 | * doesn't work with at least one type of 486 motherboard. It is easy | ||
12 | * to stop this code working; hence the copious comments. | ||
13 | * | ||
14 | * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax. | ||
15 | */ | ||
16 | .section ".x86_trampoline","a" | ||
17 | .balign 16 | ||
18 | .code32 | ||
19 | ENTRY(machine_real_restart_asm) | ||
20 | r_base = . | ||
21 | /* Get our own relocated address */ | ||
22 | call 1f | ||
23 | 1: 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 | |||
35 | /* Set up the IDT for real mode. */ | ||
36 | lidtl (machine_real_restart_idt - r_base)(%ebx) | ||
37 | |||
38 | /* | ||
39 | * 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 | ||
41 | * prepare the descriptors. | ||
42 | */ | ||
43 | lgdtl (machine_real_restart_gdt - r_base)(%ebx) | ||
44 | |||
45 | /* | ||
46 | * Load the data segment registers with 16-bit compatible values | ||
47 | */ | ||
48 | movl $16, %ecx | ||
49 | movl %ecx, %ds | ||
50 | movl %ecx, %es | ||
51 | movl %ecx, %fs | ||
52 | movl %ecx, %gs | ||
53 | movl %ecx, %ss | ||
54 | ljmpl $8, $1f - r_base | ||
55 | |||
56 | /* | ||
57 | * This is 16-bit protected mode code to disable paging and the cache, | ||
58 | * switch to real mode and jump to the BIOS reset code. | ||
59 | * | ||
60 | * The instruction that switches to real mode by writing to CR0 must be | ||
61 | * followed immediately by a far jump instruction, which set CS to a | ||
62 | * valid value for real mode, and flushes the prefetch queue to avoid | ||
63 | * running instructions that have already been decoded in protected | ||
64 | * mode. | ||
65 | * | ||
66 | * Clears all the flags except ET, especially PG (paging), PE | ||
67 | * (protected-mode enable) and TS (task switch for coprocessor state | ||
68 | * save). Flushes the TLB after paging has been disabled. Sets CD and | ||
69 | * NW, to disable the cache on a 486, and invalidates the cache. This | ||
70 | * is more like the state of a 486 after reset. I don't know if | ||
71 | * something else should be done for other chips. | ||
72 | * | ||
73 | * More could be done here to set up the registers as if a CPU reset had | ||
74 | * occurred; hopefully real BIOSs don't assume much. This is not the | ||
75 | * actual BIOS entry point, anyway (that is at 0xfffffff0). | ||
76 | * | ||
77 | * Most of this work is probably excessive, but it is what is tested. | ||
78 | */ | ||
79 | .code16 | ||
80 | 1: | ||
81 | xorl %ecx, %ecx | ||
82 | movl %cr0, %eax | ||
83 | andl $0x00000011, %eax | ||
84 | orl $0x60000000, %eax | ||
85 | movl %eax, %cr0 | ||
86 | movl %ecx, %cr3 | ||
87 | movl %cr0, %edx | ||
88 | andl $0x60000000, %edx /* If no cache bits -> no wbinvd */ | ||
89 | jz 2f | ||
90 | wbinvd | ||
91 | 2: | ||
92 | andb $0x10, %al | ||
93 | movl %eax, %cr0 | ||
94 | .byte 0xea /* ljmpw */ | ||
95 | 101: .word 0 /* Offset */ | ||
96 | 102: .word 0 /* Segment */ | ||
97 | |||
98 | bios: | ||
99 | ljmpw $0xf000, $0xfff0 | ||
100 | |||
101 | apm: | ||
102 | movw $0x1000, %ax | ||
103 | movw %ax, %ss | ||
104 | movw $0xf000, %sp | ||
105 | movw $0x5307, %ax | ||
106 | movw $0x0001, %bx | ||
107 | movw $0x0003, %cx | ||
108 | int $0x15 | ||
109 | |||
110 | END(machine_real_restart_asm) | ||
111 | |||
112 | .balign 16 | ||
113 | /* These must match <asm/reboot.h */ | ||
114 | dispatch_table: | ||
115 | .word bios - r_base | ||
116 | .word apm - r_base | ||
117 | END(dispatch_table) | ||
118 | |||
119 | .balign 16 | ||
120 | machine_real_restart_idt: | ||
121 | .word 0xffff /* Length - real mode default value */ | ||
122 | .long 0 /* Base - real mode default value */ | ||
123 | END(machine_real_restart_idt) | ||
124 | |||
125 | .balign 16 | ||
126 | ENTRY(machine_real_restart_gdt) | ||
127 | .quad 0 /* Self-pointer, filled in by PM code */ | ||
128 | .quad 0 /* 16-bit code segment, filled in by PM code */ | ||
129 | /* | ||
130 | * 16-bit data segment with the selector value 16 = 0x10 and | ||
131 | * base value 0x100; since this is consistent with real mode | ||
132 | * semantics we don't have to reload the segments once CR0.PE = 0. | ||
133 | */ | ||
134 | .quad GDT_ENTRY(0x0093, 0x100, 0xffff) | ||
135 | END(machine_real_restart_gdt) | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 366c688d619e..16be6dc14db1 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <asm/pci-direct.h> | 49 | #include <asm/pci-direct.h> |
50 | #include <linux/init_ohci1394_dma.h> | 50 | #include <linux/init_ohci1394_dma.h> |
51 | #include <linux/kvm_para.h> | 51 | #include <linux/kvm_para.h> |
52 | #include <linux/dma-contiguous.h> | ||
52 | 53 | ||
53 | #include <linux/errno.h> | 54 | #include <linux/errno.h> |
54 | #include <linux/kernel.h> | 55 | #include <linux/kernel.h> |
@@ -72,7 +73,7 @@ | |||
72 | 73 | ||
73 | #include <asm/mtrr.h> | 74 | #include <asm/mtrr.h> |
74 | #include <asm/apic.h> | 75 | #include <asm/apic.h> |
75 | #include <asm/trampoline.h> | 76 | #include <asm/realmode.h> |
76 | #include <asm/e820.h> | 77 | #include <asm/e820.h> |
77 | #include <asm/mpspec.h> | 78 | #include <asm/mpspec.h> |
78 | #include <asm/setup.h> | 79 | #include <asm/setup.h> |
@@ -333,8 +334,8 @@ static void __init relocate_initrd(void) | |||
333 | memblock_reserve(ramdisk_here, area_size); | 334 | memblock_reserve(ramdisk_here, area_size); |
334 | initrd_start = ramdisk_here + PAGE_OFFSET; | 335 | initrd_start = ramdisk_here + PAGE_OFFSET; |
335 | initrd_end = initrd_start + ramdisk_size; | 336 | initrd_end = initrd_start + ramdisk_size; |
336 | printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n", | 337 | printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n", |
337 | ramdisk_here, ramdisk_here + ramdisk_size); | 338 | ramdisk_here, ramdisk_here + ramdisk_size - 1); |
338 | 339 | ||
339 | q = (char *)initrd_start; | 340 | q = (char *)initrd_start; |
340 | 341 | ||
@@ -365,8 +366,8 @@ static void __init relocate_initrd(void) | |||
365 | /* high pages is not converted by early_res_to_bootmem */ | 366 | /* high pages is not converted by early_res_to_bootmem */ |
366 | ramdisk_image = boot_params.hdr.ramdisk_image; | 367 | ramdisk_image = boot_params.hdr.ramdisk_image; |
367 | ramdisk_size = boot_params.hdr.ramdisk_size; | 368 | ramdisk_size = boot_params.hdr.ramdisk_size; |
368 | printk(KERN_INFO "Move RAMDISK from %016llx - %016llx to" | 369 | printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to" |
369 | " %08llx - %08llx\n", | 370 | " [mem %#010llx-%#010llx]\n", |
370 | ramdisk_image, ramdisk_image + ramdisk_size - 1, | 371 | ramdisk_image, ramdisk_image + ramdisk_size - 1, |
371 | ramdisk_here, ramdisk_here + ramdisk_size - 1); | 372 | ramdisk_here, ramdisk_here + ramdisk_size - 1); |
372 | } | 373 | } |
@@ -391,8 +392,8 @@ static void __init reserve_initrd(void) | |||
391 | ramdisk_size, end_of_lowmem>>1); | 392 | ramdisk_size, end_of_lowmem>>1); |
392 | } | 393 | } |
393 | 394 | ||
394 | printk(KERN_INFO "RAMDISK: %08llx - %08llx\n", ramdisk_image, | 395 | printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image, |
395 | ramdisk_end); | 396 | ramdisk_end - 1); |
396 | 397 | ||
397 | 398 | ||
398 | if (ramdisk_end <= end_of_lowmem) { | 399 | if (ramdisk_end <= end_of_lowmem) { |
@@ -905,10 +906,10 @@ void __init setup_arch(char **cmdline_p) | |||
905 | setup_bios_corruption_check(); | 906 | setup_bios_corruption_check(); |
906 | #endif | 907 | #endif |
907 | 908 | ||
908 | printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n", | 909 | printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n", |
909 | max_pfn_mapped<<PAGE_SHIFT); | 910 | (max_pfn_mapped<<PAGE_SHIFT) - 1); |
910 | 911 | ||
911 | setup_trampolines(); | 912 | setup_real_mode(); |
912 | 913 | ||
913 | init_gbpages(); | 914 | init_gbpages(); |
914 | 915 | ||
@@ -925,6 +926,7 @@ void __init setup_arch(char **cmdline_p) | |||
925 | } | 926 | } |
926 | #endif | 927 | #endif |
927 | memblock.current_limit = get_max_mapped(); | 928 | memblock.current_limit = get_max_mapped(); |
929 | dma_contiguous_reserve(0); | ||
928 | 930 | ||
929 | /* | 931 | /* |
930 | * NOTE: On x86-32, only from this point on, fixmaps are ready for use. | 932 | * NOTE: On x86-32, only from this point on, fixmaps are ready for use. |
@@ -966,6 +968,8 @@ void __init setup_arch(char **cmdline_p) | |||
966 | if (boot_cpu_data.cpuid_level >= 0) { | 968 | if (boot_cpu_data.cpuid_level >= 0) { |
967 | /* A CPU has %cr4 if and only if it has CPUID */ | 969 | /* A CPU has %cr4 if and only if it has CPUID */ |
968 | mmu_cr4_features = read_cr4(); | 970 | mmu_cr4_features = read_cr4(); |
971 | if (trampoline_cr4_features) | ||
972 | *trampoline_cr4_features = mmu_cr4_features; | ||
969 | } | 973 | } |
970 | 974 | ||
971 | #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 */ |
77 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; | 79 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; |
78 | 80 | ||
@@ -660,8 +662,12 @@ static void __cpuinit announce_cpu(int cpu, int apicid) | |||
660 | */ | 662 | */ |
661 | static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | 663 | static 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. */ |
50 | struct tboot *tboot __read_mostly; | 50 | struct 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 | |||
8 | unsigned char *x86_trampoline_base; | ||
9 | |||
10 | void __init setup_trampolines(void) | ||
11 | { | ||
12 | phys_addr_t mem; | ||
13 | size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start); | ||
14 | |||
15 | /* Has to be in very low memory so we can execute real-mode AP code. */ | ||
16 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); | ||
17 | if (!mem) | ||
18 | panic("Cannot allocate trampoline\n"); | ||
19 | |||
20 | x86_trampoline_base = __va(mem); | ||
21 | memblock_reserve(mem, size); | ||
22 | |||
23 | printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", | ||
24 | x86_trampoline_base, (unsigned long long)mem, size); | ||
25 | |||
26 | memcpy(x86_trampoline_base, x86_trampoline_start, size); | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * setup_trampolines() gets called very early, to guarantee the | ||
31 | * availability of low memory. This is before the proper kernel page | ||
32 | * tables are set up, so we cannot set page permissions in that | ||
33 | * function. Thus, we use an arch_initcall instead. | ||
34 | */ | ||
35 | static int __init configure_trampolines(void) | ||
36 | { | ||
37 | size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start); | ||
38 | |||
39 | set_memory_x((unsigned long)x86_trampoline_base, size >> PAGE_SHIFT); | ||
40 | return 0; | ||
41 | } | ||
42 | arch_initcall(configure_trampolines); | ||
diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S deleted file mode 100644 index 451c0a7ef7fd..000000000000 --- a/arch/x86/kernel/trampoline_32.S +++ /dev/null | |||
@@ -1,83 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Trampoline.S Derived from Setup.S by Linus Torvalds | ||
4 | * | ||
5 | * 4 Jan 1997 Michael Chastain: changed to gnu as. | ||
6 | * | ||
7 | * This is only used for booting secondary CPUs in SMP machine | ||
8 | * | ||
9 | * Entry: CS:IP point to the start of our code, we are | ||
10 | * in real mode with no stack, but the rest of the | ||
11 | * trampoline page to make our stack and everything else | ||
12 | * is a mystery. | ||
13 | * | ||
14 | * We jump into arch/x86/kernel/head_32.S. | ||
15 | * | ||
16 | * On entry to trampoline_data, the processor is in real mode | ||
17 | * with 16-bit addressing and 16-bit data. CS has some value | ||
18 | * and IP is zero. Thus, data addresses need to be absolute | ||
19 | * (no relocation) and are taken with regard to r_base. | ||
20 | * | ||
21 | * If you work on this file, check the object module with | ||
22 | * objdump --reloc to make sure there are no relocation | ||
23 | * entries except for: | ||
24 | * | ||
25 | * TYPE VALUE | ||
26 | * R_386_32 startup_32_smp | ||
27 | * R_386_32 boot_gdt | ||
28 | */ | ||
29 | |||
30 | #include <linux/linkage.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <asm/segment.h> | ||
33 | #include <asm/page_types.h> | ||
34 | |||
35 | #ifdef CONFIG_SMP | ||
36 | |||
37 | .section ".x86_trampoline","a" | ||
38 | .balign PAGE_SIZE | ||
39 | .code16 | ||
40 | |||
41 | ENTRY(trampoline_data) | ||
42 | r_base = . | ||
43 | wbinvd # Needed for NUMA-Q should be harmless for others | ||
44 | mov %cs, %ax # Code and data in the same place | ||
45 | mov %ax, %ds | ||
46 | |||
47 | cli # We should be safe anyway | ||
48 | |||
49 | movl $0xA5A5A5A5, trampoline_status - r_base | ||
50 | # write marker for master knows we're running | ||
51 | |||
52 | /* GDT tables in non default location kernel can be beyond 16MB and | ||
53 | * lgdt will not be able to load the address as in real mode default | ||
54 | * operand size is 16bit. Use lgdtl instead to force operand size | ||
55 | * to 32 bit. | ||
56 | */ | ||
57 | |||
58 | lidtl boot_idt_descr - r_base # load idt with 0, 0 | ||
59 | lgdtl boot_gdt_descr - r_base # load gdt with whatever is appropriate | ||
60 | |||
61 | xor %ax, %ax | ||
62 | inc %ax # protected mode (PE) bit | ||
63 | lmsw %ax # into protected mode | ||
64 | # flush prefetch and jump to startup_32_smp in arch/i386/kernel/head.S | ||
65 | ljmpl $__BOOT_CS, $(startup_32_smp-__PAGE_OFFSET) | ||
66 | |||
67 | # These need to be in the same 64K segment as the above; | ||
68 | # hence we don't use the boot_gdt_descr defined in head.S | ||
69 | boot_gdt_descr: | ||
70 | .word __BOOT_DS + 7 # gdt limit | ||
71 | .long boot_gdt - __PAGE_OFFSET # gdt base | ||
72 | |||
73 | boot_idt_descr: | ||
74 | .word 0 # idt limit = 0 | ||
75 | .long 0 # idt base = 0L | ||
76 | |||
77 | ENTRY(trampoline_status) | ||
78 | .long 0 | ||
79 | |||
80 | .globl trampoline_end | ||
81 | trampoline_end: | ||
82 | |||
83 | #endif /* CONFIG_SMP */ | ||
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S deleted file mode 100644 index 09ff51799e96..000000000000 --- a/arch/x86/kernel/trampoline_64.S +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Trampoline.S Derived from Setup.S by Linus Torvalds | ||
4 | * | ||
5 | * 4 Jan 1997 Michael Chastain: changed to gnu as. | ||
6 | * 15 Sept 2005 Eric Biederman: 64bit PIC support | ||
7 | * | ||
8 | * Entry: CS:IP point to the start of our code, we are | ||
9 | * in real mode with no stack, but the rest of the | ||
10 | * trampoline page to make our stack and everything else | ||
11 | * is a mystery. | ||
12 | * | ||
13 | * On entry to trampoline_data, the processor is in real mode | ||
14 | * with 16-bit addressing and 16-bit data. CS has some value | ||
15 | * and IP is zero. Thus, data addresses need to be absolute | ||
16 | * (no relocation) and are taken with regard to r_base. | ||
17 | * | ||
18 | * With the addition of trampoline_level4_pgt this code can | ||
19 | * now enter a 64bit kernel that lives at arbitrary 64bit | ||
20 | * physical addresses. | ||
21 | * | ||
22 | * If you work on this file, check the object module with objdump | ||
23 | * --full-contents --reloc to make sure there are no relocation | ||
24 | * entries. | ||
25 | */ | ||
26 | |||
27 | #include <linux/linkage.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <asm/pgtable_types.h> | ||
30 | #include <asm/page_types.h> | ||
31 | #include <asm/msr.h> | ||
32 | #include <asm/segment.h> | ||
33 | #include <asm/processor-flags.h> | ||
34 | |||
35 | .section ".x86_trampoline","a" | ||
36 | .balign PAGE_SIZE | ||
37 | .code16 | ||
38 | |||
39 | ENTRY(trampoline_data) | ||
40 | r_base = . | ||
41 | cli # We should be safe anyway | ||
42 | wbinvd | ||
43 | mov %cs, %ax # Code and data in the same place | ||
44 | mov %ax, %ds | ||
45 | mov %ax, %es | ||
46 | mov %ax, %ss | ||
47 | |||
48 | |||
49 | movl $0xA5A5A5A5, trampoline_status - r_base | ||
50 | # write marker for master knows we're running | ||
51 | |||
52 | # Setup stack | ||
53 | movw $(trampoline_stack_end - r_base), %sp | ||
54 | |||
55 | call verify_cpu # Verify the cpu supports long mode | ||
56 | testl %eax, %eax # Check for return code | ||
57 | jnz no_longmode | ||
58 | |||
59 | mov %cs, %ax | ||
60 | movzx %ax, %esi # Find the 32bit trampoline location | ||
61 | shll $4, %esi | ||
62 | |||
63 | # Fixup the absolute vectors | ||
64 | leal (startup_32 - r_base)(%esi), %eax | ||
65 | movl %eax, startup_32_vector - r_base | ||
66 | leal (startup_64 - r_base)(%esi), %eax | ||
67 | movl %eax, startup_64_vector - r_base | ||
68 | leal (tgdt - r_base)(%esi), %eax | ||
69 | movl %eax, (tgdt + 2 - r_base) | ||
70 | |||
71 | /* | ||
72 | * GDT tables in non default location kernel can be beyond 16MB and | ||
73 | * lgdt will not be able to load the address as in real mode default | ||
74 | * operand size is 16bit. Use lgdtl instead to force operand size | ||
75 | * to 32 bit. | ||
76 | */ | ||
77 | |||
78 | lidtl tidt - r_base # load idt with 0, 0 | ||
79 | lgdtl tgdt - r_base # load gdt with whatever is appropriate | ||
80 | |||
81 | mov $X86_CR0_PE, %ax # protected mode (PE) bit | ||
82 | lmsw %ax # into protected mode | ||
83 | |||
84 | # flush prefetch and jump to startup_32 | ||
85 | ljmpl *(startup_32_vector - r_base) | ||
86 | |||
87 | .code32 | ||
88 | .balign 4 | ||
89 | startup_32: | ||
90 | movl $__KERNEL_DS, %eax # Initialize the %ds segment register | ||
91 | movl %eax, %ds | ||
92 | |||
93 | movl $X86_CR4_PAE, %eax | ||
94 | movl %eax, %cr4 # Enable PAE mode | ||
95 | |||
96 | # Setup trampoline 4 level pagetables | ||
97 | leal (trampoline_level4_pgt - r_base)(%esi), %eax | ||
98 | movl %eax, %cr3 | ||
99 | |||
100 | movl $MSR_EFER, %ecx | ||
101 | movl $(1 << _EFER_LME), %eax # Enable Long Mode | ||
102 | xorl %edx, %edx | ||
103 | wrmsr | ||
104 | |||
105 | # Enable paging and in turn activate Long Mode | ||
106 | # Enable protected mode | ||
107 | movl $(X86_CR0_PG | X86_CR0_PE), %eax | ||
108 | movl %eax, %cr0 | ||
109 | |||
110 | /* | ||
111 | * At this point we're in long mode but in 32bit compatibility mode | ||
112 | * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn | ||
113 | * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use | ||
114 | * the new gdt/idt that has __KERNEL_CS with CS.L = 1. | ||
115 | */ | ||
116 | ljmp *(startup_64_vector - r_base)(%esi) | ||
117 | |||
118 | .code64 | ||
119 | .balign 4 | ||
120 | startup_64: | ||
121 | # Now jump into the kernel using virtual addresses | ||
122 | movq $secondary_startup_64, %rax | ||
123 | jmp *%rax | ||
124 | |||
125 | .code16 | ||
126 | no_longmode: | ||
127 | hlt | ||
128 | jmp no_longmode | ||
129 | #include "verify_cpu.S" | ||
130 | |||
131 | .balign 4 | ||
132 | # Careful these need to be in the same 64K segment as the above; | ||
133 | tidt: | ||
134 | .word 0 # idt limit = 0 | ||
135 | .word 0, 0 # idt base = 0L | ||
136 | |||
137 | # Duplicate the global descriptor table | ||
138 | # so the kernel can live anywhere | ||
139 | .balign 4 | ||
140 | tgdt: | ||
141 | .short tgdt_end - tgdt # gdt limit | ||
142 | .long tgdt - r_base | ||
143 | .short 0 | ||
144 | .quad 0x00cf9b000000ffff # __KERNEL32_CS | ||
145 | .quad 0x00af9b000000ffff # __KERNEL_CS | ||
146 | .quad 0x00cf93000000ffff # __KERNEL_DS | ||
147 | tgdt_end: | ||
148 | |||
149 | .balign 4 | ||
150 | startup_32_vector: | ||
151 | .long startup_32 - r_base | ||
152 | .word __KERNEL32_CS, 0 | ||
153 | |||
154 | .balign 4 | ||
155 | startup_64_vector: | ||
156 | .long startup_64 - r_base | ||
157 | .word __KERNEL_CS, 0 | ||
158 | |||
159 | .balign 4 | ||
160 | ENTRY(trampoline_status) | ||
161 | .long 0 | ||
162 | |||
163 | trampoline_stack: | ||
164 | .org 0x1000 | ||
165 | trampoline_stack_end: | ||
166 | ENTRY(trampoline_level4_pgt) | ||
167 | .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE | ||
168 | .fill 510,8,0 | ||
169 | .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE | ||
170 | |||
171 | ENTRY(trampoline_end) | ||
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 0f703f10901a..22a1530146a8 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S | |||
@@ -197,18 +197,6 @@ SECTIONS | |||
197 | 197 | ||
198 | INIT_DATA_SECTION(16) | 198 | INIT_DATA_SECTION(16) |
199 | 199 | ||
200 | /* | ||
201 | * Code and data for a variety of lowlevel trampolines, to be | ||
202 | * copied into base memory (< 1 MiB) during initialization. | ||
203 | * Since it is copied early, the main copy can be discarded | ||
204 | * afterwards. | ||
205 | */ | ||
206 | .x86_trampoline : AT(ADDR(.x86_trampoline) - LOAD_OFFSET) { | ||
207 | x86_trampoline_start = .; | ||
208 | *(.x86_trampoline) | ||
209 | x86_trampoline_end = .; | ||
210 | } | ||
211 | |||
212 | .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { | 200 | .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { |
213 | __x86_cpu_dev_start = .; | 201 | __x86_cpu_dev_start = .; |
214 | *(.x86_cpu_dev.init) | 202 | *(.x86_cpu_dev.init) |