diff options
Diffstat (limited to 'arch/x86/kernel/head_32.S')
-rw-r--r-- | arch/x86/kernel/head_32.S | 188 |
1 files changed, 94 insertions, 94 deletions
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index fa8c1b8e09fb..ce0be7cd085e 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -60,18 +60,20 @@ | |||
60 | #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) | 60 | #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | /* Number of possible pages in the lowmem region */ | ||
64 | LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) | ||
65 | |||
63 | /* Enough space to fit pagetables for the low memory linear map */ | 66 | /* Enough space to fit pagetables for the low memory linear map */ |
64 | MAPPING_BEYOND_END = \ | 67 | MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT |
65 | PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT | ||
66 | 68 | ||
67 | /* | 69 | /* |
68 | * Worst-case size of the kernel mapping we need to make: | 70 | * Worst-case size of the kernel mapping we need to make: |
69 | * the worst-case size of the kernel itself, plus the extra we need | 71 | * a relocatable kernel can live anywhere in lowmem, so we need to be able |
70 | * to map for the linear map. | 72 | * to map all of lowmem. |
71 | */ | 73 | */ |
72 | KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT | 74 | KERNEL_PAGES = LOWMEM_PAGES |
73 | 75 | ||
74 | INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm | 76 | INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE |
75 | RESERVE_BRK(pagetables, INIT_MAP_SIZE) | 77 | RESERVE_BRK(pagetables, INIT_MAP_SIZE) |
76 | 78 | ||
77 | /* | 79 | /* |
@@ -83,6 +85,8 @@ RESERVE_BRK(pagetables, INIT_MAP_SIZE) | |||
83 | */ | 85 | */ |
84 | __HEAD | 86 | __HEAD |
85 | ENTRY(startup_32) | 87 | ENTRY(startup_32) |
88 | movl pa(stack_start),%ecx | ||
89 | |||
86 | /* test KEEP_SEGMENTS flag to see if the bootloader is asking | 90 | /* test KEEP_SEGMENTS flag to see if the bootloader is asking |
87 | us to not reload segments */ | 91 | us to not reload segments */ |
88 | testb $(1<<6), BP_loadflags(%esi) | 92 | testb $(1<<6), BP_loadflags(%esi) |
@@ -97,7 +101,9 @@ ENTRY(startup_32) | |||
97 | movl %eax,%es | 101 | movl %eax,%es |
98 | movl %eax,%fs | 102 | movl %eax,%fs |
99 | movl %eax,%gs | 103 | movl %eax,%gs |
104 | movl %eax,%ss | ||
100 | 2: | 105 | 2: |
106 | leal -__PAGE_OFFSET(%ecx),%esp | ||
101 | 107 | ||
102 | /* | 108 | /* |
103 | * Clear BSS first so that there are no surprises... | 109 | * Clear BSS first so that there are no surprises... |
@@ -124,72 +130,35 @@ ENTRY(startup_32) | |||
124 | movsl | 130 | movsl |
125 | movl pa(boot_params) + NEW_CL_POINTER,%esi | 131 | movl pa(boot_params) + NEW_CL_POINTER,%esi |
126 | andl %esi,%esi | 132 | andl %esi,%esi |
127 | jz 1f # No comand line | 133 | jz 1f # No command line |
128 | movl $pa(boot_command_line),%edi | 134 | movl $pa(boot_command_line),%edi |
129 | movl $(COMMAND_LINE_SIZE/4),%ecx | 135 | movl $(COMMAND_LINE_SIZE/4),%ecx |
130 | rep | 136 | rep |
131 | movsl | 137 | movsl |
132 | 1: | 138 | 1: |
133 | 139 | ||
134 | #ifdef CONFIG_OLPC_OPENFIRMWARE | 140 | #ifdef CONFIG_OLPC |
135 | /* save OFW's pgdir table for later use when calling into OFW */ | 141 | /* save OFW's pgdir table for later use when calling into OFW */ |
136 | movl %cr3, %eax | 142 | movl %cr3, %eax |
137 | movl %eax, pa(olpc_ofw_pgd) | 143 | movl %eax, pa(olpc_ofw_pgd) |
138 | #endif | 144 | #endif |
139 | 145 | ||
140 | #ifdef CONFIG_PARAVIRT | ||
141 | /* This is can only trip for a broken bootloader... */ | ||
142 | cmpw $0x207, pa(boot_params + BP_version) | ||
143 | jb default_entry | ||
144 | |||
145 | /* Paravirt-compatible boot parameters. Look to see what architecture | ||
146 | we're booting under. */ | ||
147 | movl pa(boot_params + BP_hardware_subarch), %eax | ||
148 | cmpl $num_subarch_entries, %eax | ||
149 | jae bad_subarch | ||
150 | |||
151 | movl pa(subarch_entries)(,%eax,4), %eax | ||
152 | subl $__PAGE_OFFSET, %eax | ||
153 | jmp *%eax | ||
154 | |||
155 | bad_subarch: | ||
156 | WEAK(lguest_entry) | ||
157 | WEAK(xen_entry) | ||
158 | /* Unknown implementation; there's really | ||
159 | nothing we can do at this point. */ | ||
160 | ud2a | ||
161 | |||
162 | __INITDATA | ||
163 | |||
164 | subarch_entries: | ||
165 | .long default_entry /* normal x86/PC */ | ||
166 | .long lguest_entry /* lguest hypervisor */ | ||
167 | .long xen_entry /* Xen hypervisor */ | ||
168 | .long default_entry /* Moorestown MID */ | ||
169 | num_subarch_entries = (. - subarch_entries) / 4 | ||
170 | .previous | ||
171 | #endif /* CONFIG_PARAVIRT */ | ||
172 | |||
173 | /* | 146 | /* |
174 | * Initialize page tables. This creates a PDE and a set of page | 147 | * Initialize page tables. This creates a PDE and a set of page |
175 | * tables, which are located immediately beyond __brk_base. The variable | 148 | * tables, which are located immediately beyond __brk_base. The variable |
176 | * _brk_end is set up to point to the first "safe" location. | 149 | * _brk_end is set up to point to the first "safe" location. |
177 | * Mappings are created both at virtual address 0 (identity mapping) | 150 | * Mappings are created both at virtual address 0 (identity mapping) |
178 | * and PAGE_OFFSET for up to _end. | 151 | * and PAGE_OFFSET for up to _end. |
179 | * | ||
180 | * Note that the stack is not yet set up! | ||
181 | */ | 152 | */ |
182 | default_entry: | ||
183 | #ifdef CONFIG_X86_PAE | 153 | #ifdef CONFIG_X86_PAE |
184 | 154 | ||
185 | /* | 155 | /* |
186 | * In PAE mode swapper_pg_dir is statically defined to contain enough | 156 | * In PAE mode initial_page_table is statically defined to contain |
187 | * entries to cover the VMSPLIT option (that is the top 1, 2 or 3 | 157 | * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 |
188 | * entries). The identity mapping is handled by pointing two PGD | 158 | * entries). The identity mapping is handled by pointing two PGD entries |
189 | * entries to the first kernel PMD. | 159 | * to the first kernel PMD. |
190 | * | 160 | * |
191 | * Note the upper half of each PMD or PTE are always zero at | 161 | * Note the upper half of each PMD or PTE are always zero at this stage. |
192 | * this stage. | ||
193 | */ | 162 | */ |
194 | 163 | ||
195 | #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ | 164 | #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ |
@@ -197,7 +166,7 @@ default_entry: | |||
197 | xorl %ebx,%ebx /* %ebx is kept at zero */ | 166 | xorl %ebx,%ebx /* %ebx is kept at zero */ |
198 | 167 | ||
199 | movl $pa(__brk_base), %edi | 168 | movl $pa(__brk_base), %edi |
200 | movl $pa(swapper_pg_pmd), %edx | 169 | movl $pa(initial_pg_pmd), %edx |
201 | movl $PTE_IDENT_ATTR, %eax | 170 | movl $PTE_IDENT_ATTR, %eax |
202 | 10: | 171 | 10: |
203 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ | 172 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ |
@@ -226,14 +195,14 @@ default_entry: | |||
226 | movl %eax, pa(max_pfn_mapped) | 195 | movl %eax, pa(max_pfn_mapped) |
227 | 196 | ||
228 | /* Do early initialization of the fixmap area */ | 197 | /* Do early initialization of the fixmap area */ |
229 | movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax | 198 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax |
230 | movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8) | 199 | movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) |
231 | #else /* Not PAE */ | 200 | #else /* Not PAE */ |
232 | 201 | ||
233 | page_pde_offset = (__PAGE_OFFSET >> 20); | 202 | page_pde_offset = (__PAGE_OFFSET >> 20); |
234 | 203 | ||
235 | movl $pa(__brk_base), %edi | 204 | movl $pa(__brk_base), %edi |
236 | movl $pa(swapper_pg_dir), %edx | 205 | movl $pa(initial_page_table), %edx |
237 | movl $PTE_IDENT_ATTR, %eax | 206 | movl $PTE_IDENT_ATTR, %eax |
238 | 10: | 207 | 10: |
239 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ | 208 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ |
@@ -257,10 +226,45 @@ page_pde_offset = (__PAGE_OFFSET >> 20); | |||
257 | movl %eax, pa(max_pfn_mapped) | 226 | movl %eax, pa(max_pfn_mapped) |
258 | 227 | ||
259 | /* Do early initialization of the fixmap area */ | 228 | /* Do early initialization of the fixmap area */ |
260 | movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax | 229 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax |
261 | movl %eax,pa(swapper_pg_dir+0xffc) | 230 | movl %eax,pa(initial_page_table+0xffc) |
262 | #endif | 231 | #endif |
263 | jmp 3f | 232 | |
233 | #ifdef CONFIG_PARAVIRT | ||
234 | /* This is can only trip for a broken bootloader... */ | ||
235 | cmpw $0x207, pa(boot_params + BP_version) | ||
236 | jb default_entry | ||
237 | |||
238 | /* Paravirt-compatible boot parameters. Look to see what architecture | ||
239 | we're booting under. */ | ||
240 | movl pa(boot_params + BP_hardware_subarch), %eax | ||
241 | cmpl $num_subarch_entries, %eax | ||
242 | jae bad_subarch | ||
243 | |||
244 | movl pa(subarch_entries)(,%eax,4), %eax | ||
245 | subl $__PAGE_OFFSET, %eax | ||
246 | jmp *%eax | ||
247 | |||
248 | bad_subarch: | ||
249 | WEAK(lguest_entry) | ||
250 | WEAK(xen_entry) | ||
251 | /* Unknown implementation; there's really | ||
252 | nothing we can do at this point. */ | ||
253 | ud2a | ||
254 | |||
255 | __INITDATA | ||
256 | |||
257 | subarch_entries: | ||
258 | .long default_entry /* normal x86/PC */ | ||
259 | .long lguest_entry /* lguest hypervisor */ | ||
260 | .long xen_entry /* Xen hypervisor */ | ||
261 | .long default_entry /* Moorestown MID */ | ||
262 | num_subarch_entries = (. - subarch_entries) / 4 | ||
263 | .previous | ||
264 | #else | ||
265 | jmp default_entry | ||
266 | #endif /* CONFIG_PARAVIRT */ | ||
267 | |||
264 | /* | 268 | /* |
265 | * Non-boot CPU entry point; entered from trampoline.S | 269 | * Non-boot CPU entry point; entered from trampoline.S |
266 | * We can't lgdt here, because lgdt itself uses a data segment, but | 270 | * We can't lgdt here, because lgdt itself uses a data segment, but |
@@ -280,8 +284,11 @@ ENTRY(startup_32_smp) | |||
280 | movl %eax,%es | 284 | movl %eax,%es |
281 | movl %eax,%fs | 285 | movl %eax,%fs |
282 | movl %eax,%gs | 286 | movl %eax,%gs |
287 | movl pa(stack_start),%ecx | ||
288 | movl %eax,%ss | ||
289 | leal -__PAGE_OFFSET(%ecx),%esp | ||
283 | #endif /* CONFIG_SMP */ | 290 | #endif /* CONFIG_SMP */ |
284 | 3: | 291 | default_entry: |
285 | 292 | ||
286 | /* | 293 | /* |
287 | * New page tables may be in 4Mbyte page mode and may | 294 | * New page tables may be in 4Mbyte page mode and may |
@@ -315,6 +322,10 @@ ENTRY(startup_32_smp) | |||
315 | subl $0x80000001, %eax | 322 | subl $0x80000001, %eax |
316 | cmpl $(0x8000ffff-0x80000001), %eax | 323 | cmpl $(0x8000ffff-0x80000001), %eax |
317 | ja 6f | 324 | ja 6f |
325 | |||
326 | /* Clear bogus XD_DISABLE bits */ | ||
327 | call verify_cpu | ||
328 | |||
318 | mov $0x80000001, %eax | 329 | mov $0x80000001, %eax |
319 | cpuid | 330 | cpuid |
320 | /* Execute Disable bit supported? */ | 331 | /* Execute Disable bit supported? */ |
@@ -334,15 +345,15 @@ ENTRY(startup_32_smp) | |||
334 | /* | 345 | /* |
335 | * Enable paging | 346 | * Enable paging |
336 | */ | 347 | */ |
337 | movl pa(initial_page_table), %eax | 348 | movl $pa(initial_page_table), %eax |
338 | movl %eax,%cr3 /* set the page table pointer.. */ | 349 | movl %eax,%cr3 /* set the page table pointer.. */ |
339 | movl %cr0,%eax | 350 | movl %cr0,%eax |
340 | orl $X86_CR0_PG,%eax | 351 | orl $X86_CR0_PG,%eax |
341 | movl %eax,%cr0 /* ..and set paging (PG) bit */ | 352 | movl %eax,%cr0 /* ..and set paging (PG) bit */ |
342 | ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ | 353 | ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ |
343 | 1: | 354 | 1: |
344 | /* Set up the stack pointer */ | 355 | /* Shift the stack pointer to a virtual address */ |
345 | lss stack_start,%esp | 356 | addl $__PAGE_OFFSET, %esp |
346 | 357 | ||
347 | /* | 358 | /* |
348 | * Initialize eflags. Some BIOS's leave bits like NT set. This would | 359 | * Initialize eflags. Some BIOS's leave bits like NT set. This would |
@@ -354,9 +365,7 @@ ENTRY(startup_32_smp) | |||
354 | 365 | ||
355 | #ifdef CONFIG_SMP | 366 | #ifdef CONFIG_SMP |
356 | cmpb $0, ready | 367 | cmpb $0, ready |
357 | jz 1f /* Initial CPU cleans BSS */ | 368 | jnz checkCPUtype |
358 | jmp checkCPUtype | ||
359 | 1: | ||
360 | #endif /* CONFIG_SMP */ | 369 | #endif /* CONFIG_SMP */ |
361 | 370 | ||
362 | /* | 371 | /* |
@@ -464,14 +473,7 @@ is386: movl $2,%ecx # set MP | |||
464 | 473 | ||
465 | cld # gcc2 wants the direction flag cleared at all times | 474 | cld # gcc2 wants the direction flag cleared at all times |
466 | pushl $0 # fake return address for unwinder | 475 | pushl $0 # fake return address for unwinder |
467 | #ifdef CONFIG_SMP | ||
468 | movb ready, %cl | ||
469 | movb $1, ready | 476 | movb $1, ready |
470 | cmpb $0,%cl # the first CPU calls start_kernel | ||
471 | je 1f | ||
472 | movl (stack_start), %esp | ||
473 | 1: | ||
474 | #endif /* CONFIG_SMP */ | ||
475 | jmp *(initial_code) | 477 | jmp *(initial_code) |
476 | 478 | ||
477 | /* | 479 | /* |
@@ -610,33 +612,31 @@ ignore_int: | |||
610 | #endif | 612 | #endif |
611 | iret | 613 | iret |
612 | 614 | ||
615 | #include "verify_cpu.S" | ||
616 | |||
613 | __REFDATA | 617 | __REFDATA |
614 | .align 4 | 618 | .align 4 |
615 | ENTRY(initial_code) | 619 | ENTRY(initial_code) |
616 | .long i386_start_kernel | 620 | .long i386_start_kernel |
617 | ENTRY(initial_page_table) | ||
618 | .long pa(swapper_pg_dir) | ||
619 | 621 | ||
620 | /* | 622 | /* |
621 | * BSS section | 623 | * BSS section |
622 | */ | 624 | */ |
623 | __PAGE_ALIGNED_BSS | 625 | __PAGE_ALIGNED_BSS |
624 | .align PAGE_SIZE_asm | 626 | .align PAGE_SIZE |
625 | #ifdef CONFIG_X86_PAE | 627 | #ifdef CONFIG_X86_PAE |
626 | swapper_pg_pmd: | 628 | initial_pg_pmd: |
627 | .fill 1024*KPMDS,4,0 | 629 | .fill 1024*KPMDS,4,0 |
628 | #else | 630 | #else |
629 | ENTRY(swapper_pg_dir) | 631 | ENTRY(initial_page_table) |
630 | .fill 1024,4,0 | 632 | .fill 1024,4,0 |
631 | #endif | 633 | #endif |
632 | swapper_pg_fixmap: | 634 | initial_pg_fixmap: |
633 | .fill 1024,4,0 | ||
634 | #ifdef CONFIG_X86_TRAMPOLINE | ||
635 | ENTRY(trampoline_pg_dir) | ||
636 | .fill 1024,4,0 | 635 | .fill 1024,4,0 |
637 | #endif | ||
638 | ENTRY(empty_zero_page) | 636 | ENTRY(empty_zero_page) |
639 | .fill 4096,1,0 | 637 | .fill 4096,1,0 |
638 | ENTRY(swapper_pg_dir) | ||
639 | .fill 1024,4,0 | ||
640 | 640 | ||
641 | /* | 641 | /* |
642 | * This starts the data section. | 642 | * This starts the data section. |
@@ -644,37 +644,37 @@ ENTRY(empty_zero_page) | |||
644 | #ifdef CONFIG_X86_PAE | 644 | #ifdef CONFIG_X86_PAE |
645 | __PAGE_ALIGNED_DATA | 645 | __PAGE_ALIGNED_DATA |
646 | /* Page-aligned for the benefit of paravirt? */ | 646 | /* Page-aligned for the benefit of paravirt? */ |
647 | .align PAGE_SIZE_asm | 647 | .align PAGE_SIZE |
648 | ENTRY(swapper_pg_dir) | 648 | ENTRY(initial_page_table) |
649 | .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ | 649 | .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ |
650 | # if KPMDS == 3 | 650 | # if KPMDS == 3 |
651 | .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 | 651 | .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 |
652 | .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 | 652 | .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0 |
653 | .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0 | 653 | .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0 |
654 | # elif KPMDS == 2 | 654 | # elif KPMDS == 2 |
655 | .long 0,0 | 655 | .long 0,0 |
656 | .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 | 656 | .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 |
657 | .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 | 657 | .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0 |
658 | # elif KPMDS == 1 | 658 | # elif KPMDS == 1 |
659 | .long 0,0 | 659 | .long 0,0 |
660 | .long 0,0 | 660 | .long 0,0 |
661 | .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 | 661 | .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 |
662 | # else | 662 | # else |
663 | # error "Kernel PMDs should be 1, 2 or 3" | 663 | # error "Kernel PMDs should be 1, 2 or 3" |
664 | # endif | 664 | # endif |
665 | .align PAGE_SIZE_asm /* needs to be page-sized too */ | 665 | .align PAGE_SIZE /* needs to be page-sized too */ |
666 | #endif | 666 | #endif |
667 | 667 | ||
668 | .data | 668 | .data |
669 | .balign 4 | ||
669 | ENTRY(stack_start) | 670 | ENTRY(stack_start) |
670 | .long init_thread_union+THREAD_SIZE | 671 | .long init_thread_union+THREAD_SIZE |
671 | .long __BOOT_DS | ||
672 | |||
673 | ready: .byte 0 | ||
674 | 672 | ||
675 | early_recursion_flag: | 673 | early_recursion_flag: |
676 | .long 0 | 674 | .long 0 |
677 | 675 | ||
676 | ready: .byte 0 | ||
677 | |||
678 | int_msg: | 678 | int_msg: |
679 | .asciz "Unknown interrupt or fault at: %p %p %p\n" | 679 | .asciz "Unknown interrupt or fault at: %p %p %p\n" |
680 | 680 | ||