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