Commit f37240f1 authored by Jarkko Sakkinen's avatar Jarkko Sakkinen Committed by H. Peter Anvin
Browse files

x86, realmode: header for trampoline code



Added header for trampoline code that can be used to supply
input data to it. This makes interface between real mode code
and kernel cleaner and simpler. Replaced two confusing pointers
to level4 pgt in trampoline_64.S with a single pointer to the
beginning of the page table.

Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@intel.com>
Link: http://lkml.kernel.org/r/1336501366-28617-21-git-send-email-jarkko.sakkinen@intel.com


Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent c4845474
Loading
Loading
Loading
Loading
+20 −12
Original line number Diff line number Diff line
@@ -8,24 +8,32 @@
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__));

+15 −12
Original line number Diff line number Diff line
@@ -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
}

+1 −1
Original line number Diff line number Diff line
@@ -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;
+16 −19
Original line number Diff line number Diff line
@@ -12,23 +12,20 @@
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_start
	.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_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
#endif
	/* APM/BIOS reboot */
#ifdef CONFIG_X86_32
	.long	pa_machine_real_restart_asm
#endif
END(real_mode_header)
+6 −30
Original line number Diff line number Diff line
@@ -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"
Loading