aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/head_32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/head_32.S')
-rw-r--r--arch/x86/kernel/head_32.S188
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 */
64LOWMEM_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 */
64MAPPING_BEYOND_END = \ 67MAPPING_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 */
72KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT 74KERNEL_PAGES = LOWMEM_PAGES
73 75
74INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm 76INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE
75RESERVE_BRK(pagetables, INIT_MAP_SIZE) 77RESERVE_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
85ENTRY(startup_32) 87ENTRY(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
1002: 1052:
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
1321: 1381:
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
155bad_subarch:
156WEAK(lguest_entry)
157WEAK(xen_entry)
158 /* Unknown implementation; there's really
159 nothing we can do at this point. */
160 ud2a
161
162 __INITDATA
163
164subarch_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 */
169num_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 */
182default_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
20210: 17110:
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
233page_pde_offset = (__PAGE_OFFSET >> 20); 202page_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
23810: 20710:
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
248bad_subarch:
249WEAK(lguest_entry)
250WEAK(xen_entry)
251 /* Unknown implementation; there's really
252 nothing we can do at this point. */
253 ud2a
254
255 __INITDATA
256
257subarch_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 */
262num_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 */
2843: 291default_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 */
3431: 3541:
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
3591:
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
4731:
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
615ENTRY(initial_code) 619ENTRY(initial_code)
616 .long i386_start_kernel 620 .long i386_start_kernel
617ENTRY(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
626swapper_pg_pmd: 628initial_pg_pmd:
627 .fill 1024*KPMDS,4,0 629 .fill 1024*KPMDS,4,0
628#else 630#else
629ENTRY(swapper_pg_dir) 631ENTRY(initial_page_table)
630 .fill 1024,4,0 632 .fill 1024,4,0
631#endif 633#endif
632swapper_pg_fixmap: 634initial_pg_fixmap:
633 .fill 1024,4,0
634#ifdef CONFIG_X86_TRAMPOLINE
635ENTRY(trampoline_pg_dir)
636 .fill 1024,4,0 635 .fill 1024,4,0
637#endif
638ENTRY(empty_zero_page) 636ENTRY(empty_zero_page)
639 .fill 4096,1,0 637 .fill 4096,1,0
638ENTRY(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
648ENTRY(swapper_pg_dir) 648ENTRY(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
669ENTRY(stack_start) 670ENTRY(stack_start)
670 .long init_thread_union+THREAD_SIZE 671 .long init_thread_union+THREAD_SIZE
671 .long __BOOT_DS
672
673ready: .byte 0
674 672
675early_recursion_flag: 673early_recursion_flag:
676 .long 0 674 .long 0
677 675
676ready: .byte 0
677
678int_msg: 678int_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