head_32.S 15.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
#include <asm/pgtable_32.h>
28 29 30

/* Physical address */
#define pa(X) ((X) - __PAGE_OFFSET)
L
Linus Torvalds 已提交
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 47
#define SIZEOF_PTREGS 17*4

48 49
/*
 * Worst-case size of the kernel mapping we need to make:
50 51
 * a relocatable kernel can live anywhere in lowmem, so we need to be able
 * to map all of lowmem.
52
 */
53
KERNEL_PAGES = LOWMEM_PAGES
54

55
INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE
56
RESERVE_BRK(pagetables, INIT_MAP_SIZE)
57

L
Linus Torvalds 已提交
58 59 60 61 62 63 64
/*
 * 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.
 */
65
__HEAD
L
Linus Torvalds 已提交
66
ENTRY(startup_32)
67
	movl pa(initial_stack),%ecx
68
	
R
Rusty Russell 已提交
69 70
	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
		us to not reload segments */
71
	testb $KEEP_SEGMENTS, BP_loadflags(%esi)
R
Rusty Russell 已提交
72
	jnz 2f
L
Linus Torvalds 已提交
73 74 75 76

/*
 * Set segments to known values.
 */
77
	lgdt pa(boot_gdt_descr)
L
Linus Torvalds 已提交
78 79 80 81 82
	movl $(__BOOT_DS),%eax
	movl %eax,%ds
	movl %eax,%es
	movl %eax,%fs
	movl %eax,%gs
83
	movl %eax,%ss
R
Rusty Russell 已提交
84
2:
85
	leal -__PAGE_OFFSET(%ecx),%esp
L
Linus Torvalds 已提交
86 87 88 89

/*
 * Clear BSS first so that there are no surprises...
 */
R
Rusty Russell 已提交
90
	cld
L
Linus Torvalds 已提交
91
	xorl %eax,%eax
92 93
	movl $pa(__bss_start),%edi
	movl $pa(__bss_stop),%ecx
L
Linus Torvalds 已提交
94 95 96
	subl %edi,%ecx
	shrl $2,%ecx
	rep ; stosl
97 98 99 100 101 102 103 104
/*
 * 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.
 */
105
	movl $pa(boot_params),%edi
106 107 108 109
	movl $(PARAM_SIZE/4),%ecx
	cld
	rep
	movsl
110
	movl pa(boot_params) + NEW_CL_POINTER,%esi
111
	andl %esi,%esi
112
	jz 1f			# No command line
113
	movl $pa(boot_command_line),%edi
114 115 116 117
	movl $(COMMAND_LINE_SIZE/4),%ecx
	rep
	movsl
1:
L
Linus Torvalds 已提交
118

119
#ifdef CONFIG_OLPC
120 121 122 123 124
	/* save OFW's pgdir table for later use when calling into OFW */
	movl %cr3, %eax
	movl %eax, pa(olpc_ofw_pgd)
#endif

125
#ifdef CONFIG_MICROCODE
126 127 128 129
	/* Early load ucode on BSP. */
	call load_ucode_bsp
#endif

130 131
	/* Create early pagetables. */
	call  mk_early_pgtbl_32
132 133

	/* Do early initialization of the fixmap area */
134
	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
135 136
#ifdef  CONFIG_X86_PAE
#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
137
	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
138
#else
139
	movl %eax,pa(initial_page_table+0xffc)
140
#endif
141 142 143 144

#ifdef CONFIG_PARAVIRT
	/* This is can only trip for a broken bootloader... */
	cmpw $0x207, pa(boot_params + BP_version)
145
	jb .Ldefault_entry
146 147 148 149 150

	/* 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
151
	jae .Lbad_subarch
152 153 154 155 156

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

157
.Lbad_subarch:
158 159 160 161 162 163 164 165 166
WEAK(lguest_entry)
WEAK(xen_entry)
	/* Unknown implementation; there's really
	   nothing we can do at this point. */
	ud2a

	__INITDATA

subarch_entries:
167
	.long .Ldefault_entry		/* normal x86/PC */
168 169
	.long lguest_entry		/* lguest hypervisor */
	.long xen_entry			/* Xen hypervisor */
170
	.long .Ldefault_entry		/* Moorestown MID */
171 172 173
num_subarch_entries = (. - subarch_entries) / 4
.previous
#else
174
	jmp .Ldefault_entry
175 176
#endif /* CONFIG_PARAVIRT */

177 178 179 180 181 182 183
#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)
184
	movl initial_stack, %ecx
185
	movl %ecx, %esp
186 187
	call *(initial_code)
1:	jmp 1b
188 189 190
ENDPROC(start_cpu0)
#endif

L
Linus Torvalds 已提交
191 192 193
/*
 * Non-boot CPU entry point; entered from trampoline.S
 * We can't lgdt here, because lgdt itself uses a data segment, but
194
 * we know the trampoline has already loaded the boot_gdt for us.
195 196 197
 *
 * If cpu hotplug is not supported then this code can go in init section
 * which will be freed later
L
Linus Torvalds 已提交
198 199 200 201 202 203 204 205
 */
ENTRY(startup_32_smp)
	cld
	movl $(__BOOT_DS),%eax
	movl %eax,%ds
	movl %eax,%es
	movl %eax,%fs
	movl %eax,%gs
206
	movl pa(initial_stack),%ecx
207 208
	movl %eax,%ss
	leal -__PAGE_OFFSET(%ecx),%esp
209

210
#ifdef CONFIG_MICROCODE
211 212 213 214
	/* Early load ucode on AP. */
	call load_ucode_ap
#endif

215
.Ldefault_entry:
216 217 218 219 220 221
#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 已提交
222
/*
223 224 225 226 227 228 229 230 231 232 233
 * 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 已提交
234
 *
235 236
 * 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 已提交
237
 */
238
	movl $-1,pa(X86_CPUID)		# preset CPUID level
239 240
	movl $X86_EFLAGS_ID,%ecx
	pushl %ecx
241
	popfl				# set EFLAGS=ID
242
	pushfl
243 244
	popl %eax			# get EFLAGS
	testl $X86_EFLAGS_ID,%eax	# did EFLAGS.ID remained set?
245
	jz .Lenable_paging		# hw disallowed setting of ID bit
246 247 248 249 250
					# which means no CPUID and no CR4

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

252 253
	movl $1,%eax
	cpuid
254
	andl $~1,%edx			# Ignore CPUID.FPU
255
	jz .Lenable_paging		# No flags or only CPUID.FPU = no CR4
256

257
	movl pa(mmu_cr4_features),%eax
L
Linus Torvalds 已提交
258 259
	movl %eax,%cr4

260
	testb $X86_CR4_PAE, %al		# check if PAE is enabled
261
	jz .Lenable_paging
L
Linus Torvalds 已提交
262 263 264 265

	/* Check if extended functions are implemented */
	movl $0x80000000, %eax
	cpuid
266 267 268
	/* Value must be in the range 0x80000001 to 0x8000ffff */
	subl $0x80000001, %eax
	cmpl $(0x8000ffff-0x80000001), %eax
269
	ja .Lenable_paging
270 271 272 273

	/* Clear bogus XD_DISABLE bits */
	call verify_cpu

L
Linus Torvalds 已提交
274 275 276
	mov $0x80000001, %eax
	cpuid
	/* Execute Disable bit supported? */
277
	btl $(X86_FEATURE_NX & 31), %edx
278
	jnc .Lenable_paging
L
Linus Torvalds 已提交
279 280

	/* Setup EFER (Extended Feature Enable Register) */
281
	movl $MSR_EFER, %ecx
L
Linus Torvalds 已提交
282 283
	rdmsr

284
	btsl $_EFER_NX, %eax
L
Linus Torvalds 已提交
285 286 287
	/* Make changes effective */
	wrmsr

288
.Lenable_paging:
L
Linus Torvalds 已提交
289 290 291 292

/*
 * Enable paging
 */
293
	movl $pa(initial_page_table), %eax
L
Linus Torvalds 已提交
294
	movl %eax,%cr3		/* set the page table pointer.. */
295
	movl $CR0_STATE,%eax
L
Linus Torvalds 已提交
296 297 298
	movl %eax,%cr0		/* ..and set paging (PG) bit */
	ljmp $__BOOT_CS,$1f	/* Clear prefetch and normalize %eip */
1:
299 300
	/* Shift the stack pointer to a virtual address */
	addl $__PAGE_OFFSET, %esp
L
Linus Torvalds 已提交
301 302 303 304 305

/*
 * start system 32-bit setup. We need to re-do some of the things done
 * in 16-bit mode for the "real" operations.
 */
306 307 308 309 310
	movl setup_once_ref,%eax
	andl %eax,%eax
	jz 1f				# Did we do this already?
	call *%eax
1:
311

L
Linus Torvalds 已提交
312
/*
313
 * Check if it is 486
L
Linus Torvalds 已提交
314
 */
315
	movb $4,X86			# at least 486
316
	cmpl $-1,X86_CPUID
317
	je .Lis486
L
Linus Torvalds 已提交
318 319 320 321 322 323 324 325 326 327

	/* 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?
328
	je .Lis486
L
Linus Torvalds 已提交
329 330 331 332 333 334 335 336 337 338 339 340 341

	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

342
.Lis486:
343
	movl $0x50022,%ecx	# set AM, WP, NE and MP
344
	movl %cr0,%eax
L
Linus Torvalds 已提交
345 346 347 348
	andl $0x80000011,%eax	# Save PG,PE,ET
	orl %ecx,%eax
	movl %eax,%cr0

349
	lgdt early_gdt_descr
L
Linus Torvalds 已提交
350 351 352 353 354 355 356 357 358
	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

359 360 361
	movl $(__KERNEL_PERCPU), %eax
	movl %eax,%fs			# set this cpu's percpu

362
	movl $(__KERNEL_STACK_CANARY),%eax
363
	movl %eax,%gs
364 365

	xorl %eax,%eax			# Clear LDT
L
Linus Torvalds 已提交
366
	lldt %ax
367

368 369 370
	call *(initial_code)
1:	jmp 1b
ENDPROC(startup_32_smp)
L
Linus Torvalds 已提交
371

372 373
#include "verify_cpu.S"

L
Linus Torvalds 已提交
374
/*
375
 *  setup_once
L
Linus Torvalds 已提交
376
 *
377
 *  The setup work we only want to run on the BSP.
L
Linus Torvalds 已提交
378 379 380
 *
 *  Warning: %esi is live across this function.
 */
381 382 383
__INIT
setup_once:
	/*
384 385 386 387 388
	 * 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.
389
	 */
L
Linus Torvalds 已提交
390

391
	movl $idt_table,%edi
392
	movl $early_idt_handler_array,%eax
393 394
	movl $NUM_EXCEPTION_VECTORS,%ecx
1:
L
Linus Torvalds 已提交
395
	movl %eax,(%edi)
396 397 398
	movl %eax,4(%edi)
	/* interrupt gate, dpl=0, present */
	movl $(0x8E000000 + __KERNEL_CS),2(%edi)
399
	addl $EARLY_IDT_HANDLER_SIZE,%eax
L
Linus Torvalds 已提交
400
	addl $8,%edi
401
	loop 1b
402

403 404
	movl $256 - NUM_EXCEPTION_VECTORS,%ecx
	movl $ignore_int,%edx
405
	movl $(__KERNEL_CS << 16),%eax
406
	movw %dx,%ax		/* selector = 0x0010 = cs */
407
	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */
408 409 410 411 412
2:
	movl %eax,(%edi)
	movl %edx,4(%edi)
	addl $8,%edi
	loop 2b
413

414 415 416 417 418 419 420 421 422 423 424 425 426
#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
427

428
	andl $0,setup_once_ref	/* Once is enough, thanks */
L
Linus Torvalds 已提交
429 430
	ret

431
ENTRY(early_idt_handler_array)
432 433 434 435 436 437
	# 36(%esp) %eflags
	# 32(%esp) %cs
	# 28(%esp) %eip
	# 24(%rsp) error code
	i = 0
	.rept NUM_EXCEPTION_VECTORS
438
	.ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
439 440 441
	pushl $0		# Dummy error code, to make stack frame uniform
	.endif
	pushl $i		# 20(%esp) Vector number
442
	jmp early_idt_handler_common
443
	i = i + 1
444
	.fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
445
	.endr
446
ENDPROC(early_idt_handler_array)
447
	
448 449 450 451 452
early_idt_handler_common:
	/*
	 * The stack is the hardware frame, an error code or zero, and the
	 * vector number.
	 */
453
	cld
454

455
	incl %ss:early_recursion_flag
456

457
	/* The vector number is in pt_regs->gs */
458

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 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
	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
503
ENDPROC(early_idt_handler_common)
504

L
Linus Torvalds 已提交
505 506 507 508
/* This is the default interrupt "handler" :-) */
	ALIGN
ignore_int:
	cld
M
Matt Mackall 已提交
509
#ifdef CONFIG_PRINTK
L
Linus Torvalds 已提交
510 511 512 513 514 515 516 517
	pushl %eax
	pushl %ecx
	pushl %edx
	pushl %es
	pushl %ds
	movl $(__KERNEL_DS),%eax
	movl %eax,%ds
	movl %eax,%es
518 519 520
	cmpl $2,early_recursion_flag
	je hlt_loop
	incl early_recursion_flag
L
Linus Torvalds 已提交
521 522 523 524 525 526
	pushl 16(%esp)
	pushl 24(%esp)
	pushl 32(%esp)
	pushl 40(%esp)
	pushl $int_msg
	call printk
527 528 529

	call dump_stack

L
Linus Torvalds 已提交
530 531 532 533 534 535
	addl $(5*4),%esp
	popl %ds
	popl %es
	popl %edx
	popl %ecx
	popl %eax
M
Matt Mackall 已提交
536
#endif
L
Linus Torvalds 已提交
537
	iret
538 539 540 541

hlt_loop:
	hlt
	jmp hlt_loop
542 543 544
ENDPROC(ignore_int)
__INITDATA
	.align 4
545
GLOBAL(early_recursion_flag)
546
	.long 0
L
Linus Torvalds 已提交
547

548 549
__REFDATA
	.align 4
T
Thomas Gleixner 已提交
550 551
ENTRY(initial_code)
	.long i386_start_kernel
552 553
ENTRY(setup_once_ref)
	.long setup_once
T
Thomas Gleixner 已提交
554

L
Linus Torvalds 已提交
555 556 557
/*
 * BSS section
 */
558
__PAGE_ALIGNED_BSS
559
	.align PAGE_SIZE
560
#ifdef CONFIG_X86_PAE
561
.globl initial_pg_pmd
562
initial_pg_pmd:
563 564
	.fill 1024*KPMDS,4,0
#else
565 566
.globl initial_page_table
initial_page_table:
L
Linus Torvalds 已提交
567
	.fill 1024,4,0
568
#endif
569
initial_pg_fixmap:
E
Eric W. Biderman 已提交
570
	.fill 1024,4,0
571 572
.globl empty_zero_page
empty_zero_page:
L
Linus Torvalds 已提交
573
	.fill 4096,1,0
574 575
.globl swapper_pg_dir
swapper_pg_dir:
576
	.fill 1024,4,0
577
EXPORT_SYMBOL(empty_zero_page)
578

L
Linus Torvalds 已提交
579 580 581
/*
 * This starts the data section.
 */
582
#ifdef CONFIG_X86_PAE
583
__PAGE_ALIGNED_DATA
584
	/* Page-aligned for the benefit of paravirt? */
585
	.align PAGE_SIZE
586 587
ENTRY(initial_page_table)
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
588
# if KPMDS == 3
589 590 591
	.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
592 593
# elif KPMDS == 2
	.long	0,0
594 595
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
596 597 598
# elif KPMDS == 1
	.long	0,0
	.long	0,0
599
	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
600 601 602
# else
#  error "Kernel PMDs should be 1, 2 or 3"
# endif
603
	.align PAGE_SIZE		/* needs to be page-sized too */
604 605
#endif

L
Linus Torvalds 已提交
606
.data
607
.balign 4
608
ENTRY(initial_stack)
609 610 611 612 613 614
	/*
	 * 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 已提交
615

616
__INITRODATA
L
Linus Torvalds 已提交
617
int_msg:
618
	.asciz "Unknown interrupt or fault at: %p %p %p\n"
L
Linus Torvalds 已提交
619

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

L
Linus Torvalds 已提交
622 623 624 625 626 627 628
/*
 * 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:
 */

629
	.data
L
Linus Torvalds 已提交
630 631 632 633 634 635 636 637
.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
638
	.long boot_gdt - __PAGE_OFFSET
L
Linus Torvalds 已提交
639 640 641 642 643 644 645 646

	.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
647
ENTRY(early_gdt_descr)
L
Linus Torvalds 已提交
648
	.word GDT_ENTRIES*8-1
R
Rusty Russell 已提交
649
	.long gdt_page			/* Overwritten for secondary CPUs */
L
Linus Torvalds 已提交
650 651

/*
652
 * The boot_gdt must mirror the equivalent in setup.S and is
L
Linus Torvalds 已提交
653 654 655
 * used only for booting.
 */
	.align L1_CACHE_BYTES
656
ENTRY(boot_gdt)
L
Linus Torvalds 已提交
657 658 659
	.fill GDT_ENTRY_BOOT_CS,8,0
	.quad 0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
	.quad 0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */