diff options
Diffstat (limited to 'arch/x86/realmode/init.c')
| -rw-r--r-- | arch/x86/realmode/init.c | 49 | 
1 files changed, 29 insertions, 20 deletions
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index cbca565af5b..a44f457e70a 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c @@ -8,9 +8,26 @@  struct real_mode_header *real_mode_header;  u32 *trampoline_cr4_features; -void __init setup_real_mode(void) +void __init reserve_real_mode(void)  {  	phys_addr_t mem; +	unsigned char *base; +	size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); + +	/* Has to be under 1M so we can execute real-mode AP code. */ +	mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); +	if (!mem) +		panic("Cannot allocate trampoline\n"); + +	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); +} + +void __init setup_real_mode(void) +{  	u16 real_mode_seg;  	u32 *rel;  	u32 count; @@ -25,16 +42,7 @@ void __init setup_real_mode(void)  	u64 efer;  #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); -	if (!mem) -		panic("Cannot allocate trampoline\n"); - -	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); +	base = (unsigned char *)real_mode_header;  	memcpy(base, real_mode_blob, size); @@ -62,9 +70,9 @@ void __init setup_real_mode(void)  		__va(real_mode_header->trampoline_header);  #ifdef CONFIG_X86_32 -	trampoline_header->start = __pa(startup_32_smp); +	trampoline_header->start = __pa_symbol(startup_32_smp);  	trampoline_header->gdt_limit = __BOOT_DS + 7; -	trampoline_header->gdt_base = __pa(boot_gdt); +	trampoline_header->gdt_base = __pa_symbol(boot_gdt);  #else  	/*  	 * Some AMD processors will #GP(0) if EFER.LMA is set in WRMSR @@ -78,16 +86,18 @@ void __init setup_real_mode(void)  	*trampoline_cr4_features = read_cr4();  	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; +	trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd; +	trampoline_pgd[511] = init_level4_pgt[511].pgd;  #endif  }  /* - * set_real_mode_permissions() gets called very early, to guarantee the - * availability of low memory.  This is before the proper kernel page + * reserve_real_mode() gets called very early, to guarantee the + * availability of low memory. This is before the proper kernel page   * tables are set up, so we cannot set page permissions in that - * function.  Thus, we use an arch_initcall instead. + * function. Also trampoline code will be executed by APs so we + * need to mark it executable at do_pre_smp_initcalls() at least, + * thus run it as a early_initcall().   */  static int __init set_real_mode_permissions(void)  { @@ -111,5 +121,4 @@ static int __init set_real_mode_permissions(void)  	return 0;  } - -arch_initcall(set_real_mode_permissions); +early_initcall(set_real_mode_permissions);  |