head_32.S 17.1 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
/*
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Enhanced CPU detection and feature setting code by Mike Jagdis
 *  and Martin Mares, November 1997.
 */

.text
#include <linux/threads.h>
11
#include <linux/init.h>
Linus Torvalds's avatar
Linus Torvalds committed
12
13
#include <linux/linkage.h>
#include <asm/segment.h>
14
15
#include <asm/page_types.h>
#include <asm/pgtable_types.h>
Linus Torvalds's avatar
Linus Torvalds committed
16
17
#include <asm/cache.h>
#include <asm/thread_info.h>
18
#include <asm/asm-offsets.h>
Linus Torvalds's avatar
Linus Torvalds committed
19
#include <asm/setup.h>
20
#include <asm/processor-flags.h>
21
22
#include <asm/msr-index.h>
#include <asm/cpufeature.h>
23
#include <asm/percpu.h>
24
25
26

/* Physical address */
#define pa(X) ((X) - __PAGE_OFFSET)
Linus Torvalds's avatar
Linus Torvalds committed
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

/*
 * References to members of the new_cpu_data structure.
 */

#define X86		new_cpu_data+CPUINFO_x86
#define X86_VENDOR	new_cpu_data+CPUINFO_x86_vendor
#define X86_MODEL	new_cpu_data+CPUINFO_x86_model
#define X86_MASK	new_cpu_data+CPUINFO_x86_mask
#define X86_HARD_MATH	new_cpu_data+CPUINFO_hard_math
#define X86_CPUID	new_cpu_data+CPUINFO_cpuid_level
#define X86_CAPABILITY	new_cpu_data+CPUINFO_x86_capability
#define X86_VENDOR_ID	new_cpu_data+CPUINFO_x86_vendor_id

/*
42
43
 * This is how much memory in addition to the memory covered up to
 * and including _end we need mapped initially.
44
 * We need:
45
46
 *     (KERNEL_IMAGE_SIZE/4096) / 1024 pages (worst case, non PAE)
 *     (KERNEL_IMAGE_SIZE/4096) / 512 + 4 pages (worst case for PAE)
Linus Torvalds's avatar
Linus Torvalds committed
47
48
49
50
51
 *
 * Modulo rounding, each megabyte assigned here requires a kilobyte of
 * memory, which is currently unreclaimed.
 *
 * This should be a multiple of a page.
52
53
54
 *
 * KERNEL_IMAGE_SIZE should be greater than pa(_end)
 * and small than max_low_pfn, otherwise will waste some page table entries
Linus Torvalds's avatar
Linus Torvalds committed
55
56
 */

57
#if PTRS_PER_PMD > 1
58
#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
59
#else
60
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
61
62
#endif

63
/* Enough space to fit pagetables for the low memory linear map */
64
65
MAPPING_BEYOND_END = \
	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
66
67
68
69
70
71
72
73

/*
 * Worst-case size of the kernel mapping we need to make:
 * the worst-case size of the kernel itself, plus the extra we need
 * to map for the linear map.
 */
KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT

74
INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
75
RESERVE_BRK(pagetables, INIT_MAP_SIZE)
76

Linus Torvalds's avatar
Linus Torvalds committed
77
78
79
80
81
82
83
/*
 * 32-bit kernel entrypoint; only used by the boot CPU.  On entry,
 * %esi points to the real-mode code as a 32-bit pointer.
 * CS and DS must be 4 GB flat segments, but we don't depend on
 * any particular GDT layout, because we load our own as soon as we
 * can.
 */
84
__HEAD
Linus Torvalds's avatar
Linus Torvalds committed
85
ENTRY(startup_32)
Rusty Russell's avatar
Rusty Russell committed
86
87
88
89
	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
		us to not reload segments */
	testb $(1<<6), BP_loadflags(%esi)
	jnz 2f
Linus Torvalds's avatar
Linus Torvalds committed
90
91
92
93

/*
 * Set segments to known values.
 */
94
	lgdt pa(boot_gdt_descr)
Linus Torvalds's avatar
Linus Torvalds committed
95
96
97
98
99
	movl $(__BOOT_DS),%eax
	movl %eax,%ds
	movl %eax,%es
	movl %eax,%fs
	movl %eax,%gs
Rusty Russell's avatar
Rusty Russell committed
100
2:
Linus Torvalds's avatar
Linus Torvalds committed
101
102
103
104

/*
 * Clear BSS first so that there are no surprises...
 */
Rusty Russell's avatar
Rusty Russell committed
105
	cld
Linus Torvalds's avatar
Linus Torvalds committed
106
	xorl %eax,%eax
107
108
	movl $pa(__bss_start),%edi
	movl $pa(__bss_stop),%ecx
Linus Torvalds's avatar
Linus Torvalds committed
109
110
111
	subl %edi,%ecx
	shrl $2,%ecx
	rep ; stosl
112
113
114
115
116
117
118
119
/*
 * Copy bootup parameters out of the way.
 * Note: %esi still has the pointer to the real-mode data.
 * With the kexec as boot loader, parameter segment might be loaded beyond
 * kernel image and might not even be addressable by early boot page tables.
 * (kexec on panic case). Hence copy out the parameters before initializing
 * page tables.
 */
120
	movl $pa(boot_params),%edi
121
122
123
124
	movl $(PARAM_SIZE/4),%ecx
	cld
	rep
	movsl
125
	movl pa(boot_params) + NEW_CL_POINTER,%esi
126
	andl %esi,%esi
127
	jz 1f			# No comand line
128
	movl $pa(boot_command_line),%edi
129
130
131
132
	movl $(COMMAND_LINE_SIZE/4),%ecx
	rep
	movsl
1:
Linus Torvalds's avatar
Linus Torvalds committed
133

134
135
136
137
138
139
#ifdef CONFIG_OLPC_OPENFIRMWARE
	/* save OFW's pgdir table for later use when calling into OFW */
	movl %cr3, %eax
	movl %eax, pa(olpc_ofw_pgd)
#endif

Rusty Russell's avatar
Rusty Russell committed
140
#ifdef CONFIG_PARAVIRT
141
142
	/* This is can only trip for a broken bootloader... */
	cmpw $0x207, pa(boot_params + BP_version)
Rusty Russell's avatar
Rusty Russell committed
143
144
145
146
	jb default_entry

	/* Paravirt-compatible boot parameters.  Look to see what architecture
		we're booting under. */
147
	movl pa(boot_params + BP_hardware_subarch), %eax
Rusty Russell's avatar
Rusty Russell committed
148
149
150
	cmpl $num_subarch_entries, %eax
	jae bad_subarch

151
	movl pa(subarch_entries)(,%eax,4), %eax
Rusty Russell's avatar
Rusty Russell committed
152
153
154
155
156
157
158
159
160
	subl $__PAGE_OFFSET, %eax
	jmp *%eax

bad_subarch:
WEAK(lguest_entry)
WEAK(xen_entry)
	/* Unknown implementation; there's really
	   nothing we can do at this point. */
	ud2a
161
162
163

	__INITDATA

Rusty Russell's avatar
Rusty Russell committed
164
165
166
167
subarch_entries:
	.long default_entry		/* normal x86/PC */
	.long lguest_entry		/* lguest hypervisor */
	.long xen_entry			/* Xen hypervisor */
168
	.long default_entry		/* Moorestown MID */
Rusty Russell's avatar
Rusty Russell committed
169
170
171
172
num_subarch_entries = (. - subarch_entries) / 4
.previous
#endif /* CONFIG_PARAVIRT */

Linus Torvalds's avatar
Linus Torvalds committed
173
174
/*
 * Initialize page tables.  This creates a PDE and a set of page
175
 * tables, which are located immediately beyond __brk_base.  The variable
176
 * _brk_end is set up to point to the first "safe" location.
Linus Torvalds's avatar
Linus Torvalds committed
177
 * Mappings are created both at virtual address 0 (identity mapping)
178
 * and PAGE_OFFSET for up to _end.
Linus Torvalds's avatar
Linus Torvalds committed
179
 *
180
 * Note that the stack is not yet set up!
Linus Torvalds's avatar
Linus Torvalds committed
181
 */
Rusty Russell's avatar
Rusty Russell committed
182
default_entry:
183
184
185
#ifdef CONFIG_X86_PAE

	/*
186
187
188
189
	 * In PAE mode initial_page_table is statically defined to contain
	 * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
	 * entries). The identity mapping is handled by pointing two PGD entries
	 * to the first kernel PMD.
190
	 *
191
	 * Note the upper half of each PMD or PTE are always zero at this stage.
192
193
	 */

Joe Korty's avatar
Joe Korty committed
194
#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
195
196
197

	xorl %ebx,%ebx				/* %ebx is kept at zero */

198
	movl $pa(__brk_base), %edi
199
	movl $pa(initial_pg_pmd), %edx
200
	movl $PTE_IDENT_ATTR, %eax
201
10:
202
	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PMD entry */
203
204
205
206
207
208
209
210
211
212
213
214
215
	movl %ecx,(%edx)			/* Store PMD entry */
						/* Upper half already zero */
	addl $8,%edx
	movl $512,%ecx
11:
	stosl
	xchgl %eax,%ebx
	stosl
	xchgl %eax,%ebx
	addl $0x1000,%eax
	loop 11b

	/*
216
	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
217
	 */
218
	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
219
220
221
	cmpl %ebp,%eax
	jb 10b
1:
222
223
	addl $__PAGE_OFFSET, %edi
	movl %edi, pa(_brk_end)
224
225
	shrl $12, %eax
	movl %eax, pa(max_pfn_mapped)
226
227

	/* Do early initialization of the fixmap area */
228
229
	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
230
231
232
233
#else	/* Not PAE */

page_pde_offset = (__PAGE_OFFSET >> 20);

234
	movl $pa(__brk_base), %edi
235
	movl $pa(initial_page_table), %edx
236
	movl $PTE_IDENT_ATTR, %eax
Linus Torvalds's avatar
Linus Torvalds committed
237
10:
238
	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PDE entry */
Linus Torvalds's avatar
Linus Torvalds committed
239
240
241
242
243
244
245
246
	movl %ecx,(%edx)			/* Store identity PDE entry */
	movl %ecx,page_pde_offset(%edx)		/* Store kernel PDE entry */
	addl $4,%edx
	movl $1024, %ecx
11:
	stosl
	addl $0x1000,%eax
	loop 11b
247
	/*
248
	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
249
	 */
250
	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
Linus Torvalds's avatar
Linus Torvalds committed
251
252
	cmpl %ebp,%eax
	jb 10b
253
254
	addl $__PAGE_OFFSET, %edi
	movl %edi, pa(_brk_end)
255
256
	shrl $12, %eax
	movl %eax, pa(max_pfn_mapped)
257

258
	/* Do early initialization of the fixmap area */
259
260
	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
	movl %eax,pa(initial_page_table+0xffc)
261
#endif
Linus Torvalds's avatar
Linus Torvalds committed
262
263
264
265
	jmp 3f
/*
 * Non-boot CPU entry point; entered from trampoline.S
 * We can't lgdt here, because lgdt itself uses a data segment, but
266
 * we know the trampoline has already loaded the boot_gdt for us.
267
268
269
 *
 * If cpu hotplug is not supported then this code can go in init section
 * which will be freed later
Linus Torvalds's avatar
Linus Torvalds committed
270
 */
271

272
__CPUINIT
273
274

#ifdef CONFIG_SMP
Linus Torvalds's avatar
Linus Torvalds committed
275
276
277
278
279
280
281
ENTRY(startup_32_smp)
	cld
	movl $(__BOOT_DS),%eax
	movl %eax,%ds
	movl %eax,%es
	movl %eax,%fs
	movl %eax,%gs
282
283
#endif /* CONFIG_SMP */
3:
Linus Torvalds's avatar
Linus Torvalds committed
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

/*
 *	New page tables may be in 4Mbyte page mode and may
 *	be using the global pages. 
 *
 *	NOTE! If we are on a 486 we may have no cr4 at all!
 *	So we do not try to touch it unless we really have
 *	some bits in it to set.  This won't work if the BSP
 *	implements cr4 but this AP does not -- very unlikely
 *	but be warned!  The same applies to the pse feature
 *	if not equally supported. --macro
 *
 *	NOTE! We have to correct for the fact that we're
 *	not yet offset PAGE_OFFSET..
 */
299
#define cr4_bits pa(mmu_cr4_features)
Linus Torvalds's avatar
Linus Torvalds committed
300
301
302
303
304
305
306
	movl cr4_bits,%edx
	andl %edx,%edx
	jz 6f
	movl %cr4,%eax		# Turn on paging options (PSE,PAE,..)
	orl %edx,%eax
	movl %eax,%cr4

307
308
	testb $X86_CR4_PAE, %al		# check if PAE is enabled
	jz 6f
Linus Torvalds's avatar
Linus Torvalds committed
309
310
311
312

	/* Check if extended functions are implemented */
	movl $0x80000000, %eax
	cpuid
313
314
315
316
	/* Value must be in the range 0x80000001 to 0x8000ffff */
	subl $0x80000001, %eax
	cmpl $(0x8000ffff-0x80000001), %eax
	ja 6f
Linus Torvalds's avatar
Linus Torvalds committed
317
318
319
	mov $0x80000001, %eax
	cpuid
	/* Execute Disable bit supported? */
320
	btl $(X86_FEATURE_NX & 31), %edx
Linus Torvalds's avatar
Linus Torvalds committed
321
322
323
	jnc 6f

	/* Setup EFER (Extended Feature Enable Register) */
324
	movl $MSR_EFER, %ecx
Linus Torvalds's avatar
Linus Torvalds committed
325
326
	rdmsr

327
	btsl $_EFER_NX, %eax
Linus Torvalds's avatar
Linus Torvalds committed
328
329
330
331
332
333
334
335
	/* Make changes effective */
	wrmsr

6:

/*
 * Enable paging
 */
336
	movl $pa(initial_page_table), %eax
Linus Torvalds's avatar
Linus Torvalds committed
337
338
	movl %eax,%cr3		/* set the page table pointer.. */
	movl %cr0,%eax
339
	orl  $X86_CR0_PG,%eax
Linus Torvalds's avatar
Linus Torvalds committed
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
	movl %eax,%cr0		/* ..and set paging (PG) bit */
	ljmp $__BOOT_CS,$1f	/* Clear prefetch and normalize %eip */
1:
	/* Set up the stack pointer */
	lss stack_start,%esp

/*
 * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
 * confuse the debugger if this code is traced.
 * XXX - best to initialize before switching to protected mode.
 */
	pushl $0
	popfl

#ifdef CONFIG_SMP
355
	cmpb $0, ready
Linus Torvalds's avatar
Linus Torvalds committed
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
	jz  1f				/* Initial CPU cleans BSS */
	jmp checkCPUtype
1:
#endif /* CONFIG_SMP */

/*
 * start system 32-bit setup. We need to re-do some of the things done
 * in 16-bit mode for the "real" operations.
 */
	call setup_idt

checkCPUtype:

	movl $-1,X86_CPUID		#  -1 for no CPUID initially

/* check if it is 486 or 386. */
/*
 * XXX - this does a lot of unnecessary setup.  Alignment checks don't
 * apply at our cpl of 0 and the stack ought to be aligned already, and
 * we don't need to preserve eflags.
 */

	movb $3,X86		# at least 386
	pushfl			# push EFLAGS
	popl %eax		# get EFLAGS
	movl %eax,%ecx		# save original EFLAGS
	xorl $0x240000,%eax	# flip AC and ID bits in EFLAGS
	pushl %eax		# copy to EFLAGS
	popfl			# set EFLAGS
	pushfl			# get new EFLAGS
	popl %eax		# put it in eax
	xorl %ecx,%eax		# change in flags
	pushl %ecx		# restore original EFLAGS
	popfl
	testl $0x40000,%eax	# check if AC bit changed
	je is386

	movb $4,X86		# at least 486
	testl $0x200000,%eax	# check if ID bit changed
	je is486

	/* get vendor info */
	xorl %eax,%eax			# call CPUID with 0 -> return vendor ID
	cpuid
	movl %eax,X86_CPUID		# save CPUID level
	movl %ebx,X86_VENDOR_ID		# lo 4 chars
	movl %edx,X86_VENDOR_ID+4	# next 4 chars
	movl %ecx,X86_VENDOR_ID+8	# last 4 chars

	orl %eax,%eax			# do we have processor info as well?
	je is486

	movl $1,%eax		# Use the CPUID instruction to get CPU type
	cpuid
	movb %al,%cl		# save reg for future use
	andb $0x0f,%ah		# mask processor family
	movb %ah,X86
	andb $0xf0,%al		# mask model
	shrb $4,%al
	movb %al,X86_MODEL
	andb $0x0f,%cl		# mask mask revision
	movb %cl,X86_MASK
	movl %edx,X86_CAPABILITY

is486:	movl $0x50022,%ecx	# set AM, WP, NE and MP
	jmp 2f

is386:	movl $2,%ecx		# set MP
2:	movl %cr0,%eax
	andl $0x80000011,%eax	# Save PG,PE,ET
	orl %ecx,%eax
	movl %eax,%cr0

	call check_x87
430
	lgdt early_gdt_descr
Linus Torvalds's avatar
Linus Torvalds committed
431
432
433
434
435
436
437
438
439
	lidt idt_descr
	ljmp $(__KERNEL_CS),$1f
1:	movl $(__KERNEL_DS),%eax	# reload all the segment registers
	movl %eax,%ss			# after changing gdt.

	movl $(__USER_DS),%eax		# DS/ES contains default USER segment
	movl %eax,%ds
	movl %eax,%es

440
441
442
	movl $(__KERNEL_PERCPU), %eax
	movl %eax,%fs			# set this cpu's percpu

443
444
445
446
447
448
449
#ifdef CONFIG_CC_STACKPROTECTOR
	/*
	 * The linker can't handle this by relocation.  Manually set
	 * base address in stack canary segment descriptor.
	 */
	cmpb $0,ready
	jne 1f
450
451
	movl $gdt_page,%eax
	movl $stack_canary,%ecx
452
453
454
455
456
457
458
	movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
	shrl $16, %ecx
	movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
	movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
1:
#endif
	movl $(__KERNEL_STACK_CANARY),%eax
459
	movl %eax,%gs
460
461

	xorl %eax,%eax			# Clear LDT
Linus Torvalds's avatar
Linus Torvalds committed
462
	lldt %ax
463

Linus Torvalds's avatar
Linus Torvalds committed
464
	cld			# gcc2 wants the direction flag cleared at all times
465
	pushl $0		# fake return address for unwinder
Linus Torvalds's avatar
Linus Torvalds committed
466
#ifdef CONFIG_SMP
467
468
	movb ready, %cl
	movb $1, ready
469
	cmpb $0,%cl		# the first CPU calls start_kernel
470
	je   1f
471
	movl (stack_start), %esp
472
1:
Linus Torvalds's avatar
Linus Torvalds committed
473
#endif /* CONFIG_SMP */
Glauber Costa's avatar
Glauber Costa committed
474
	jmp *(initial_code)
Linus Torvalds's avatar
Linus Torvalds committed
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

/*
 * We depend on ET to be correct. This checks for 287/387.
 */
check_x87:
	movb $0,X86_HARD_MATH
	clts
	fninit
	fstsw %ax
	cmpb $0,%al
	je 1f
	movl %cr0,%eax		/* no coprocessor: have to set bits */
	xorl $4,%eax		/* set EM */
	movl %eax,%cr0
	ret
	ALIGN
1:	movb $1,X86_HARD_MATH
	.byte 0xDB,0xE4		/* fsetpm for 287, ignored by 387 */
	ret

/*
 *  setup_idt
 *
 *  sets up a idt with 256 entries pointing to
 *  ignore_int, interrupt gates. It doesn't actually load
 *  idt - that can be done only after paging has been enabled
 *  and the kernel moved to PAGE_OFFSET. Interrupts
 *  are enabled elsewhere, when we can be relatively
 *  sure everything is ok.
 *
 *  Warning: %esi is live across this function.
 */
setup_idt:
	lea ignore_int,%edx
	movl $(__KERNEL_CS << 16),%eax
	movw %dx,%ax		/* selector = 0x0010 = cs */
	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */

	lea idt_table,%edi
	mov $256,%ecx
rp_sidt:
	movl %eax,(%edi)
	movl %edx,4(%edi)
	addl $8,%edi
	dec %ecx
	jne rp_sidt
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

.macro	set_early_handler handler,trapno
	lea \handler,%edx
	movl $(__KERNEL_CS << 16),%eax
	movw %dx,%ax
	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */
	lea idt_table,%edi
	movl %eax,8*\trapno(%edi)
	movl %edx,8*\trapno+4(%edi)
.endm

	set_early_handler handler=early_divide_err,trapno=0
	set_early_handler handler=early_illegal_opcode,trapno=6
	set_early_handler handler=early_protection_fault,trapno=13
	set_early_handler handler=early_page_fault,trapno=14

Linus Torvalds's avatar
Linus Torvalds committed
537
538
	ret

539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
early_divide_err:
	xor %edx,%edx
	pushl $0	/* fake errcode */
	jmp early_fault

early_illegal_opcode:
	movl $6,%edx
	pushl $0	/* fake errcode */
	jmp early_fault

early_protection_fault:
	movl $13,%edx
	jmp early_fault

early_page_fault:
	movl $14,%edx
	jmp early_fault

early_fault:
	cld
#ifdef CONFIG_PRINTK
560
	pusha
561
562
563
564
565
566
567
568
569
570
571
572
	movl $(__KERNEL_DS),%eax
	movl %eax,%ds
	movl %eax,%es
	cmpl $2,early_recursion_flag
	je hlt_loop
	incl early_recursion_flag
	movl %cr2,%eax
	pushl %eax
	pushl %edx		/* trapno */
	pushl $fault_msg
	call printk
#endif
573
	call dump_stack
574
575
576
577
hlt_loop:
	hlt
	jmp hlt_loop

Linus Torvalds's avatar
Linus Torvalds committed
578
579
580
581
/* This is the default interrupt "handler" :-) */
	ALIGN
ignore_int:
	cld
582
#ifdef CONFIG_PRINTK
Linus Torvalds's avatar
Linus Torvalds committed
583
584
585
586
587
588
589
590
	pushl %eax
	pushl %ecx
	pushl %edx
	pushl %es
	pushl %ds
	movl $(__KERNEL_DS),%eax
	movl %eax,%ds
	movl %eax,%es
591
592
593
	cmpl $2,early_recursion_flag
	je hlt_loop
	incl early_recursion_flag
Linus Torvalds's avatar
Linus Torvalds committed
594
595
596
597
598
599
	pushl 16(%esp)
	pushl 24(%esp)
	pushl 32(%esp)
	pushl 40(%esp)
	pushl $int_msg
	call printk
600
601
602

	call dump_stack

Linus Torvalds's avatar
Linus Torvalds committed
603
604
605
606
607
608
	addl $(5*4),%esp
	popl %ds
	popl %es
	popl %edx
	popl %ecx
	popl %eax
609
#endif
Linus Torvalds's avatar
Linus Torvalds committed
610
611
	iret

612
	__REFDATA
613
614
615
616
.align 4
ENTRY(initial_code)
	.long i386_start_kernel

Linus Torvalds's avatar
Linus Torvalds committed
617
618
619
/*
 * BSS section
 */
620
__PAGE_ALIGNED_BSS
621
	.align PAGE_SIZE_asm
622
#ifdef CONFIG_X86_PAE
623
initial_pg_pmd:
624
625
	.fill 1024*KPMDS,4,0
#else
626
ENTRY(initial_page_table)
Linus Torvalds's avatar
Linus Torvalds committed
627
	.fill 1024,4,0
628
#endif
629
initial_pg_fixmap:
Eric W. Biderman's avatar
Eric W. Biderman committed
630
	.fill 1024,4,0
Linus Torvalds's avatar
Linus Torvalds committed
631
632
ENTRY(empty_zero_page)
	.fill 4096,1,0
633
634
ENTRY(swapper_pg_dir)
	.fill 1024,4,0
635

Linus Torvalds's avatar
Linus Torvalds committed
636
637
638
/*
 * This starts the data section.
 */
639
#ifdef CONFIG_X86_PAE
640
__PAGE_ALIGNED_DATA
641
642
	/* Page-aligned for the benefit of paravirt? */
	.align PAGE_SIZE_asm
643
644
ENTRY(initial_page_table)
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
645
# if KPMDS == 3
646
647
648
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0
649
650
# elif KPMDS == 2
	.long	0,0
651
652
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
653
654
655
# elif KPMDS == 1
	.long	0,0
	.long	0,0
656
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
657
658
659
660
661
662
# else
#  error "Kernel PMDs should be 1, 2 or 3"
# endif
	.align PAGE_SIZE_asm		/* needs to be page-sized too */
#endif

Linus Torvalds's avatar
Linus Torvalds committed
663
664
665
666
667
668
669
.data
ENTRY(stack_start)
	.long init_thread_union+THREAD_SIZE
	.long __BOOT_DS

ready:	.byte 0

670
671
672
early_recursion_flag:
	.long 0

Linus Torvalds's avatar
Linus Torvalds committed
673
int_msg:
674
	.asciz "Unknown interrupt or fault at: %p %p %p\n"
Linus Torvalds's avatar
Linus Torvalds committed
675

676
fault_msg:
Vegard Nossum's avatar
Vegard Nossum committed
677
678
679
680
681
682
683
684
685
686
/* fault info: */
	.ascii "BUG: Int %d: CR2 %p\n"
/* pusha regs: */
	.ascii "     EDI %p  ESI %p  EBP %p  ESP %p\n"
	.ascii "     EBX %p  EDX %p  ECX %p  EAX %p\n"
/* fault frame: */
	.ascii "     err %p  EIP %p   CS %p  flg %p\n"
	.ascii "Stack: %p %p %p %p %p %p %p %p\n"
	.ascii "       %p %p %p %p %p %p %p %p\n"
	.asciz "       %p %p %p %p %p %p %p %p\n"
687

Thomas Gleixner's avatar
Thomas Gleixner committed
688
#include "../../x86/xen/xen-head.S"
689

Linus Torvalds's avatar
Linus Torvalds committed
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
/*
 * The IDT and GDT 'descriptors' are a strange 48-bit object
 * only used by the lidt and lgdt instructions. They are not
 * like usual segment descriptors - they consist of a 16-bit
 * segment size, and 32-bit linear address value:
 */

.globl boot_gdt_descr
.globl idt_descr

	ALIGN
# early boot GDT descriptor (must use 1:1 address mapping)
	.word 0				# 32 bit align gdt_desc.address
boot_gdt_descr:
	.word __BOOT_DS+7
705
	.long boot_gdt - __PAGE_OFFSET
Linus Torvalds's avatar
Linus Torvalds committed
706
707
708
709
710
711
712
713

	.word 0				# 32-bit align idt_desc.address
idt_descr:
	.word IDT_ENTRIES*8-1		# idt contains 256 entries
	.long idt_table

# boot GDT descriptor (later on used by CPU#0):
	.word 0				# 32 bit align gdt_desc.address
714
ENTRY(early_gdt_descr)
Linus Torvalds's avatar
Linus Torvalds committed
715
	.word GDT_ENTRIES*8-1
716
	.long gdt_page			/* Overwritten for secondary CPUs */
Linus Torvalds's avatar
Linus Torvalds committed
717
718

/*
719
 * The boot_gdt must mirror the equivalent in setup.S and is
Linus Torvalds's avatar
Linus Torvalds committed
720
721
722
 * used only for booting.
 */
	.align L1_CACHE_BYTES
723
ENTRY(boot_gdt)
Linus Torvalds's avatar
Linus Torvalds committed
724
725
726
	.fill GDT_ENTRY_BOOT_CS,8,0
	.quad 0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
	.quad 0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */