diff options
Diffstat (limited to 'arch/x86/kernel/head64.c')
-rw-r--r-- | arch/x86/kernel/head64.c | 101 |
1 files changed, 29 insertions, 72 deletions
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index e25c57b8aa8..1b318e903bf 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -25,6 +25,27 @@ | |||
25 | #include <asm/e820.h> | 25 | #include <asm/e820.h> |
26 | #include <asm/bios_ebda.h> | 26 | #include <asm/bios_ebda.h> |
27 | 27 | ||
28 | /* boot cpu pda */ | ||
29 | static struct x8664_pda _boot_cpu_pda __read_mostly; | ||
30 | |||
31 | #ifdef CONFIG_SMP | ||
32 | /* | ||
33 | * We install an empty cpu_pda pointer table to indicate to early users | ||
34 | * (numa_set_node) that the cpu_pda pointer table for cpus other than | ||
35 | * the boot cpu is not yet setup. | ||
36 | */ | ||
37 | static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata; | ||
38 | #else | ||
39 | static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly; | ||
40 | #endif | ||
41 | |||
42 | void __init x86_64_init_pda(void) | ||
43 | { | ||
44 | _cpu_pda = __cpu_pda; | ||
45 | cpu_pda(0) = &_boot_cpu_pda; | ||
46 | pda_init(0); | ||
47 | } | ||
48 | |||
28 | static void __init zap_identity_mappings(void) | 49 | static void __init zap_identity_mappings(void) |
29 | { | 50 | { |
30 | pgd_t *pgd = pgd_offset_k(0UL); | 51 | pgd_t *pgd = pgd_offset_k(0UL); |
@@ -51,74 +72,6 @@ static void __init copy_bootdata(char *real_mode_data) | |||
51 | } | 72 | } |
52 | } | 73 | } |
53 | 74 | ||
54 | #define BIOS_LOWMEM_KILOBYTES 0x413 | ||
55 | |||
56 | /* | ||
57 | * The BIOS places the EBDA/XBDA at the top of conventional | ||
58 | * memory, and usually decreases the reported amount of | ||
59 | * conventional memory (int 0x12) too. This also contains a | ||
60 | * workaround for Dell systems that neglect to reserve EBDA. | ||
61 | * The same workaround also avoids a problem with the AMD768MPX | ||
62 | * chipset: reserve a page before VGA to prevent PCI prefetch | ||
63 | * into it (errata #56). Usually the page is reserved anyways, | ||
64 | * unless you have no PS/2 mouse plugged in. | ||
65 | */ | ||
66 | static void __init reserve_ebda_region(void) | ||
67 | { | ||
68 | unsigned int lowmem, ebda_addr; | ||
69 | |||
70 | /* To determine the position of the EBDA and the */ | ||
71 | /* end of conventional memory, we need to look at */ | ||
72 | /* the BIOS data area. In a paravirtual environment */ | ||
73 | /* that area is absent. We'll just have to assume */ | ||
74 | /* that the paravirt case can handle memory setup */ | ||
75 | /* correctly, without our help. */ | ||
76 | if (paravirt_enabled()) | ||
77 | return; | ||
78 | |||
79 | /* end of low (conventional) memory */ | ||
80 | lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES); | ||
81 | lowmem <<= 10; | ||
82 | |||
83 | /* start of EBDA area */ | ||
84 | ebda_addr = get_bios_ebda(); | ||
85 | |||
86 | /* Fixup: bios puts an EBDA in the top 64K segment */ | ||
87 | /* of conventional memory, but does not adjust lowmem. */ | ||
88 | if ((lowmem - ebda_addr) <= 0x10000) | ||
89 | lowmem = ebda_addr; | ||
90 | |||
91 | /* Fixup: bios does not report an EBDA at all. */ | ||
92 | /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */ | ||
93 | if ((ebda_addr == 0) && (lowmem >= 0x9f000)) | ||
94 | lowmem = 0x9f000; | ||
95 | |||
96 | /* Paranoia: should never happen, but... */ | ||
97 | if ((lowmem == 0) || (lowmem >= 0x100000)) | ||
98 | lowmem = 0x9f000; | ||
99 | |||
100 | /* reserve all memory between lowmem and the 1MB mark */ | ||
101 | reserve_early(lowmem, 0x100000, "BIOS reserved"); | ||
102 | } | ||
103 | |||
104 | static void __init reserve_setup_data(void) | ||
105 | { | ||
106 | struct setup_data *data; | ||
107 | unsigned long pa_data; | ||
108 | char buf[32]; | ||
109 | |||
110 | if (boot_params.hdr.version < 0x0209) | ||
111 | return; | ||
112 | pa_data = boot_params.hdr.setup_data; | ||
113 | while (pa_data) { | ||
114 | data = early_ioremap(pa_data, sizeof(*data)); | ||
115 | sprintf(buf, "setup data %x", data->type); | ||
116 | reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf); | ||
117 | pa_data = data->next; | ||
118 | early_iounmap(data, sizeof(*data)); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | void __init x86_64_start_kernel(char * real_mode_data) | 75 | void __init x86_64_start_kernel(char * real_mode_data) |
123 | { | 76 | { |
124 | int i; | 77 | int i; |
@@ -156,10 +109,15 @@ void __init x86_64_start_kernel(char * real_mode_data) | |||
156 | 109 | ||
157 | early_printk("Kernel alive\n"); | 110 | early_printk("Kernel alive\n"); |
158 | 111 | ||
159 | for (i = 0; i < NR_CPUS; i++) | 112 | x86_64_init_pda(); |
160 | cpu_pda(i) = &boot_cpu_pda[i]; | ||
161 | 113 | ||
162 | pda_init(0); | 114 | early_printk("Kernel really alive\n"); |
115 | |||
116 | x86_64_start_reservations(real_mode_data); | ||
117 | } | ||
118 | |||
119 | void __init x86_64_start_reservations(char *real_mode_data) | ||
120 | { | ||
163 | copy_bootdata(__va(real_mode_data)); | 121 | copy_bootdata(__va(real_mode_data)); |
164 | 122 | ||
165 | reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS"); | 123 | reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS"); |
@@ -175,7 +133,6 @@ void __init x86_64_start_kernel(char * real_mode_data) | |||
175 | #endif | 133 | #endif |
176 | 134 | ||
177 | reserve_ebda_region(); | 135 | reserve_ebda_region(); |
178 | reserve_setup_data(); | ||
179 | 136 | ||
180 | /* | 137 | /* |
181 | * At this point everything still needed from the boot loader | 138 | * At this point everything still needed from the boot loader |