head_32.S 18.5 KB
Newer Older
L
Linus Torvalds 已提交
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>
L
Linus Torvalds 已提交
12 13
#include <linux/linkage.h>
#include <asm/segment.h>
14 15
#include <asm/page_types.h>
#include <asm/pgtable_types.h>
L
Linus Torvalds 已提交
16 17
#include <asm/cache.h>
#include <asm/thread_info.h>
18
#include <asm/asm-offsets.h>
L
Linus Torvalds 已提交
19
#include <asm/setup.h>
20
#include <asm/processor-flags.h>
21
#include <asm/msr-index.h>
22
#include <asm/cpufeatures.h>
23
#include <asm/percpu.h>
24
#include <asm/nops.h>
25
#include <asm/bootparam.h>
26
#include <asm/export.h>
27 28 29

/* Physical address */
#define pa(X) ((X) - __PAGE_OFFSET)
L
Linus Torvalds 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

/*
 * 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

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

60
#if PTRS_PER_PMD > 1
61
#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
62
#else
63
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
64 65
#endif

66 67
#define SIZEOF_PTREGS 17*4

68 69 70 71 72 73 74 75 76 77
/*
 * Number of possible pages in the lowmem region.
 *
 * We shift 2 by 31 instead of 1 by 32 to the left in order to avoid a
 * gas warning about overflowing shift count when gas has been compiled
 * with only a host target support using a 32-bit type for internal
 * representation.
 */
LOWMEM_PAGES = (((2<<31) - __PAGE_OFFSET) >> PAGE_SHIFT)

78
/* Enough space to fit pagetables for the low memory linear map */
79
MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT
80 81 82

/*
 * Worst-case size of the kernel mapping we need to make:
83 84
 * a relocatable kernel can live anywhere in lowmem, so we need to be able
 * to map all of lowmem.
85
 */
86
KERNEL_PAGES = LOWMEM_PAGES
87

88
INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE
89
RESERVE_BRK(pagetables, INIT_MAP_SIZE)
90

L
Linus Torvalds 已提交
91 92 93 94 95 96 97
/*
 * 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.
 */
98
__HEAD
L
Linus Torvalds 已提交
99
ENTRY(startup_32)
100
	movl pa(initial_stack),%ecx
101
	
R
Rusty Russell 已提交
102 103
	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
		us to not reload segments */
104
	testb $KEEP_SEGMENTS, BP_loadflags(%esi)
R
Rusty Russell 已提交
105
	jnz 2f
L
Linus Torvalds 已提交
106 107 108 109

/*
 * Set segments to known values.
 */
110
	lgdt pa(boot_gdt_descr)
L
Linus Torvalds 已提交
111 112 113 114 115
	movl $(__BOOT_DS),%eax
	movl %eax,%ds
	movl %eax,%es
	movl %eax,%fs
	movl %eax,%gs
116
	movl %eax,%ss
R
Rusty Russell 已提交
117
2:
118
	leal -__PAGE_OFFSET(%ecx),%esp
L
Linus Torvalds 已提交
119 120 121 122

/*
 * Clear BSS first so that there are no surprises...
 */
R
Rusty Russell 已提交
123
	cld
L
Linus Torvalds 已提交
124
	xorl %eax,%eax
125 126
	movl $pa(__bss_start),%edi
	movl $pa(__bss_stop),%ecx
L
Linus Torvalds 已提交
127 128 129
	subl %edi,%ecx
	shrl $2,%ecx
	rep ; stosl
130 131 132 133 134 135 136 137
/*
 * 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.
 */
138
	movl $pa(boot_params),%edi
139 140 141 142
	movl $(PARAM_SIZE/4),%ecx
	cld
	rep
	movsl
143
	movl pa(boot_params) + NEW_CL_POINTER,%esi
144
	andl %esi,%esi
145
	jz 1f			# No command line
146
	movl $pa(boot_command_line),%edi
147 148 149 150
	movl $(COMMAND_LINE_SIZE/4),%ecx
	rep
	movsl
1:
L
Linus Torvalds 已提交
151

152
#ifdef CONFIG_OLPC
153 154 155 156 157
	/* save OFW's pgdir table for later use when calling into OFW */
	movl %cr3, %eax
	movl %eax, pa(olpc_ofw_pgd)
#endif

158
#ifdef CONFIG_MICROCODE
159 160 161 162
	/* Early load ucode on BSP. */
	call load_ucode_bsp
#endif

L
Linus Torvalds 已提交
163 164
/*
 * Initialize page tables.  This creates a PDE and a set of page
165
 * tables, which are located immediately beyond __brk_base.  The variable
166
 * _brk_end is set up to point to the first "safe" location.
L
Linus Torvalds 已提交
167
 * Mappings are created both at virtual address 0 (identity mapping)
168
 * and PAGE_OFFSET for up to _end.
L
Linus Torvalds 已提交
169
 */
170 171 172
#ifdef CONFIG_X86_PAE

	/*
173 174 175 176
	 * 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.
177
	 *
178
	 * Note the upper half of each PMD or PTE are always zero at this stage.
179 180
	 */

J
Joe Korty 已提交
181
#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
182 183 184

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

185
	movl $pa(__brk_base), %edi
186
	movl $pa(initial_pg_pmd), %edx
187
	movl $PTE_IDENT_ATTR, %eax
188
10:
189
	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PMD entry */
190 191 192 193 194 195 196 197 198 199 200 201 202
	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

	/*
203
	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
204
	 */
205
	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
206 207 208
	cmpl %ebp,%eax
	jb 10b
1:
209 210
	addl $__PAGE_OFFSET, %edi
	movl %edi, pa(_brk_end)
211 212
	shrl $12, %eax
	movl %eax, pa(max_pfn_mapped)
213 214

	/* Do early initialization of the fixmap area */
215 216
	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
217 218 219 220
#else	/* Not PAE */

page_pde_offset = (__PAGE_OFFSET >> 20);

221
	movl $pa(__brk_base), %edi
222
	movl $pa(initial_page_table), %edx
223
	movl $PTE_IDENT_ATTR, %eax
L
Linus Torvalds 已提交
224
10:
225
	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PDE entry */
L
Linus Torvalds 已提交
226 227 228 229 230 231 232 233
	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
234
	/*
235
	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
236
	 */
237
	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
L
Linus Torvalds 已提交
238 239
	cmpl %ebp,%eax
	jb 10b
240 241
	addl $__PAGE_OFFSET, %edi
	movl %edi, pa(_brk_end)
242 243
	shrl $12, %eax
	movl %eax, pa(max_pfn_mapped)
244

245
	/* Do early initialization of the fixmap area */
246 247
	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
	movl %eax,pa(initial_page_table+0xffc)
248
#endif
249 250 251 252

#ifdef CONFIG_PARAVIRT
	/* This is can only trip for a broken bootloader... */
	cmpw $0x207, pa(boot_params + BP_version)
253
	jb .Ldefault_entry
254 255 256 257 258

	/* Paravirt-compatible boot parameters.  Look to see what architecture
		we're booting under. */
	movl pa(boot_params + BP_hardware_subarch), %eax
	cmpl $num_subarch_entries, %eax
259
	jae .Lbad_subarch
260 261 262 263 264

	movl pa(subarch_entries)(,%eax,4), %eax
	subl $__PAGE_OFFSET, %eax
	jmp *%eax

265
.Lbad_subarch:
266 267 268 269 270 271 272 273 274
WEAK(lguest_entry)
WEAK(xen_entry)
	/* Unknown implementation; there's really
	   nothing we can do at this point. */
	ud2a

	__INITDATA

subarch_entries:
275
	.long .Ldefault_entry		/* normal x86/PC */
276 277
	.long lguest_entry		/* lguest hypervisor */
	.long xen_entry			/* Xen hypervisor */
278
	.long .Ldefault_entry		/* Moorestown MID */
279 280 281
num_subarch_entries = (. - subarch_entries) / 4
.previous
#else
282
	jmp .Ldefault_entry
283 284
#endif /* CONFIG_PARAVIRT */

285 286 287 288 289 290 291
#ifdef CONFIG_HOTPLUG_CPU
/*
 * Boot CPU0 entry point. It's called from play_dead(). Everything has been set
 * up already except stack. We just set up stack here. Then call
 * start_secondary().
 */
ENTRY(start_cpu0)
292
	movl initial_stack, %ecx
293
	movl %ecx, %esp
294 295
	call *(initial_code)
1:	jmp 1b
296 297 298
ENDPROC(start_cpu0)
#endif

L
Linus Torvalds 已提交
299 300 301
/*
 * Non-boot CPU entry point; entered from trampoline.S
 * We can't lgdt here, because lgdt itself uses a data segment, but
302
 * we know the trampoline has already loaded the boot_gdt for us.
303 304 305
 *
 * If cpu hotplug is not supported then this code can go in init section
 * which will be freed later
L
Linus Torvalds 已提交
306 307 308 309 310 311 312 313
 */
ENTRY(startup_32_smp)
	cld
	movl $(__BOOT_DS),%eax
	movl %eax,%ds
	movl %eax,%es
	movl %eax,%fs
	movl %eax,%gs
314
	movl pa(initial_stack),%ecx
315 316
	movl %eax,%ss
	leal -__PAGE_OFFSET(%ecx),%esp
317

318
#ifdef CONFIG_MICROCODE
319 320 321 322
	/* Early load ucode on AP. */
	call load_ucode_ap
#endif

323
.Ldefault_entry:
324 325 326 327 328 329
#define CR0_STATE	(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
			 X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
			 X86_CR0_PG)
	movl $(CR0_STATE & ~X86_CR0_PG),%eax
	movl %eax,%cr0

L
Linus Torvalds 已提交
330
/*
331 332 333 334 335 336 337 338 339 340 341
 * We want to start out with EFLAGS unambiguously cleared. Some BIOSes leave
 * bits like NT set. This would confuse the debugger if this code is traced. So
 * initialize them properly now before switching to protected mode. That means
 * DF in particular (even though we have cleared it earlier after copying the
 * command line) because GCC expects it.
 */
	pushl $0
	popfl

/*
 * New page tables may be in 4Mbyte page mode and may be using the global pages.
L
Linus Torvalds 已提交
342
 *
343 344
 * NOTE! If we are on a 486 we may have no cr4 at all! Specifically, cr4 exists
 * if and only if CPUID exists and has flags other than the FPU flag set.
L
Linus Torvalds 已提交
345
 */
346
	movl $-1,pa(X86_CPUID)		# preset CPUID level
347 348
	movl $X86_EFLAGS_ID,%ecx
	pushl %ecx
349
	popfl				# set EFLAGS=ID
350
	pushfl
351 352
	popl %eax			# get EFLAGS
	testl $X86_EFLAGS_ID,%eax	# did EFLAGS.ID remained set?
353
	jz .Lenable_paging		# hw disallowed setting of ID bit
354 355 356 357 358
					# which means no CPUID and no CR4

	xorl %eax,%eax
	cpuid
	movl %eax,pa(X86_CPUID)		# save largest std CPUID function
359

360 361
	movl $1,%eax
	cpuid
362
	andl $~1,%edx			# Ignore CPUID.FPU
363
	jz .Lenable_paging		# No flags or only CPUID.FPU = no CR4
364

365
	movl pa(mmu_cr4_features),%eax
L
Linus Torvalds 已提交
366 367
	movl %eax,%cr4

368
	testb $X86_CR4_PAE, %al		# check if PAE is enabled
369
	jz .Lenable_paging
L
Linus Torvalds 已提交
370 371 372 373

	/* Check if extended functions are implemented */
	movl $0x80000000, %eax
	cpuid
374 375 376
	/* Value must be in the range 0x80000001 to 0x8000ffff */
	subl $0x80000001, %eax
	cmpl $(0x8000ffff-0x80000001), %eax
377
	ja .Lenable_paging
378 379 380 381

	/* Clear bogus XD_DISABLE bits */
	call verify_cpu

L
Linus Torvalds 已提交
382 383 384
	mov $0x80000001, %eax
	cpuid
	/* Execute Disable bit supported? */
385
	btl $(X86_FEATURE_NX & 31), %edx
386
	jnc .Lenable_paging
L
Linus Torvalds 已提交
387 388

	/* Setup EFER (Extended Feature Enable Register) */
389
	movl $MSR_EFER, %ecx
L
Linus Torvalds 已提交
390 391
	rdmsr

392
	btsl $_EFER_NX, %eax
L
Linus Torvalds 已提交
393 394 395
	/* Make changes effective */
	wrmsr

396
.Lenable_paging:
L
Linus Torvalds 已提交
397 398 399 400

/*
 * Enable paging
 */
401
	movl $pa(initial_page_table), %eax
L
Linus Torvalds 已提交
402
	movl %eax,%cr3		/* set the page table pointer.. */
403
	movl $CR0_STATE,%eax
L
Linus Torvalds 已提交
404 405 406
	movl %eax,%cr0		/* ..and set paging (PG) bit */
	ljmp $__BOOT_CS,$1f	/* Clear prefetch and normalize %eip */
1:
407 408
	/* Shift the stack pointer to a virtual address */
	addl $__PAGE_OFFSET, %esp
L
Linus Torvalds 已提交
409 410 411 412 413

/*
 * start system 32-bit setup. We need to re-do some of the things done
 * in 16-bit mode for the "real" operations.
 */
414 415 416 417 418
	movl setup_once_ref,%eax
	andl %eax,%eax
	jz 1f				# Did we do this already?
	call *%eax
1:
419

L
Linus Torvalds 已提交
420
/*
421
 * Check if it is 486
L
Linus Torvalds 已提交
422
 */
423
	movb $4,X86			# at least 486
424
	cmpl $-1,X86_CPUID
425
	je .Lis486
L
Linus Torvalds 已提交
426 427 428 429 430 431 432 433 434 435

	/* 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?
436
	je .Lis486
L
Linus Torvalds 已提交
437 438 439 440 441 442 443 444 445 446 447 448 449

	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

450
.Lis486:
451
	movl $0x50022,%ecx	# set AM, WP, NE and MP
452
	movl %cr0,%eax
L
Linus Torvalds 已提交
453 454 455 456
	andl $0x80000011,%eax	# Save PG,PE,ET
	orl %ecx,%eax
	movl %eax,%cr0

457
	lgdt early_gdt_descr
L
Linus Torvalds 已提交
458 459 460 461 462 463 464 465 466
	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

467 468 469
	movl $(__KERNEL_PERCPU), %eax
	movl %eax,%fs			# set this cpu's percpu

470
	movl $(__KERNEL_STACK_CANARY),%eax
471
	movl %eax,%gs
472 473

	xorl %eax,%eax			# Clear LDT
L
Linus Torvalds 已提交
474
	lldt %ax
475

476 477 478
	call *(initial_code)
1:	jmp 1b
ENDPROC(startup_32_smp)
L
Linus Torvalds 已提交
479

480 481
#include "verify_cpu.S"

L
Linus Torvalds 已提交
482
/*
483
 *  setup_once
L
Linus Torvalds 已提交
484
 *
485
 *  The setup work we only want to run on the BSP.
L
Linus Torvalds 已提交
486 487 488
 *
 *  Warning: %esi is live across this function.
 */
489 490 491
__INIT
setup_once:
	/*
492 493 494 495 496
	 * Set up a idt with 256 interrupt gates that push zero if there
	 * is no error code and then jump to early_idt_handler_common.
	 * It doesn't actually load the idt - that needs to be done on
	 * each CPU. Interrupts are enabled elsewhere, when we can be
	 * relatively sure everything is ok.
497
	 */
L
Linus Torvalds 已提交
498

499
	movl $idt_table,%edi
500
	movl $early_idt_handler_array,%eax
501 502
	movl $NUM_EXCEPTION_VECTORS,%ecx
1:
L
Linus Torvalds 已提交
503
	movl %eax,(%edi)
504 505 506
	movl %eax,4(%edi)
	/* interrupt gate, dpl=0, present */
	movl $(0x8E000000 + __KERNEL_CS),2(%edi)
507
	addl $EARLY_IDT_HANDLER_SIZE,%eax
L
Linus Torvalds 已提交
508
	addl $8,%edi
509
	loop 1b
510

511 512
	movl $256 - NUM_EXCEPTION_VECTORS,%ecx
	movl $ignore_int,%edx
513
	movl $(__KERNEL_CS << 16),%eax
514
	movw %dx,%ax		/* selector = 0x0010 = cs */
515
	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */
516 517 518 519 520
2:
	movl %eax,(%edi)
	movl %edx,4(%edi)
	addl $8,%edi
	loop 2b
521

522 523 524 525 526 527 528 529 530 531 532 533 534
#ifdef CONFIG_CC_STACKPROTECTOR
	/*
	 * Configure the stack canary. The linker can't handle this by
	 * relocation.  Manually set base address in stack canary
	 * segment descriptor.
	 */
	movl $gdt_page,%eax
	movl $stack_canary,%ecx
	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)
#endif
535

536
	andl $0,setup_once_ref	/* Once is enough, thanks */
L
Linus Torvalds 已提交
537 538
	ret

539
ENTRY(early_idt_handler_array)
540 541 542 543 544 545
	# 36(%esp) %eflags
	# 32(%esp) %cs
	# 28(%esp) %eip
	# 24(%rsp) error code
	i = 0
	.rept NUM_EXCEPTION_VECTORS
546
	.ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
547 548 549
	pushl $0		# Dummy error code, to make stack frame uniform
	.endif
	pushl $i		# 20(%esp) Vector number
550
	jmp early_idt_handler_common
551
	i = i + 1
552
	.fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
553
	.endr
554
ENDPROC(early_idt_handler_array)
555
	
556 557 558 559 560
early_idt_handler_common:
	/*
	 * The stack is the hardware frame, an error code or zero, and the
	 * vector number.
	 */
561
	cld
562

563
	incl %ss:early_recursion_flag
564

565
	/* The vector number is in pt_regs->gs */
566

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
	cld
	pushl	%fs		/* pt_regs->fs */
	movw	$0, 2(%esp)	/* clear high bits (some CPUs leave garbage) */
	pushl	%es		/* pt_regs->es */
	movw	$0, 2(%esp)	/* clear high bits (some CPUs leave garbage) */
	pushl	%ds		/* pt_regs->ds */
	movw	$0, 2(%esp)	/* clear high bits (some CPUs leave garbage) */
	pushl	%eax		/* pt_regs->ax */
	pushl	%ebp		/* pt_regs->bp */
	pushl	%edi		/* pt_regs->di */
	pushl	%esi		/* pt_regs->si */
	pushl	%edx		/* pt_regs->dx */
	pushl	%ecx		/* pt_regs->cx */
	pushl	%ebx		/* pt_regs->bx */

	/* Fix up DS and ES */
	movl	$(__KERNEL_DS), %ecx
	movl	%ecx, %ds
	movl	%ecx, %es

	/* Load the vector number into EDX */
	movl	PT_GS(%esp), %edx

	/* Load GS into pt_regs->gs and clear high bits */
	movw	%gs, PT_GS(%esp)
	movw	$0, PT_GS+2(%esp)

	movl	%esp, %eax	/* args are pt_regs (EAX), trapnr (EDX) */
	call	early_fixup_exception

	popl	%ebx		/* pt_regs->bx */
	popl	%ecx		/* pt_regs->cx */
	popl	%edx		/* pt_regs->dx */
	popl	%esi		/* pt_regs->si */
	popl	%edi		/* pt_regs->di */
	popl	%ebp		/* pt_regs->bp */
	popl	%eax		/* pt_regs->ax */
	popl	%ds		/* pt_regs->ds */
	popl	%es		/* pt_regs->es */
	popl	%fs		/* pt_regs->fs */
	popl	%gs		/* pt_regs->gs */
	decl	%ss:early_recursion_flag
	addl	$4, %esp	/* pop pt_regs->orig_ax */
	iret
611
ENDPROC(early_idt_handler_common)
612

L
Linus Torvalds 已提交
613 614 615 616
/* This is the default interrupt "handler" :-) */
	ALIGN
ignore_int:
	cld
M
Matt Mackall 已提交
617
#ifdef CONFIG_PRINTK
L
Linus Torvalds 已提交
618 619 620 621 622 623 624 625
	pushl %eax
	pushl %ecx
	pushl %edx
	pushl %es
	pushl %ds
	movl $(__KERNEL_DS),%eax
	movl %eax,%ds
	movl %eax,%es
626 627 628
	cmpl $2,early_recursion_flag
	je hlt_loop
	incl early_recursion_flag
L
Linus Torvalds 已提交
629 630 631 632 633 634
	pushl 16(%esp)
	pushl 24(%esp)
	pushl 32(%esp)
	pushl 40(%esp)
	pushl $int_msg
	call printk
635 636 637

	call dump_stack

L
Linus Torvalds 已提交
638 639 640 641 642 643
	addl $(5*4),%esp
	popl %ds
	popl %es
	popl %edx
	popl %ecx
	popl %eax
M
Matt Mackall 已提交
644
#endif
L
Linus Torvalds 已提交
645
	iret
646 647 648 649

hlt_loop:
	hlt
	jmp hlt_loop
650 651 652
ENDPROC(ignore_int)
__INITDATA
	.align 4
653
GLOBAL(early_recursion_flag)
654
	.long 0
L
Linus Torvalds 已提交
655

656 657
__REFDATA
	.align 4
T
Thomas Gleixner 已提交
658 659
ENTRY(initial_code)
	.long i386_start_kernel
660 661
ENTRY(setup_once_ref)
	.long setup_once
T
Thomas Gleixner 已提交
662

L
Linus Torvalds 已提交
663 664 665
/*
 * BSS section
 */
666
__PAGE_ALIGNED_BSS
667
	.align PAGE_SIZE
668
#ifdef CONFIG_X86_PAE
669
initial_pg_pmd:
670 671
	.fill 1024*KPMDS,4,0
#else
672 673
.globl initial_page_table
initial_page_table:
L
Linus Torvalds 已提交
674
	.fill 1024,4,0
675
#endif
676
initial_pg_fixmap:
E
Eric W. Biderman 已提交
677
	.fill 1024,4,0
678 679
.globl empty_zero_page
empty_zero_page:
L
Linus Torvalds 已提交
680
	.fill 4096,1,0
681 682
.globl swapper_pg_dir
swapper_pg_dir:
683
	.fill 1024,4,0
684
EXPORT_SYMBOL(empty_zero_page)
685

L
Linus Torvalds 已提交
686 687 688
/*
 * This starts the data section.
 */
689
#ifdef CONFIG_X86_PAE
690
__PAGE_ALIGNED_DATA
691
	/* Page-aligned for the benefit of paravirt? */
692
	.align PAGE_SIZE
693 694
ENTRY(initial_page_table)
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
695
# if KPMDS == 3
696 697 698
	.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
699 700
# elif KPMDS == 2
	.long	0,0
701 702
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
703 704 705
# elif KPMDS == 1
	.long	0,0
	.long	0,0
706
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
707 708 709
# else
#  error "Kernel PMDs should be 1, 2 or 3"
# endif
710
	.align PAGE_SIZE		/* needs to be page-sized too */
711 712
#endif

L
Linus Torvalds 已提交
713
.data
714
.balign 4
715
ENTRY(initial_stack)
716 717 718 719 720 721
	/*
	 * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
	 * unwinder reliably detect the end of the stack.
	 */
	.long init_thread_union + THREAD_SIZE - SIZEOF_PTREGS - \
	      TOP_OF_KERNEL_STACK_PADDING;
L
Linus Torvalds 已提交
722

723
__INITRODATA
L
Linus Torvalds 已提交
724
int_msg:
725
	.asciz "Unknown interrupt or fault at: %p %p %p\n"
L
Linus Torvalds 已提交
726

T
Thomas Gleixner 已提交
727
#include "../../x86/xen/xen-head.S"
728

L
Linus Torvalds 已提交
729 730 731 732 733 734 735
/*
 * 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:
 */

736
	.data
L
Linus Torvalds 已提交
737 738 739 740 741 742 743 744
.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
745
	.long boot_gdt - __PAGE_OFFSET
L
Linus Torvalds 已提交
746 747 748 749 750 751 752 753

	.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
754
ENTRY(early_gdt_descr)
L
Linus Torvalds 已提交
755
	.word GDT_ENTRIES*8-1
R
Rusty Russell 已提交
756
	.long gdt_page			/* Overwritten for secondary CPUs */
L
Linus Torvalds 已提交
757 758

/*
759
 * The boot_gdt must mirror the equivalent in setup.S and is
L
Linus Torvalds 已提交
760 761 762
 * used only for booting.
 */
	.align L1_CACHE_BYTES
763
ENTRY(boot_gdt)
L
Linus Torvalds 已提交
764 765 766
	.fill GDT_ENTRY_BOOT_CS,8,0
	.quad 0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
	.quad 0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */