diff options
Diffstat (limited to 'arch/x86_64/kernel/head64.c')
-rw-r--r-- | arch/x86_64/kernel/head64.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index 5f197b0a330a..213d90e04755 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c | |||
@@ -18,8 +18,16 @@ | |||
18 | #include <asm/setup.h> | 18 | #include <asm/setup.h> |
19 | #include <asm/desc.h> | 19 | #include <asm/desc.h> |
20 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
21 | #include <asm/tlbflush.h> | ||
21 | #include <asm/sections.h> | 22 | #include <asm/sections.h> |
22 | 23 | ||
24 | static void __init zap_identity_mappings(void) | ||
25 | { | ||
26 | pgd_t *pgd = pgd_offset_k(0UL); | ||
27 | pgd_clear(pgd); | ||
28 | __flush_tlb(); | ||
29 | } | ||
30 | |||
23 | /* Don't add a printk in there. printk relies on the PDA which is not initialized | 31 | /* Don't add a printk in there. printk relies on the PDA which is not initialized |
24 | yet. */ | 32 | yet. */ |
25 | static void __init clear_bss(void) | 33 | static void __init clear_bss(void) |
@@ -29,25 +37,24 @@ static void __init clear_bss(void) | |||
29 | } | 37 | } |
30 | 38 | ||
31 | #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ | 39 | #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ |
32 | #define OLD_CL_MAGIC_ADDR 0x90020 | 40 | #define OLD_CL_MAGIC_ADDR 0x20 |
33 | #define OLD_CL_MAGIC 0xA33F | 41 | #define OLD_CL_MAGIC 0xA33F |
34 | #define OLD_CL_BASE_ADDR 0x90000 | 42 | #define OLD_CL_OFFSET 0x22 |
35 | #define OLD_CL_OFFSET 0x90022 | ||
36 | 43 | ||
37 | static void __init copy_bootdata(char *real_mode_data) | 44 | static void __init copy_bootdata(char *real_mode_data) |
38 | { | 45 | { |
39 | int new_data; | 46 | unsigned long new_data; |
40 | char * command_line; | 47 | char * command_line; |
41 | 48 | ||
42 | memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE); | 49 | memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE); |
43 | new_data = *(int *) (x86_boot_params + NEW_CL_POINTER); | 50 | new_data = *(u32 *) (x86_boot_params + NEW_CL_POINTER); |
44 | if (!new_data) { | 51 | if (!new_data) { |
45 | if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) { | 52 | if (OLD_CL_MAGIC != *(u16 *)(real_mode_data + OLD_CL_MAGIC_ADDR)) { |
46 | return; | 53 | return; |
47 | } | 54 | } |
48 | new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET; | 55 | new_data = __pa(real_mode_data) + *(u16 *)(real_mode_data + OLD_CL_OFFSET); |
49 | } | 56 | } |
50 | command_line = (char *) ((u64)(new_data)); | 57 | command_line = __va(new_data); |
51 | memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | 58 | memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); |
52 | } | 59 | } |
53 | 60 | ||
@@ -55,26 +62,30 @@ void __init x86_64_start_kernel(char * real_mode_data) | |||
55 | { | 62 | { |
56 | int i; | 63 | int i; |
57 | 64 | ||
65 | /* | ||
66 | * Make sure kernel is aligned to 2MB address. Catching it at compile | ||
67 | * time is better. Change your config file and compile the kernel | ||
68 | * for a 2MB aligned address (CONFIG_PHYSICAL_START) | ||
69 | */ | ||
70 | BUILD_BUG_ON(CONFIG_PHYSICAL_START & (__KERNEL_ALIGN - 1)); | ||
71 | |||
58 | /* clear bss before set_intr_gate with early_idt_handler */ | 72 | /* clear bss before set_intr_gate with early_idt_handler */ |
59 | clear_bss(); | 73 | clear_bss(); |
60 | 74 | ||
75 | /* Make NULL pointers segfault */ | ||
76 | zap_identity_mappings(); | ||
77 | |||
61 | for (i = 0; i < IDT_ENTRIES; i++) | 78 | for (i = 0; i < IDT_ENTRIES; i++) |
62 | set_intr_gate(i, early_idt_handler); | 79 | set_intr_gate(i, early_idt_handler); |
63 | asm volatile("lidt %0" :: "m" (idt_descr)); | 80 | asm volatile("lidt %0" :: "m" (idt_descr)); |
64 | 81 | ||
65 | early_printk("Kernel alive\n"); | 82 | early_printk("Kernel alive\n"); |
66 | 83 | ||
67 | /* | ||
68 | * switch to init_level4_pgt from boot_level4_pgt | ||
69 | */ | ||
70 | memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t)); | ||
71 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | ||
72 | |||
73 | for (i = 0; i < NR_CPUS; i++) | 84 | for (i = 0; i < NR_CPUS; i++) |
74 | cpu_pda(i) = &boot_cpu_pda[i]; | 85 | cpu_pda(i) = &boot_cpu_pda[i]; |
75 | 86 | ||
76 | pda_init(0); | 87 | pda_init(0); |
77 | copy_bootdata(real_mode_data); | 88 | copy_bootdata(__va(real_mode_data)); |
78 | #ifdef CONFIG_SMP | 89 | #ifdef CONFIG_SMP |
79 | cpu_set(0, cpu_online_map); | 90 | cpu_set(0, cpu_online_map); |
80 | #endif | 91 | #endif |