v2.4.2.7 -> v2.4.2.8
[linux-flexiantxendom0-3.2.10.git] / arch / i386 / kernel / head.S
1 /*
2  *  linux/arch/i386/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/config.h>
12 #include <linux/threads.h>
13 #include <linux/linkage.h>
14 #include <asm/segment.h>
15 #include <asm/page.h>
16 #include <asm/pgtable.h>
17 #include <asm/desc.h>
18
19 #define OLD_CL_MAGIC_ADDR       0x90020
20 #define OLD_CL_MAGIC            0xA33F
21 #define OLD_CL_BASE_ADDR        0x90000
22 #define OLD_CL_OFFSET           0x90022
23 #define NEW_CL_POINTER          0x228   /* Relative to real mode data */
24
25 /*
26  * References to members of the boot_cpu_data structure.
27  */
28
29 #define CPU_PARAMS      SYMBOL_NAME(boot_cpu_data)
30 #define X86             CPU_PARAMS+0
31 #define X86_VENDOR      CPU_PARAMS+1
32 #define X86_MODEL       CPU_PARAMS+2
33 #define X86_MASK        CPU_PARAMS+3
34 #define X86_HARD_MATH   CPU_PARAMS+6
35 #define X86_CPUID       CPU_PARAMS+8
36 #define X86_CAPABILITY  CPU_PARAMS+12
37 #define X86_VENDOR_ID   CPU_PARAMS+28
38
39 /*
40  * swapper_pg_dir is the main page directory, address 0x00101000
41  *
42  * On entry, %esi points to the real-mode code as a 32-bit pointer.
43  */
44 ENTRY(stext)
45 ENTRY(_stext)
46 startup_32:
47 /*
48  * Set segments to known values
49  */
50         cld
51         movl $(__KERNEL_DS),%eax
52         movl %eax,%ds
53         movl %eax,%es
54         movl %eax,%fs
55         movl %eax,%gs
56 #ifdef CONFIG_SMP
57         orw %bx,%bx
58         jz 1f
59
60 /*
61  *      New page tables may be in 4Mbyte page mode and may
62  *      be using the global pages. 
63  *
64  *      NOTE! If we are on a 486 we may have no cr4 at all!
65  *      So we do not try to touch it unless we really have
66  *      some bits in it to set.  This won't work if the BSP
67  *      implements cr4 but this AP does not -- very unlikely
68  *      but be warned!  The same applies to the pse feature
69  *      if not equally supported. --macro
70  *
71  *      NOTE! We have to correct for the fact that we're
72  *      not yet offset PAGE_OFFSET..
73  */
74 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
75         cmpl $0,cr4_bits
76         je 3f
77         movl %cr4,%eax          # Turn on paging options (PSE,PAE,..)
78         orl cr4_bits,%eax
79         movl %eax,%cr4
80         jmp 3f
81 1:
82 #endif
83 /*
84  * Initialize page tables
85  */
86         movl $pg0-__PAGE_OFFSET,%edi /* initialize page tables */
87         movl $007,%eax          /* "007" doesn't mean with right to kill, but
88                                    PRESENT+RW+USER */
89 2:      stosl
90         add $0x1000,%eax
91         cmp $empty_zero_page-__PAGE_OFFSET,%edi
92         jne 2b
93
94 /*
95  * Enable paging
96  */
97 3:
98         movl $swapper_pg_dir-__PAGE_OFFSET,%eax
99         movl %eax,%cr3          /* set the page table pointer.. */
100         movl %cr0,%eax
101         orl $0x80000000,%eax
102         movl %eax,%cr0          /* ..and set paging (PG) bit */
103         jmp 1f                  /* flush the prefetch-queue */
104 1:
105         movl $1f,%eax
106         jmp *%eax               /* make sure eip is relocated */
107 1:
108         /* Set up the stack pointer */
109         lss stack_start,%esp
110
111 #ifdef CONFIG_SMP
112         orw  %bx,%bx
113         jz  1f                          /* Initial CPU cleans BSS */
114         pushl $0
115         popfl
116         jmp checkCPUtype
117 1:
118 #endif CONFIG_SMP
119
120 /*
121  * Clear BSS first so that there are no surprises...
122  * No need to cld as DF is already clear from cld above...
123  */
124         xorl %eax,%eax
125         movl $ SYMBOL_NAME(__bss_start),%edi
126         movl $ SYMBOL_NAME(_end),%ecx
127         subl %edi,%ecx
128         rep
129         stosb
130
131 /*
132  * start system 32-bit setup. We need to re-do some of the things done
133  * in 16-bit mode for the "real" operations.
134  */
135         call setup_idt
136 /*
137  * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
138  * confuse the debugger if this code is traced.
139  * XXX - best to initialize before switching to protected mode.
140  */
141         pushl $0
142         popfl
143 /*
144  * Copy bootup parameters out of the way. First 2kB of
145  * _empty_zero_page is for boot parameters, second 2kB
146  * is for the command line.
147  *
148  * Note: %esi still has the pointer to the real-mode data.
149  */
150         movl $ SYMBOL_NAME(empty_zero_page),%edi
151         movl $512,%ecx
152         cld
153         rep
154         movsl
155         xorl %eax,%eax
156         movl $512,%ecx
157         rep
158         stosl
159         movl SYMBOL_NAME(empty_zero_page)+NEW_CL_POINTER,%esi
160         andl %esi,%esi
161         jnz 2f                  # New command line protocol
162         cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
163         jne 1f
164         movzwl OLD_CL_OFFSET,%esi
165         addl $(OLD_CL_BASE_ADDR),%esi
166 2:
167         movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
168         movl $512,%ecx
169         rep
170         movsl
171 1:
172 #ifdef CONFIG_SMP
173 checkCPUtype:
174 #endif
175
176         movl $-1,X86_CPUID              #  -1 for no CPUID initially
177
178 /* check if it is 486 or 386. */
179 /*
180  * XXX - this does a lot of unnecessary setup.  Alignment checks don't
181  * apply at our cpl of 0 and the stack ought to be aligned already, and
182  * we don't need to preserve eflags.
183  */
184
185         movl $3,X86             # at least 386
186         pushfl                  # push EFLAGS
187         popl %eax               # get EFLAGS
188         movl %eax,%ecx          # save original EFLAGS
189         xorl $0x40000,%eax      # flip AC bit in EFLAGS
190         pushl %eax              # copy to EFLAGS
191         popfl                   # set EFLAGS
192         pushfl                  # get new EFLAGS
193         popl %eax               # put it in eax
194         xorl %ecx,%eax          # change in flags
195         andl $0x40000,%eax      # check if AC bit changed
196         je is386
197
198         movl $4,X86             # at least 486
199         movl %ecx,%eax
200         xorl $0x200000,%eax     # check ID flag
201         pushl %eax
202         popfl                   # if we are on a straight 486DX, SX, or
203         pushfl                  # 487SX we can't change it
204         popl %eax
205         xorl %ecx,%eax
206         pushl %ecx              # restore original EFLAGS
207         popfl
208         andl $0x200000,%eax
209         je is486
210
211         /* get vendor info */
212         xorl %eax,%eax                  # call CPUID with 0 -> return vendor ID
213         cpuid
214         movl %eax,X86_CPUID             # save CPUID level
215         movl %ebx,X86_VENDOR_ID         # lo 4 chars
216         movl %edx,X86_VENDOR_ID+4       # next 4 chars
217         movl %ecx,X86_VENDOR_ID+8       # last 4 chars
218
219         orl %eax,%eax                   # do we have processor info as well?
220         je is486
221
222         movl $1,%eax            # Use the CPUID instruction to get CPU type
223         cpuid
224         movb %al,%cl            # save reg for future use
225         andb $0x0f,%ah          # mask processor family
226         movb %ah,X86
227         andb $0xf0,%al          # mask model
228         shrb $4,%al
229         movb %al,X86_MODEL
230         andb $0x0f,%cl          # mask mask revision
231         movb %cl,X86_MASK
232         movl %edx,X86_CAPABILITY
233
234 is486:
235         movl %cr0,%eax          # 486 or better
236         andl $0x80000011,%eax   # Save PG,PE,ET
237         orl $0x50022,%eax       # set AM, WP, NE and MP
238         jmp 2f
239
240 is386:  pushl %ecx              # restore original EFLAGS
241         popfl
242         movl %cr0,%eax          # 386
243         andl $0x80000011,%eax   # Save PG,PE,ET
244         orl $2,%eax             # set MP
245 2:      movl %eax,%cr0
246         call check_x87
247 #ifdef CONFIG_SMP
248         incb ready
249 #endif
250         lgdt gdt_descr
251         lidt idt_descr
252         ljmp $(__KERNEL_CS),$1f
253 1:      movl $(__KERNEL_DS),%eax        # reload all the segment registers
254         movl %eax,%ds           # after changing gdt.
255         movl %eax,%es
256         movl %eax,%fs
257         movl %eax,%gs
258 #ifdef CONFIG_SMP
259         movl $(__KERNEL_DS), %eax
260         movl %eax,%ss           # Reload the stack pointer (segment only)
261 #else
262         lss stack_start,%esp    # Load processor stack
263 #endif
264         xorl %eax,%eax
265         lldt %ax
266         cld                     # gcc2 wants the direction flag cleared at all times
267 #ifdef CONFIG_SMP
268         movb ready, %cl 
269         cmpb $1,%cl
270         je 1f                   # the first CPU calls start_kernel
271                                 # all other CPUs call initialize_secondary
272         call SYMBOL_NAME(initialize_secondary)
273         jmp L6
274 1:
275 #endif
276         call SYMBOL_NAME(start_kernel)
277 L6:
278         jmp L6                  # main should never return here, but
279                                 # just in case, we know what happens.
280
281 #ifdef CONFIG_SMP
282 ready:  .byte 0
283 #endif
284
285 /*
286  * We depend on ET to be correct. This checks for 287/387.
287  */
288 check_x87:
289         movb $0,X86_HARD_MATH
290         clts
291         fninit
292         fstsw %ax
293         cmpb $0,%al
294         je 1f
295         movl %cr0,%eax          /* no coprocessor: have to set bits */
296         xorl $4,%eax            /* set EM */
297         movl %eax,%cr0
298         ret
299         ALIGN
300 1:      movb $1,X86_HARD_MATH
301         .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
302         ret
303
304 /*
305  *  setup_idt
306  *
307  *  sets up a idt with 256 entries pointing to
308  *  ignore_int, interrupt gates. It doesn't actually load
309  *  idt - that can be done only after paging has been enabled
310  *  and the kernel moved to PAGE_OFFSET. Interrupts
311  *  are enabled elsewhere, when we can be relatively
312  *  sure everything is ok.
313  */
314 setup_idt:
315         lea ignore_int,%edx
316         movl $(__KERNEL_CS << 16),%eax
317         movw %dx,%ax            /* selector = 0x0010 = cs */
318         movw $0x8E00,%dx        /* interrupt gate - dpl=0, present */
319
320         lea SYMBOL_NAME(idt_table),%edi
321         mov $256,%ecx
322 rp_sidt:
323         movl %eax,(%edi)
324         movl %edx,4(%edi)
325         addl $8,%edi
326         dec %ecx
327         jne rp_sidt
328         ret
329
330 ENTRY(stack_start)
331         .long SYMBOL_NAME(init_task_union)+8192
332         .long __KERNEL_DS
333
334 /* This is the default interrupt "handler" :-) */
335 int_msg:
336         .asciz "Unknown interrupt\n"
337         ALIGN
338 ignore_int:
339         cld
340         pushl %eax
341         pushl %ecx
342         pushl %edx
343         pushl %es
344         pushl %ds
345         movl $(__KERNEL_DS),%eax
346         movl %eax,%ds
347         movl %eax,%es
348         pushl $int_msg
349         call SYMBOL_NAME(printk)
350         popl %eax
351         popl %ds
352         popl %es
353         popl %edx
354         popl %ecx
355         popl %eax
356         iret
357
358 /*
359  * The interrupt descriptor table has room for 256 idt's,
360  * the global descriptor table is dependent on the number
361  * of tasks we can have..
362  */
363 #define IDT_ENTRIES     256
364 #define GDT_ENTRIES     (__TSS(NR_CPUS))
365
366
367 .globl SYMBOL_NAME(idt)
368 .globl SYMBOL_NAME(gdt)
369
370         ALIGN
371         .word 0
372 idt_descr:
373         .word IDT_ENTRIES*8-1           # idt contains 256 entries
374 SYMBOL_NAME(idt):
375         .long SYMBOL_NAME(idt_table)
376
377         .word 0
378 gdt_descr:
379         .word GDT_ENTRIES*8-1
380 SYMBOL_NAME(gdt):
381         .long SYMBOL_NAME(gdt_table)
382
383 /*
384  * This is initialized to create an identity-mapping at 0-8M (for bootup
385  * purposes) and another mapping of the 0-8M area at virtual address
386  * PAGE_OFFSET.
387  */
388 .org 0x1000
389 ENTRY(swapper_pg_dir)
390         .long 0x00102007
391         .long 0x00103007
392         .fill BOOT_USER_PGD_PTRS-2,4,0
393         /* default: 766 entries */
394         .long 0x00102007
395         .long 0x00103007
396         /* default: 254 entries */
397         .fill BOOT_KERNEL_PGD_PTRS-2,4,0
398
399 /*
400  * The page tables are initialized to only 8MB here - the final page
401  * tables are set up later depending on memory size.
402  */
403 .org 0x2000
404 ENTRY(pg0)
405
406 .org 0x3000
407 ENTRY(pg1)
408
409 /*
410  * empty_zero_page must immediately follow the page tables ! (The
411  * initialization loop counts until empty_zero_page)
412  */
413
414 .org 0x4000
415 ENTRY(empty_zero_page)
416
417 .org 0x5000
418
419 /*
420  * This starts the data section. Note that the above is all
421  * in the text section because it has alignment requirements
422  * that we cannot fulfill any other way.
423  */
424 .data
425
426 ALIGN
427 /*
428  * This contains typically 140 quadwords, depending on NR_CPUS.
429  *
430  * NOTE! Make sure the gdt descriptor in head.S matches this if you
431  * change anything.
432  */
433 ENTRY(gdt_table)
434         .quad 0x0000000000000000        /* NULL descriptor */
435         .quad 0x0000000000000000        /* not used */
436         .quad 0x00cf9a000000ffff        /* 0x10 kernel 4GB code at 0x00000000 */
437         .quad 0x00cf92000000ffff        /* 0x18 kernel 4GB data at 0x00000000 */
438         .quad 0x00cffa000000ffff        /* 0x23 user   4GB code at 0x00000000 */
439         .quad 0x00cff2000000ffff        /* 0x2b user   4GB data at 0x00000000 */
440         .quad 0x0000000000000000        /* not used */
441         .quad 0x0000000000000000        /* not used */
442         /*
443          * The APM segments have byte granularity and their bases
444          * and limits are set at run time.
445          */
446         .quad 0x0040920000000000        /* 0x40 APM set up for bad BIOS's */
447         .quad 0x00409a0000000000        /* 0x48 APM CS    code */
448         .quad 0x00009a0000000000        /* 0x50 APM CS 16 code (16 bit) */
449         .quad 0x0040920000000000        /* 0x58 APM DS    data */
450         .fill NR_CPUS*4,8,0             /* space for TSS's and LDT's */
451                 
452 /*
453  * This is to aid debugging, the various locking macros will be putting
454  * code fragments here.  When an oops occurs we'd rather know that it's
455  * inside the .text.lock section rather than as some offset from whatever
456  * function happens to be last in the .text segment.
457  */
458 .section .text.lock
459 ENTRY(stext_lock)