]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/x86/kernel/head_32.S
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / head_32.S
1 /*
2  *  linux/arch/i386/kernel/head.S -- the 32-bit startup code.
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  *
6  *  Enhanced CPU detection and feature setting code by Mike Jagdis
7  *  and Martin Mares, November 1997.
8  */
9
10 .text
11 #include <linux/threads.h>
12 #include <linux/linkage.h>
13 #include <asm/segment.h>
14 #include <asm/page.h>
15 #include <asm/pgtable.h>
16 #include <asm/desc.h>
17 #include <asm/cache.h>
18 #include <asm/thread_info.h>
19 #include <asm/asm-offsets.h>
20 #include <asm/setup.h>
21
22 /*
23  * References to members of the new_cpu_data structure.
24  */
25
26 #define X86             new_cpu_data+CPUINFO_x86
27 #define X86_VENDOR      new_cpu_data+CPUINFO_x86_vendor
28 #define X86_MODEL       new_cpu_data+CPUINFO_x86_model
29 #define X86_MASK        new_cpu_data+CPUINFO_x86_mask
30 #define X86_HARD_MATH   new_cpu_data+CPUINFO_hard_math
31 #define X86_CPUID       new_cpu_data+CPUINFO_cpuid_level
32 #define X86_CAPABILITY  new_cpu_data+CPUINFO_x86_capability
33 #define X86_VENDOR_ID   new_cpu_data+CPUINFO_x86_vendor_id
34
35 /*
36  * This is how much memory *in addition to the memory covered up to
37  * and including _end* we need mapped initially.
38  * We need:
39  *  - one bit for each possible page, but only in low memory, which means
40  *     2^32/4096/8 = 128K worst case (4G/4G split.)
41  *  - enough space to map all low memory, which means
42  *     (2^32/4096) / 1024 pages (worst case, non PAE)
43  *     (2^32/4096) / 512 + 4 pages (worst case for PAE)
44  *  - a few pages for allocator use before the kernel pagetable has
45  *     been set up
46  *
47  * Modulo rounding, each megabyte assigned here requires a kilobyte of
48  * memory, which is currently unreclaimed.
49  *
50  * This should be a multiple of a page.
51  */
52 LOW_PAGES = 1<<(32-PAGE_SHIFT_asm)
53
54 /*
55  * To preserve the DMA pool in PAGEALLOC kernels, we'll allocate
56  * pagetables from above the 16MB DMA limit, so we'll have to set
57  * up pagetables 16MB more (worst-case):
58  */
59 #ifdef CONFIG_DEBUG_PAGEALLOC
60 LOW_PAGES = LOW_PAGES + 0x1000000
61 #endif
62
63 #if PTRS_PER_PMD > 1
64 PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD
65 #else
66 PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PGD)
67 #endif
68 BOOTBITMAP_SIZE = LOW_PAGES / 8
69 ALLOCATOR_SLOP = 4
70
71 INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm
72
73 /*
74  * 32-bit kernel entrypoint; only used by the boot CPU.  On entry,
75  * %esi points to the real-mode code as a 32-bit pointer.
76  * CS and DS must be 4 GB flat segments, but we don't depend on
77  * any particular GDT layout, because we load our own as soon as we
78  * can.
79  */
80 .section .text.head,"ax",@progbits
81 ENTRY(startup_32)
82
83 /*
84  * Set segments to known values.
85  */
86         cld
87         lgdt boot_gdt_descr - __PAGE_OFFSET
88         movl $(__BOOT_DS),%eax
89         movl %eax,%ds
90         movl %eax,%es
91         movl %eax,%fs
92         movl %eax,%gs
93
94 /*
95  * Clear BSS first so that there are no surprises...
96  * No need to cld as DF is already clear from cld above...
97  */
98         xorl %eax,%eax
99         movl $__bss_start - __PAGE_OFFSET,%edi
100         movl $__bss_stop - __PAGE_OFFSET,%ecx
101         subl %edi,%ecx
102         shrl $2,%ecx
103         rep ; stosl
104 /*
105  * Copy bootup parameters out of the way.
106  * Note: %esi still has the pointer to the real-mode data.
107  * With the kexec as boot loader, parameter segment might be loaded beyond
108  * kernel image and might not even be addressable by early boot page tables.
109  * (kexec on panic case). Hence copy out the parameters before initializing
110  * page tables.
111  */
112         movl $(boot_params - __PAGE_OFFSET),%edi
113         movl $(PARAM_SIZE/4),%ecx
114         cld
115         rep
116         movsl
117         movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi
118         andl %esi,%esi
119         jnz 2f                  # New command line protocol
120         cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
121         jne 1f
122         movzwl OLD_CL_OFFSET,%esi
123         addl $(OLD_CL_BASE_ADDR),%esi
124 2:
125         movl $(boot_command_line - __PAGE_OFFSET),%edi
126         movl $(COMMAND_LINE_SIZE/4),%ecx
127         rep
128         movsl
129 1:
130
131 /*
132  * Initialize page tables.  This creates a PDE and a set of page
133  * tables, which are located immediately beyond _end.  The variable
134  * init_pg_tables_end is set up to point to the first "safe" location.
135  * Mappings are created both at virtual address 0 (identity mapping)
136  * and PAGE_OFFSET for up to _end+sizeof(page tables)+INIT_MAP_BEYOND_END.
137  *
138  * Warning: don't use %esi or the stack in this code.  However, %esp
139  * can be used as a GPR if you really need it...
140  */
141 page_pde_offset = (__PAGE_OFFSET >> 20);
142
143         movl $(pg0 - __PAGE_OFFSET), %edi
144         movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
145         movl $0x007, %eax                       /* 0x007 = PRESENT+RW+USER */
146 10:
147         leal 0x007(%edi),%ecx                   /* Create PDE entry */
148         movl %ecx,(%edx)                        /* Store identity PDE entry */
149         movl %ecx,page_pde_offset(%edx)         /* Store kernel PDE entry */
150         addl $4,%edx
151         movl $1024, %ecx
152 11:
153         stosl
154         addl $0x1000,%eax
155         loop 11b
156         /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
157         /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
158         leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
159         cmpl %ebp,%eax
160         jb 10b
161         movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
162
163         xorl %ebx,%ebx                          /* This is the boot CPU (BSP) */
164         jmp 3f
165 /*
166  * Non-boot CPU entry point; entered from trampoline.S
167  * We can't lgdt here, because lgdt itself uses a data segment, but
168  * we know the trampoline has already loaded the boot_gdt for us.
169  *
170  * If cpu hotplug is not supported then this code can go in init section
171  * which will be freed later
172  */
173
174 #ifndef CONFIG_HOTPLUG_CPU
175 .section .init.text,"ax",@progbits
176 #endif
177
178         /* Do an early initialization of the fixmap area */
179         movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
180         movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax
181         addl $0x007, %eax                       /* 0x007 = PRESENT+RW+USER */
182         movl %eax, 4092(%edx)
183
184 #ifdef CONFIG_SMP
185 ENTRY(startup_32_smp)
186         cld
187         movl $(__BOOT_DS),%eax
188         movl %eax,%ds
189         movl %eax,%es
190         movl %eax,%fs
191         movl %eax,%gs
192
193 /*
194  *      New page tables may be in 4Mbyte page mode and may
195  *      be using the global pages. 
196  *
197  *      NOTE! If we are on a 486 we may have no cr4 at all!
198  *      So we do not try to touch it unless we really have
199  *      some bits in it to set.  This won't work if the BSP
200  *      implements cr4 but this AP does not -- very unlikely
201  *      but be warned!  The same applies to the pse feature
202  *      if not equally supported. --macro
203  *
204  *      NOTE! We have to correct for the fact that we're
205  *      not yet offset PAGE_OFFSET..
206  */
207 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
208         movl cr4_bits,%edx
209         andl %edx,%edx
210         jz 6f
211         movl %cr4,%eax          # Turn on paging options (PSE,PAE,..)
212         orl %edx,%eax
213         movl %eax,%cr4
214
215         btl $5, %eax            # check if PAE is enabled
216         jnc 6f
217
218         /* Check if extended functions are implemented */
219         movl $0x80000000, %eax
220         cpuid
221         cmpl $0x80000000, %eax
222         jbe 6f
223         mov $0x80000001, %eax
224         cpuid
225         /* Execute Disable bit supported? */
226         btl $20, %edx
227         jnc 6f
228
229         /* Setup EFER (Extended Feature Enable Register) */
230         movl $0xc0000080, %ecx
231         rdmsr
232
233         btsl $11, %eax
234         /* Make changes effective */
235         wrmsr
236
237 6:
238         /* This is a secondary processor (AP) */
239         xorl %ebx,%ebx
240         incl %ebx
241
242 #endif /* CONFIG_SMP */
243 3:
244
245 /*
246  * Enable paging
247  */
248         movl $swapper_pg_dir-__PAGE_OFFSET,%eax
249         movl %eax,%cr3          /* set the page table pointer.. */
250         movl %cr0,%eax
251         orl $0x80000000,%eax
252         movl %eax,%cr0          /* ..and set paging (PG) bit */
253         ljmp $__BOOT_CS,$1f     /* Clear prefetch and normalize %eip */
254 1:
255         /* Set up the stack pointer */
256         lss stack_start,%esp
257
258 /*
259  * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
260  * confuse the debugger if this code is traced.
261  * XXX - best to initialize before switching to protected mode.
262  */
263         pushl $0
264         popfl
265
266 #ifdef CONFIG_SMP
267         andl %ebx,%ebx
268         jz  1f                          /* Initial CPU cleans BSS */
269         jmp checkCPUtype
270 1:
271 #endif /* CONFIG_SMP */
272
273 /*
274  * start system 32-bit setup. We need to re-do some of the things done
275  * in 16-bit mode for the "real" operations.
276  */
277         call setup_idt
278
279 checkCPUtype:
280
281         movl $-1,X86_CPUID              #  -1 for no CPUID initially
282
283 /* check if it is 486 or 386. */
284 /*
285  * XXX - this does a lot of unnecessary setup.  Alignment checks don't
286  * apply at our cpl of 0 and the stack ought to be aligned already, and
287  * we don't need to preserve eflags.
288  */
289
290         movb $3,X86             # at least 386
291         pushfl                  # push EFLAGS
292         popl %eax               # get EFLAGS
293         movl %eax,%ecx          # save original EFLAGS
294         xorl $0x240000,%eax     # flip AC and ID bits in EFLAGS
295         pushl %eax              # copy to EFLAGS
296         popfl                   # set EFLAGS
297         pushfl                  # get new EFLAGS
298         popl %eax               # put it in eax
299         xorl %ecx,%eax          # change in flags
300         pushl %ecx              # restore original EFLAGS
301         popfl
302         testl $0x40000,%eax     # check if AC bit changed
303         je is386
304
305         movb $4,X86             # at least 486
306         testl $0x200000,%eax    # check if ID bit changed
307         je is486
308
309         /* get vendor info */
310         xorl %eax,%eax                  # call CPUID with 0 -> return vendor ID
311         cpuid
312         movl %eax,X86_CPUID             # save CPUID level
313         movl %ebx,X86_VENDOR_ID         # lo 4 chars
314         movl %edx,X86_VENDOR_ID+4       # next 4 chars
315         movl %ecx,X86_VENDOR_ID+8       # last 4 chars
316
317         orl %eax,%eax                   # do we have processor info as well?
318         je is486
319
320         movl $1,%eax            # Use the CPUID instruction to get CPU type
321         cpuid
322         movb %al,%cl            # save reg for future use
323         andb $0x0f,%ah          # mask processor family
324         movb %ah,X86
325         andb $0xf0,%al          # mask model
326         shrb $4,%al
327         movb %al,X86_MODEL
328         andb $0x0f,%cl          # mask mask revision
329         movb %cl,X86_MASK
330         movl %edx,X86_CAPABILITY
331
332 is486:  movl $0x50022,%ecx      # set AM, WP, NE and MP
333         jmp 2f
334
335 is386:  movl $2,%ecx            # set MP
336 2:      movl %cr0,%eax
337         andl $0x80000011,%eax   # Save PG,PE,ET
338         orl %ecx,%eax
339         movl %eax,%cr0
340
341         call check_x87
342         lgdt early_gdt_descr
343         lidt idt_descr
344         ljmp $(__KERNEL_CS),$1f
345 1:      movl $(__KERNEL_DS),%eax        # reload all the segment registers
346         movl %eax,%ss                   # after changing gdt.
347         movl %eax,%fs                   # gets reset once there's real percpu
348
349         movl $(__USER_DS),%eax          # DS/ES contains default USER segment
350         movl %eax,%ds
351         movl %eax,%es
352
353         xorl %eax,%eax                  # Clear GS and LDT
354         movl %eax,%gs
355         lldt %ax
356
357         cld                     # gcc2 wants the direction flag cleared at all times
358         pushl $0                # fake return address for unwinder
359 #ifdef CONFIG_SMP
360         movb ready, %cl
361         movb $1, ready
362         cmpb $0,%cl             # the first CPU calls start_kernel
363         je   1f
364         movl $(__KERNEL_PERCPU), %eax
365         movl %eax,%fs           # set this cpu's percpu
366         jmp initialize_secondary # all other CPUs call initialize_secondary
367 1:
368 #endif /* CONFIG_SMP */
369         jmp start_kernel
370
371 /*
372  * We depend on ET to be correct. This checks for 287/387.
373  */
374 check_x87:
375         movb $0,X86_HARD_MATH
376         clts
377         fninit
378         fstsw %ax
379         cmpb $0,%al
380         je 1f
381         movl %cr0,%eax          /* no coprocessor: have to set bits */
382         xorl $4,%eax            /* set EM */
383         movl %eax,%cr0
384         ret
385         ALIGN
386 1:      movb $1,X86_HARD_MATH
387         .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
388         ret
389
390 /*
391  *  setup_idt
392  *
393  *  sets up a idt with 256 entries pointing to
394  *  ignore_int, interrupt gates. It doesn't actually load
395  *  idt - that can be done only after paging has been enabled
396  *  and the kernel moved to PAGE_OFFSET. Interrupts
397  *  are enabled elsewhere, when we can be relatively
398  *  sure everything is ok.
399  *
400  *  Warning: %esi is live across this function.
401  */
402 setup_idt:
403         lea ignore_int,%edx
404         movl $(__KERNEL_CS << 16),%eax
405         movw %dx,%ax            /* selector = 0x0010 = cs */
406         movw $0x8E00,%dx        /* interrupt gate - dpl=0, present */
407
408         lea idt_table,%edi
409         mov $256,%ecx
410 rp_sidt:
411         movl %eax,(%edi)
412         movl %edx,4(%edi)
413         addl $8,%edi
414         dec %ecx
415         jne rp_sidt
416
417 .macro  set_early_handler handler,trapno
418         lea \handler,%edx
419         movl $(__KERNEL_CS << 16),%eax
420         movw %dx,%ax
421         movw $0x8E00,%dx        /* interrupt gate - dpl=0, present */
422         lea idt_table,%edi
423         movl %eax,8*\trapno(%edi)
424         movl %edx,8*\trapno+4(%edi)
425 .endm
426
427         set_early_handler handler=early_divide_err,trapno=0
428         set_early_handler handler=early_illegal_opcode,trapno=6
429         set_early_handler handler=early_protection_fault,trapno=13
430         set_early_handler handler=early_page_fault,trapno=14
431
432         ret
433
434 early_divide_err:
435         xor %edx,%edx
436         pushl $0        /* fake errcode */
437         jmp early_fault
438
439 early_illegal_opcode:
440         movl $6,%edx
441         pushl $0        /* fake errcode */
442         jmp early_fault
443
444 early_protection_fault:
445         movl $13,%edx
446         jmp early_fault
447
448 early_page_fault:
449         movl $14,%edx
450         jmp early_fault
451
452 early_fault:
453         cld
454 #ifdef CONFIG_PRINTK
455         pusha
456         movl $(__KERNEL_DS),%eax
457         movl %eax,%ds
458         movl %eax,%es
459         cmpl $2,early_recursion_flag
460         je hlt_loop
461         incl early_recursion_flag
462         movl %cr2,%eax
463         pushl %eax
464         pushl %edx              /* trapno */
465         pushl $fault_msg
466 #ifdef CONFIG_EARLY_PRINTK
467         call early_printk
468 #else
469         call printk
470 #endif
471 #endif
472 hlt_loop:
473         hlt
474         jmp hlt_loop
475
476 /* This is the default interrupt "handler" :-) */
477         ALIGN
478 ignore_int:
479         cld
480 #ifdef CONFIG_PRINTK
481         pushl %eax
482         pushl %ecx
483         pushl %edx
484         pushl %es
485         pushl %ds
486         movl $(__KERNEL_DS),%eax
487         movl %eax,%ds
488         movl %eax,%es
489         cmpl $2,early_recursion_flag
490         je hlt_loop
491         incl early_recursion_flag
492         pushl 16(%esp)
493         pushl 24(%esp)
494         pushl 32(%esp)
495         pushl 40(%esp)
496         pushl $int_msg
497 #ifdef CONFIG_EARLY_PRINTK
498         call early_printk
499 #else
500         call printk
501 #endif
502         addl $(5*4),%esp
503         popl %ds
504         popl %es
505         popl %edx
506         popl %ecx
507         popl %eax
508 #endif
509         iret
510
511 .section .text
512 /*
513  * Real beginning of normal "text" segment
514  */
515 ENTRY(stext)
516 ENTRY(_stext)
517
518 /*
519  * BSS section
520  */
521 .section ".bss.page_aligned","wa"
522         .align PAGE_SIZE_asm
523 ENTRY(swapper_pg_dir)
524         .fill 1024,4,0
525 ENTRY(swapper_pg_pmd)
526         .fill 1024,4,0
527 ENTRY(empty_zero_page)
528         .fill 4096,1,0
529
530 /*
531  * This starts the data section.
532  */
533 .data
534 ENTRY(stack_start)
535         .long init_thread_union+THREAD_SIZE
536         .long __BOOT_DS
537
538 ready:  .byte 0
539
540 early_recursion_flag:
541         .long 0
542
543 int_msg:
544         .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
545
546 fault_msg:
547         .ascii                                                          \
548 /* fault info: */       "BUG: Int %d: CR2 %p\n"                         \
549 /* pusha regs: */       "     EDI %p  ESI %p  EBP %p  ESP %p\n"         \
550                         "     EBX %p  EDX %p  ECX %p  EAX %p\n"         \
551 /* fault frame: */      "     err %p  EIP %p   CS %p  flg %p\n"         \
552                                                                         \
553                         "Stack: %p %p %p %p %p %p %p %p\n"              \
554                         "       %p %p %p %p %p %p %p %p\n"              \
555                         "       %p %p %p %p %p %p %p %p\n"
556
557 #include "../../x86/xen/xen-head.S"
558
559 /*
560  * The IDT and GDT 'descriptors' are a strange 48-bit object
561  * only used by the lidt and lgdt instructions. They are not
562  * like usual segment descriptors - they consist of a 16-bit
563  * segment size, and 32-bit linear address value:
564  */
565
566 .globl boot_gdt_descr
567 .globl idt_descr
568
569         ALIGN
570 # early boot GDT descriptor (must use 1:1 address mapping)
571         .word 0                         # 32 bit align gdt_desc.address
572 boot_gdt_descr:
573         .word __BOOT_DS+7
574         .long boot_gdt - __PAGE_OFFSET
575
576         .word 0                         # 32-bit align idt_desc.address
577 idt_descr:
578         .word IDT_ENTRIES*8-1           # idt contains 256 entries
579         .long idt_table
580
581 # boot GDT descriptor (later on used by CPU#0):
582         .word 0                         # 32 bit align gdt_desc.address
583 ENTRY(early_gdt_descr)
584         .word GDT_ENTRIES*8-1
585         .long per_cpu__gdt_page         /* Overwritten for secondary CPUs */
586
587 /*
588  * The boot_gdt must mirror the equivalent in setup.S and is
589  * used only for booting.
590  */
591         .align L1_CACHE_BYTES
592 ENTRY(boot_gdt)
593         .fill GDT_ENTRY_BOOT_CS,8,0
594         .quad 0x00cf9a000000ffff        /* kernel 4GB code at 0x00000000 */
595         .quad 0x00cf92000000ffff        /* kernel 4GB data at 0x00000000 */