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__));
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);
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);
*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
}
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;
#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)
*
* 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>
.code16
.balign PAGE_SIZE
-ENTRY(trampoline_data)
+ENTRY(trampoline_start)
wbinvd # Needed for NUMA-Q should be harmless for others
LJMPW_RM(1f)
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
* 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
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"
* 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.
.balign PAGE_SIZE
.code16
-ENTRY(trampoline_data)
+ENTRY(trampoline_start)
cli # We should be safe anyway
wbinvd
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
.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
.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"
--- /dev/null
+ .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
ljmpl $__KERNEL_CS, $pa_startup_32
/* -> jmp *%eax in trampoline_32.S */
#else
- jmp trampoline_data
+ jmp trampoline_start
#endif
bogus_real_magic: