diff options
Diffstat (limited to 'arch/x86/realmode/init.c')
| -rw-r--r-- | arch/x86/realmode/init.c | 47 | 
1 files changed, 35 insertions, 12 deletions
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index 705e3fffb4a1..5db706f14111 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c @@ -1,9 +1,11 @@  #include <linux/io.h> +#include <linux/slab.h>  #include <linux/memblock.h>  #include <asm/cacheflush.h>  #include <asm/pgtable.h>  #include <asm/realmode.h> +#include <asm/tlbflush.h>  struct real_mode_header *real_mode_header;  u32 *trampoline_cr4_features; @@ -11,25 +13,37 @@ u32 *trampoline_cr4_features;  /* Hold the pgd entry used on booting additional CPUs */  pgd_t trampoline_pgd_entry; +void __init set_real_mode_mem(phys_addr_t mem, size_t size) +{ +	void *base = __va(mem); + +	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 reserve_real_mode(void)  {  	phys_addr_t mem; -	unsigned char *base; -	size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); +	size_t size = real_mode_size_needed(); + +	if (!size) +		return; + +	WARN_ON(slab_is_available());  	/* 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"); +	if (!mem) { +		pr_info("No sub-1M memory is available for the trampoline\n"); +		return; +	} -	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); +	set_real_mode_mem(mem, size);  } -void __init setup_real_mode(void) +static void __init setup_real_mode(void)  {  	u16 real_mode_seg;  	const u32 *rel; @@ -84,7 +98,7 @@ void __init setup_real_mode(void)  	trampoline_header->start = (u64) secondary_startup_64;  	trampoline_cr4_features = &trampoline_header->cr4; -	*trampoline_cr4_features = __read_cr4(); +	*trampoline_cr4_features = mmu_cr4_features;  	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);  	trampoline_pgd[0] = trampoline_pgd_entry.pgd; @@ -100,7 +114,7 @@ void __init setup_real_mode(void)   * 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) +static void __init set_real_mode_permissions(void)  {  	unsigned char *base = (unsigned char *) real_mode_header;  	size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); @@ -119,7 +133,16 @@ static int __init set_real_mode_permissions(void)  	set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);  	set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);  	set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT); +} + +static int __init init_real_mode(void) +{ +	if (!real_mode_header) +		panic("Real mode trampoline was not allocated"); + +	setup_real_mode(); +	set_real_mode_permissions();  	return 0;  } -early_initcall(set_real_mode_permissions); +early_initcall(init_real_mode);  | 
