aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/realmode/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/realmode/init.c')
-rw-r--r--arch/x86/realmode/init.c47
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 @@
1#include <linux/io.h> 1#include <linux/io.h>
2#include <linux/slab.h>
2#include <linux/memblock.h> 3#include <linux/memblock.h>
3 4
4#include <asm/cacheflush.h> 5#include <asm/cacheflush.h>
5#include <asm/pgtable.h> 6#include <asm/pgtable.h>
6#include <asm/realmode.h> 7#include <asm/realmode.h>
8#include <asm/tlbflush.h>
7 9
8struct real_mode_header *real_mode_header; 10struct real_mode_header *real_mode_header;
9u32 *trampoline_cr4_features; 11u32 *trampoline_cr4_features;
@@ -11,25 +13,37 @@ u32 *trampoline_cr4_features;
11/* Hold the pgd entry used on booting additional CPUs */ 13/* Hold the pgd entry used on booting additional CPUs */
12pgd_t trampoline_pgd_entry; 14pgd_t trampoline_pgd_entry;
13 15
16void __init set_real_mode_mem(phys_addr_t mem, size_t size)
17{
18 void *base = __va(mem);
19
20 real_mode_header = (struct real_mode_header *) base;
21 printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
22 base, (unsigned long long)mem, size);
23}
24
14void __init reserve_real_mode(void) 25void __init reserve_real_mode(void)
15{ 26{
16 phys_addr_t mem; 27 phys_addr_t mem;
17 unsigned char *base; 28 size_t size = real_mode_size_needed();
18 size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); 29
30 if (!size)
31 return;
32
33 WARN_ON(slab_is_available());
19 34
20 /* Has to be under 1M so we can execute real-mode AP code. */ 35 /* Has to be under 1M so we can execute real-mode AP code. */
21 mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); 36 mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
22 if (!mem) 37 if (!mem) {
23 panic("Cannot allocate trampoline\n"); 38 pr_info("No sub-1M memory is available for the trampoline\n");
39 return;
40 }
24 41
25 base = __va(mem);
26 memblock_reserve(mem, size); 42 memblock_reserve(mem, size);
27 real_mode_header = (struct real_mode_header *) base; 43 set_real_mode_mem(mem, size);
28 printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
29 base, (unsigned long long)mem, size);
30} 44}
31 45
32void __init setup_real_mode(void) 46static void __init setup_real_mode(void)
33{ 47{
34 u16 real_mode_seg; 48 u16 real_mode_seg;
35 const u32 *rel; 49 const u32 *rel;
@@ -84,7 +98,7 @@ void __init setup_real_mode(void)
84 98
85 trampoline_header->start = (u64) secondary_startup_64; 99 trampoline_header->start = (u64) secondary_startup_64;
86 trampoline_cr4_features = &trampoline_header->cr4; 100 trampoline_cr4_features = &trampoline_header->cr4;
87 *trampoline_cr4_features = __read_cr4(); 101 *trampoline_cr4_features = mmu_cr4_features;
88 102
89 trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); 103 trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
90 trampoline_pgd[0] = trampoline_pgd_entry.pgd; 104 trampoline_pgd[0] = trampoline_pgd_entry.pgd;
@@ -100,7 +114,7 @@ void __init setup_real_mode(void)
100 * need to mark it executable at do_pre_smp_initcalls() at least, 114 * need to mark it executable at do_pre_smp_initcalls() at least,
101 * thus run it as a early_initcall(). 115 * thus run it as a early_initcall().
102 */ 116 */
103static int __init set_real_mode_permissions(void) 117static void __init set_real_mode_permissions(void)
104{ 118{
105 unsigned char *base = (unsigned char *) real_mode_header; 119 unsigned char *base = (unsigned char *) real_mode_header;
106 size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); 120 size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
@@ -119,7 +133,16 @@ static int __init set_real_mode_permissions(void)
119 set_memory_nx((unsigned long) base, size >> PAGE_SHIFT); 133 set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
120 set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT); 134 set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
121 set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT); 135 set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);
136}
137
138static int __init init_real_mode(void)
139{
140 if (!real_mode_header)
141 panic("Real mode trampoline was not allocated");
142
143 setup_real_mode();
144 set_real_mode_permissions();
122 145
123 return 0; 146 return 0;
124} 147}
125early_initcall(set_real_mode_permissions); 148early_initcall(init_real_mode);