Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

x86, realmode: Move SMP trampoline to unified realmode code



Migrated SMP trampoline code to the real mode blob.
SMP trampoline code is not yet removed from
.x86_trampoline because it is needed by the wakeup
code.

[ hpa: always enable compiling startup_32_smp in head_32.S... it is
  only a few instructions which go into .init on UP builds, and it makes
  the rest of the code less #ifdef ugly. ]

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


Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 5a8c9aeb
Loading
Loading
Loading
Loading
+18 −0
Original line number Original line Diff line number Diff line
@@ -12,6 +12,17 @@ struct real_mode_header {
	/* reboot */
	/* reboot */
#ifdef CONFIG_X86_32
#ifdef CONFIG_X86_32
	u32	machine_real_restart_asm;
	u32	machine_real_restart_asm;
#endif
	/* SMP trampoline */
	u32	trampoline_data;
	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;
#endif
#endif
} __attribute__((__packed__));
} __attribute__((__packed__));


@@ -25,6 +36,13 @@ extern unsigned long initial_gs;
extern unsigned char real_mode_blob[];
extern unsigned char real_mode_blob[];
extern unsigned char real_mode_relocs[];
extern unsigned char real_mode_relocs[];


#ifdef CONFIG_X86_32
extern unsigned char startup_32_smp[];
extern unsigned char boot_gdt[];
#else
extern unsigned char secondary_startup_64[];
#endif

extern void __init setup_real_mode(void);
extern void __init setup_real_mode(void);


#endif /* _ARCH_X86_REALMODE_H */
#endif /* _ARCH_X86_REALMODE_H */
+1 −4
Original line number Original line Diff line number Diff line
@@ -273,10 +273,7 @@ num_subarch_entries = (. - subarch_entries) / 4
 * If cpu hotplug is not supported then this code can go in init section
 * If cpu hotplug is not supported then this code can go in init section
 * which will be freed later
 * which will be freed later
 */
 */

__CPUINIT
__CPUINIT

#ifdef CONFIG_SMP
ENTRY(startup_32_smp)
ENTRY(startup_32_smp)
	cld
	cld
	movl $(__BOOT_DS),%eax
	movl $(__BOOT_DS),%eax
@@ -287,7 +284,7 @@ ENTRY(startup_32_smp)
	movl pa(stack_start),%ecx
	movl pa(stack_start),%ecx
	movl %eax,%ss
	movl %eax,%ss
	leal -__PAGE_OFFSET(%ecx),%esp
	leal -__PAGE_OFFSET(%ecx),%esp
#endif /* CONFIG_SMP */

default_entry:
default_entry:


/*
/*
+0 −4
Original line number Original line Diff line number Diff line
@@ -136,10 +136,6 @@ ident_complete:
	/* Fixup phys_base */
	/* Fixup phys_base */
	addq	%rbp, phys_base(%rip)
	addq	%rbp, phys_base(%rip)


	/* Fixup trampoline */
	addq	%rbp, trampoline_level4_pgt + 0(%rip)
	addq	%rbp, trampoline_level4_pgt + (511*8)(%rip)

	/* Due to ENTRY(), sometimes the empty space gets filled with
	/* Due to ENTRY(), sometimes the empty space gets filled with
	 * zeros. Better take a jmp than relying on empty space being
	 * zeros. Better take a jmp than relying on empty space being
	 * filled with 0x90 (nop)
	 * filled with 0x90 (nop)
+14 −0
Original line number Original line Diff line number Diff line
@@ -58,6 +58,20 @@ void __init setup_real_mode(void)
	/* Copied header will contain relocated physical addresses. */
	/* Copied header will contain relocated physical addresses. */
	memcpy(&real_mode_header, real_mode_base,
	memcpy(&real_mode_header, real_mode_base,
	       sizeof(struct real_mode_header));
	       sizeof(struct real_mode_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);
#else
	*((u64 *) __va(real_mode_header.startup_64_smp)) =
		(u64) __pa(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;
#endif
}
}


/*
/*
+10 −8
Original line number Original line Diff line number Diff line
@@ -57,7 +57,7 @@
#include <asm/nmi.h>
#include <asm/nmi.h>
#include <asm/irq.h>
#include <asm/irq.h>
#include <asm/idle.h>
#include <asm/idle.h>
#include <asm/trampoline.h>
#include <asm/realmode.h>
#include <asm/cpu.h>
#include <asm/cpu.h>
#include <asm/numa.h>
#include <asm/numa.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
@@ -73,6 +73,8 @@
#include <asm/smpboot_hooks.h>
#include <asm/smpboot_hooks.h>
#include <asm/i8259.h>
#include <asm/i8259.h>


#include <asm/realmode.h>

/* State of each CPU */
/* State of each CPU */
DEFINE_PER_CPU(int, cpu_state) = { 0 };
DEFINE_PER_CPU(int, cpu_state) = { 0 };


@@ -662,8 +664,12 @@ static void __cpuinit announce_cpu(int cpu, int apicid)
 */
 */
static int __cpuinit do_boot_cpu(int apicid, int cpu)
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 boot_error = 0;
	unsigned long boot_error = 0;
	unsigned long start_ip;
	int timeout;
	int timeout;
	struct create_idle c_idle = {
	struct create_idle c_idle = {
		.cpu	= cpu,
		.cpu	= cpu,
@@ -713,9 +719,6 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
	initial_code = (unsigned long)start_secondary;
	initial_code = (unsigned long)start_secondary;
	stack_start  = c_idle.idle->thread.sp;
	stack_start  = c_idle.idle->thread.sp;


	/* start_ip had better be page-aligned! */
	start_ip = trampoline_address();

	/* So we see what's up */
	/* So we see what's up */
	announce_cpu(cpu, apicid);
	announce_cpu(cpu, apicid);


@@ -778,8 +781,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
			pr_debug("CPU%d: has booted.\n", cpu);
			pr_debug("CPU%d: has booted.\n", cpu);
		} else {
		} else {
			boot_error = 1;
			boot_error = 1;
			if (*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status)
			if (*trampoline_status == 0xA5A5A5A5)
			    == 0xA5A5A5A5)
				/* trampoline started but...? */
				/* trampoline started but...? */
				pr_err("CPU%d: Stuck ??\n", cpu);
				pr_err("CPU%d: Stuck ??\n", cpu);
			else
			else
@@ -805,7 +807,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
	}
	}


	/* mark "stuck" area as not stuck */
	/* mark "stuck" area as not stuck */
	*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status) = 0;
	*trampoline_status = 0;


	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
		/*
		/*
Loading