summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/realmode.h32
-rw-r--r--arch/x86/kernel/realmode.c27
-rw-r--r--arch/x86/kernel/smpboot.c2
-rw-r--r--arch/x86/realmode/rm/header.S35
-rw-r--r--arch/x86/realmode/rm/trampoline_32.S36
-rw-r--r--arch/x86/realmode/rm/trampoline_64.S18
-rw-r--r--arch/x86/realmode/rm/trampoline_common.S23
-rw-r--r--arch/x86/realmode/rm/wakeup_asm.S2
8 files changed, 87 insertions, 88 deletions
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index d3ae49f4c3ef..1421eed1c8e8 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -8,25 +8,33 @@
struct real_mode_header {
u32 text_start;
u32 ro_end;
- /* reboot */
-#ifdef CONFIG_X86_32
- u32 machine_real_restart_asm;
-#endif
/* SMP trampoline */
- u32 trampoline_data;
+ u32 trampoline_start;
u32 trampoline_status;
-#ifdef CONFIG_X86_32
- u32 startup_32_smp;
- u32 boot_gdt;
-#else
- u32 startup_64_smp;
- u32 level3_ident_pgt;
- u32 level3_kernel_pgt;
+ u32 trampoline_header;
+#ifdef CONFIG_X86_64
+ u32 trampoline_pgd;
#endif
+ /* ACPI S3 wakeup */
#ifdef CONFIG_ACPI_SLEEP
u32 wakeup_start;
u32 wakeup_header;
#endif
+ /* APM/BIOS reboot */
+#ifdef CONFIG_X86_32
+ u32 machine_real_restart_asm;
+#endif
+} __attribute__((__packed__));
+
+/* This must match data at trampoline_32/64.S */
+struct trampoline_header {
+#ifdef CONFIG_X86_32
+ u32 start;
+ u16 gdt_limit;
+ u32 gdt_base;
+#else
+ u64 start;
+#endif
} __attribute__((__packed__));
extern struct real_mode_header *real_mode_header;
diff --git a/arch/x86/kernel/realmode.c b/arch/x86/kernel/realmode.c
index 632c810ec8ea..712fba8fd774 100644
--- a/arch/x86/kernel/realmode.c
+++ b/arch/x86/kernel/realmode.c
@@ -17,8 +17,11 @@ void __init setup_real_mode(void)
u16 *seg;
int i;
unsigned char *base;
-
+ struct trampoline_header *trampoline_header;
size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
+#ifdef CONFIG_X86_64
+ u64 *trampoline_pgd;
+#endif
/* Has to be in very low memory so we can execute real-mode AP code. */
mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
@@ -28,7 +31,6 @@ void __init setup_real_mode(void)
base = __va(mem);
memblock_reserve(mem, size);
real_mode_header = (struct real_mode_header *) base;
-
printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
base, (unsigned long long)mem, size);
@@ -53,18 +55,19 @@ void __init setup_real_mode(void)
*ptr += __pa(base);
}
+ /* Must be perfomed *after* relocation. */
+ trampoline_header = (struct trampoline_header *)
+ __va(real_mode_header->trampoline_header);
+
#ifdef CONFIG_X86_32
- *((u32 *)__va(real_mode_header->startup_32_smp)) = __pa(startup_32_smp);
- *((u32 *)__va(real_mode_header->boot_gdt)) = __pa(boot_gdt);
+ trampoline_header->start = __pa(startup_32_smp);
+ trampoline_header->gdt_limit = __BOOT_DS + 7;
+ trampoline_header->gdt_base = __pa(boot_gdt);
#else
- *((u64 *) __va(real_mode_header->startup_64_smp)) =
- (u64)secondary_startup_64;
-
- *((u64 *) __va(real_mode_header->level3_ident_pgt)) =
- __pa(level3_ident_pgt) + _KERNPG_TABLE;
-
- *((u64 *) __va(real_mode_header->level3_kernel_pgt)) =
- __pa(level3_kernel_pgt) + _KERNPG_TABLE;
+ trampoline_header->start = (u64) secondary_startup_64;
+ trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
+ trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE;
+ trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE;
#endif
}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index b8c0661e2341..757c4b1d0a02 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -667,7 +667,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
volatile u32 *trampoline_status =
(volatile u32 *) __va(real_mode_header->trampoline_status);
/* start_ip had better be page-aligned! */
- unsigned long start_ip = real_mode_header->trampoline_data;
+ unsigned long start_ip = real_mode_header->trampoline_start;
unsigned long boot_error = 0;
int timeout;
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
index c83005c4d455..b4c32632bf16 100644
--- a/arch/x86/realmode/rm/header.S
+++ b/arch/x86/realmode/rm/header.S
@@ -7,28 +7,25 @@
#include <linux/linkage.h>
#include <asm/page_types.h>
- .section ".header", "a"
+ .section ".header", "a"
GLOBAL(real_mode_header)
- .long pa_text_start
- .long pa_ro_end
-#ifdef CONFIG_X86_32
- .long pa_machine_real_restart_asm
-#endif
- /* SMP trampoline */
- .long pa_trampoline_data
- .long pa_trampoline_status
-#ifdef CONFIG_X86_32
- .long pa_startup_32_smp
- .long pa_boot_gdt
-#else
- .long pa_startup_64_smp
- .long pa_level3_ident_pgt
- .long pa_level3_kernel_pgt
+ .long pa_text_start
+ .long pa_ro_end
+ /* SMP trampoline */
+ .long pa_trampoline_start
+ .long pa_trampoline_status
+ .long pa_trampoline_header
+#ifdef CONFIG_X86_64
+ .long pa_trampoline_pgd;
#endif
- /* ACPI sleep */
+ /* ACPI S3 wakeup */
#ifdef CONFIG_ACPI_SLEEP
- .long pa_wakeup_start
- .long pa_wakeup_header
+ .long pa_wakeup_start
+ .long pa_wakeup_header
+#endif
+ /* APM/BIOS reboot */
+#ifdef CONFIG_X86_32
+ .long pa_machine_real_restart_asm
#endif
END(real_mode_header)
diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S
index 1ecdbb59191b..6fc064b4d2b9 100644
--- a/arch/x86/realmode/rm/trampoline_32.S
+++ b/arch/x86/realmode/rm/trampoline_32.S
@@ -13,16 +13,10 @@
*
* We jump into arch/x86/kernel/head_32.S.
*
- * On entry to trampoline_data, the processor is in real mode
+ * On entry to trampoline_start, the processor is in real mode
* with 16-bit addressing and 16-bit data. CS has some value
* and IP is zero. Thus, we load CS to the physical segment
* of the real mode code before doing anything further.
- *
- * The structure real_mode_header includes entries that need
- * to be set up before executing this code:
- *
- * startup_32_smp
- * boot_gdt
*/
#include <linux/linkage.h>
@@ -35,7 +29,7 @@
.code16
.balign PAGE_SIZE
-ENTRY(trampoline_data)
+ENTRY(trampoline_start)
wbinvd # Needed for NUMA-Q should be harmless for others
LJMPW_RM(1f)
@@ -45,7 +39,7 @@ ENTRY(trampoline_data)
cli # We should be safe anyway
- movl startup_32_smp, %eax # where we need to go
+ movl tr_start, %eax # where we need to go
movl $0xA5A5A5A5, trampoline_status
# write marker for master knows we're running
@@ -56,8 +50,8 @@ ENTRY(trampoline_data)
* operand size is 16bit. Use lgdtl instead to force operand size
* to 32 bit.
*/
- lidtl boot_idt_descr # load idt with 0, 0
- lgdtl boot_gdt_descr # load gdt with whatever is appropriate
+ lidtl tr_idt # load idt with 0, 0
+ lgdtl tr_gdt # load gdt with whatever is appropriate
movw $1, %dx # protected mode (PE) bit
lmsw %dx # into protected mode
@@ -69,22 +63,4 @@ ENTRY(trampoline_data)
ENTRY(startup_32) # note: also used from wakeup_asm.S
jmp *%eax
- .section ".rodata","a"
-
- .balign 4
-boot_idt_descr:
- .word 0 # idt limit = 0
- .long 0 # idt base = 0L
-
- .data
-
-boot_gdt_descr:
- .word __BOOT_DS + 7 # gdt limit
-GLOBAL(boot_gdt)
- .long 0 # gdt base
-
- .bss
-
- .balign 4
-GLOBAL(trampoline_status) .space 4
-GLOBAL(startup_32_smp) .space 4
+#include "trampoline_common.S"
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index f71ea0800d3d..3f7293239365 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -10,7 +10,7 @@
* trampoline page to make our stack and everything else
* is a mystery.
*
- * On entry to trampoline_data, the processor is in real mode
+ * On entry to trampoline_start, the processor is in real mode
* with 16-bit addressing and 16-bit data. CS has some value
* and IP is zero. Thus, data addresses need to be absolute
* (no relocation) and are taken with regard to r_base.
@@ -37,7 +37,7 @@
.balign PAGE_SIZE
.code16
-ENTRY(trampoline_data)
+ENTRY(trampoline_start)
cli # We should be safe anyway
wbinvd
@@ -97,7 +97,7 @@ ENTRY(startup_32)
movl %eax, %cr4 # Enable PAE mode
# Setup trampoline 4 level pagetables
- movl $pa_level3_ident_pgt, %eax
+ movl $pa_trampoline_pgd, %eax
movl %eax, %cr3
movl $MSR_EFER, %ecx
@@ -122,7 +122,7 @@ ENTRY(startup_32)
.balign 4
ENTRY(startup_64)
# Now jump into the kernel using virtual addresses
- jmpq *startup_64_smp(%rip)
+ jmpq *tr_start(%rip)
.section ".rodata","a"
.balign 16
@@ -143,12 +143,4 @@ tgdt:
.quad 0x00cf93000000ffff # __KERNEL_DS
tgdt_end:
- .bss
-
- .balign PAGE_SIZE
-GLOBAL(level3_ident_pgt) .space 511*8
-GLOBAL(level3_kernel_pgt) .space 8
-
- .balign 8
-GLOBAL(startup_64_smp) .space 8
-GLOBAL(trampoline_status) .space 4
+#include "trampoline_common.S"
diff --git a/arch/x86/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S
new file mode 100644
index 000000000000..c3f951c468c5
--- /dev/null
+++ b/arch/x86/realmode/rm/trampoline_common.S
@@ -0,0 +1,23 @@
+ .section ".rodata","a"
+
+ .balign 4
+tr_idt: .fill 1, 6, 0
+
+ .bss
+
+ .balign 4
+GLOBAL(trampoline_status) .space 4
+
+GLOBAL(trampoline_header)
+#ifdef CONFIG_X86_32
+ tr_start: .space 4
+ tr_gdt: .space 6
+#else
+ tr_start: .space 8
+#endif
+END(trampoline_header)
+
+#ifdef CONFIG_X86_64
+ .balign PAGE_SIZE
+GLOBAL(trampoline_pgd) .space PAGE_SIZE
+#endif
diff --git a/arch/x86/realmode/rm/wakeup_asm.S b/arch/x86/realmode/rm/wakeup_asm.S
index 8a57c5a05fbc..46108f05e04e 100644
--- a/arch/x86/realmode/rm/wakeup_asm.S
+++ b/arch/x86/realmode/rm/wakeup_asm.S
@@ -132,7 +132,7 @@ ENTRY(wakeup_start)
ljmpl $__KERNEL_CS, $pa_startup_32
/* -> jmp *%eax in trampoline_32.S */
#else
- jmp trampoline_data
+ jmp trampoline_start
#endif
bogus_real_magic: