/*
 *  linux/arch/i386/head.S -- the 32-bit startup code.
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Enhanced CPU detection and feature setting code by Mike Jagdis
 *  and Martin Mares, November 1997.
 */

.text
#include <linux/tasks.h>
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>


#define CL_MAGIC_ADDR	0x90020
#define CL_MAGIC	0xA33F
#define CL_BASE_ADDR	0x90000
#define CL_OFFSET	0x90022

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

#define CPU_PARAMS	SYMBOL_NAME(boot_cpu_data)
#define X86		CPU_PARAMS+0
#define X86_VENDOR	CPU_PARAMS+1
#define X86_MODEL	CPU_PARAMS+2
#define X86_MASK	CPU_PARAMS+3
#define X86_HARD_MATH	CPU_PARAMS+6
#define X86_CPUID	CPU_PARAMS+8
#define X86_CAPABILITY	CPU_PARAMS+12
#define X86_VENDOR_ID	CPU_PARAMS+16

/*
 * swapper_pg_dir is the main page directory, address 0x00101000
 */
ENTRY(stext)
ENTRY(_stext)
startup_32:
/*
 * Set segments to known values
 */
	cld
	movl $(__KERNEL_DS),%eax
	movl %ax,%ds
	movl %ax,%es
	movl %ax,%fs
	movl %ax,%gs
#ifdef __SMP__
	orw %bx,%bx
	jz 1f
/*
 *	New page tables may be in 4Mbyte page mode and may
 *	be using the global pages. 
 *
 *	NOTE! We have to correct for the fact that we're
 *	not yet offset PAGE_OFFSET..
 */
#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
	movl %cr4,%eax		# Turn on 4Mb pages
	orl cr4_bits,%eax
	movl %eax,%cr4
#endif
/*
 * Setup paging (the tables are already set up, just switch them on)
 */
1:
	movl $0x101000,%eax
	movl %eax,%cr3		/* set the page table pointer.. */
	movl %cr0,%eax
	orl $0x80000000,%eax
	movl %eax,%cr0		/* ..and set paging (PG) bit */
	jmp 1f			/* flush the prefetch-queue */
1:
	movl $1f,%eax
	jmp *%eax		/* make sure eip is relocated */
1:
	/* Set up the stack pointer */
	lss stack_start,%esp

#ifdef __SMP__
	orw  %bx,%bx
	jz  1f				/* Initial CPU cleans BSS */
	pushl $0
	popfl
	jmp checkCPUtype
1:
#endif __SMP__
/*
 * Clear BSS first so that there are no surprises...
 */
	xorl %eax,%eax
	movl $ SYMBOL_NAME(__bss_start),%edi
	movl $ SYMBOL_NAME(_end),%ecx
	subl %edi,%ecx
	cld
	rep
	stosb
/*
 * 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
/*
 * 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
/*
 * Copy bootup parameters out of the way. First 2kB of
 * _empty_zero_page is for boot parameters, second 2kB
 * is for the command line.
 */
	movl $0x90000,%esi
	movl $ SYMBOL_NAME(empty_zero_page),%edi
	movl $512,%ecx
	cld
	rep
	movsl
	xorl %eax,%eax
	movl $512,%ecx
	rep
	stosl
	cmpw $(CL_MAGIC),CL_MAGIC_ADDR
	jne 1f
	movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
	movzwl CL_OFFSET,%esi
	addl $(CL_BASE_ADDR),%esi
	movl $2048,%ecx
	rep
	movsb
1:
#ifdef __SMP__
checkCPUtype:
#endif

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

/*
 * Don't do this here. Do it in the CPU init code in C, right now we
 * must _not_ play unsafe games with the IO ports.
 *
 * A PPro and a P-II will also preserve the flags after a division,
 * so this "cyrix" test is just completely unsafe. IO port 0x22 is
 * some magic ACPI port on non-cyrix chips, so if this trashes that
 * we're screwed.
 *
 * This code belongs in "asm-i386/bugs.h" anyway (at which point we
 * _have_ done a CPUID for CPU's that support it directly, so we'll
 * be able to tell a intel P-II trivially at that point).
 */
#undef CYRIX_CODE_BREAKAGE
#ifdef CYRIX_CODE_BREAKAGE

	/*
	 * A Cyrix preserves flags in cases where other CPUs change
	 * them in undefined ways. We need to know this since we may
	 * need to enable the CPUID instruction at least. (Cyrix chips
	 * prior to M2 have CPUID disabled by default, the Cx486s
	 * didn't have it at all.)
	 */
	xor %ax,%ax
	sahf
	movb $5,%al
	movb $2,%bl
	div %bl
	lahf
	cmpb $2,%ah
	jne ncyrix

	/*
	 * It behaves like a Cyrix so put "Cyrix" in the vendor id
	 * field. It may be overwritten later with the real thing
	 * if CPUID works.
	 */
	movl $0x69727943,X86_VENDOR_ID			# low 4 chars
	movl $0x00000078,X86_VENDOR_ID+4		# next 4 chars

	/*
	 * N.B. The pattern of accesses to 0x22 and 0x23 is *important*
	 *      so do not try and "optimise" it! For the same reason we
	 *	do all this with interrupts off just to be sure.
	 */
#define setCx86(reg, val) \
	movb reg,%al;	\
	outb %al,$0x22;	\
	movb val,%al;	\
	outb %al,$0x23

#define getCx86(reg) \
	movb reg,%al;	\
	outb %al,$0x22;	\
	inb $0x23,%al

	getCx86($0xc3)		# get CCR3
	movb %al,%cl		# Save old value
	movb %al,%bl
	andb $0x0f,%bl		# Enable all config registers (for CCR4 access)
	orb $0x10,%bl
	setCx86($0xc3,%bl)

	getCx86($0xe8)		# CCR4 |= CPUID
	orb $0x80,%al
	movb %al,%bl
	setCx86($0xe8,%bl)

	setCx86($0xc3,%cl)	# Restore old CCR3

ncyrix:

#endif

	movl $3,X86		# at least 386
	pushfl			# push EFLAGS
	popl %eax		# get EFLAGS
	movl %eax,%ecx		# save original EFLAGS
	xorl $0x40000,%eax	# flip AC bit 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
	andl $0x40000,%eax	# check if AC bit changed
	je is386

	movl $4,X86		# at least 486
	movl %ecx,%eax
	xorl $0x200000,%eax	# check ID flag
	pushl %eax
	popfl			# if we are on a straight 486DX, SX, or
	pushfl			# 487SX we can't change it
	popl %eax
	xorl %ecx,%eax
	pushl %ecx		# restore original EFLAGS
	popfl
	andl $0x200000,%eax
	je nocpuid

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

	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

nocpuid:

#ifdef CYRIX_CODE_BREAKAGE
	/*
	 * Even if we had CPUID Cyrix tries to look compatible with
	 * Intel so we have to go elsewhere for the nitty gritty.
	 */
	cmpl $0x69727943,X86_VENDOR_ID		# "Cyri[x.*]"?
	jne is486				# maybe ...

	movb $0xfe,X86_MODEL			# Generic Cx486?
	movb $0,X86_MASK

	getCx86($0xc3)		# Test for DEVID by writing CCR3
	movb %al,%cl
	movb %al,%bl
	orb $0x80,%bl
	setCx86($0xc3,%bl)
	getCx86($0xc0)		# dummy to change bus
	getCx86($0xc3)
	cmpb %al,%cl
	je is486		# not writable == no DEVID

	setCx86($0xc3,%cl)	# restore CCR3

	getCx86($0xff)		# get DEVID in preference to any CPUID
	movb %al,X86_MASK
	getCx86($0xfe)
	movb %al,X86_MODEL
	andb $0xf0,%al		# Check for 6x86(L)
	cmp $0x30,%al
	jnz is486
	getCx86($0xe9)		# CCR5: reset SLOP bit, so that the udelay loop
	andb $0xfd,%al		# works well on 6x86(L) CPU's.
	movb %al,%bl
	setCx86($0xe9,%bl)
#endif

is486:
	movl %cr0,%eax		# 486 or better
	andl $0x80000011,%eax	# Save PG,PE,ET
	orl $0x50022,%eax	# set AM, WP, NE and MP
	jmp 2f

is386:	pushl %ecx		# restore original EFLAGS
	popfl
	movl %cr0,%eax		# 386
	andl $0x80000011,%eax	# Save PG,PE,ET
	orl $2,%eax		# set MP
2:	movl %eax,%cr0
	call check_x87
#ifdef __SMP__
	movb ready,%al		# First CPU if 0
	orb %al,%al
	jz 4f			# First CPU skip this stuff
	movl %cr4,%eax		# Turn on 4Mb pages
	orl $16,%eax
	movl %eax,%cr4
	movl %cr3,%eax		# Intel specification clarification says
	movl %eax,%cr3		# to do this. Maybe it makes a difference.
				# Who knows ?
#endif
4:
#ifdef __SMP__
	incb ready
#endif
	lgdt gdt_descr
	lidt idt_descr
	ljmp $(__KERNEL_CS),$1f
1:	movl $(__KERNEL_DS),%eax	# reload all the segment registers
	movl %ax,%ds		# after changing gdt.
	movl %ax,%es
	movl %ax,%fs
	movl %ax,%gs
#ifdef __SMP__
	movl $(__KERNEL_DS), %eax
	mov  %ax,%ss		# Reload the stack pointer (segment only)
#else
	lss stack_start,%esp	# Load processor stack
#endif
	xorl %eax,%eax
	lldt %ax
	pushl %eax		# These are the parameters to main :-)
	pushl %eax
	pushl %eax
	cld			# gcc2 wants the direction flag cleared at all times
	call SYMBOL_NAME(start_kernel)
L6:
	jmp L6			# main should never return here, but
				# just in case, we know what happens.

#ifdef __SMP__
ready:	.byte 0
#endif

/*
 * 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.
 */
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 SYMBOL_NAME(idt_table),%edi
	mov $256,%ecx
rp_sidt:
	movl %eax,(%edi)
	movl %edx,4(%edi)
	addl $8,%edi
	dec %ecx
	jne rp_sidt
	ret

ENTRY(stack_start)
	.long SYMBOL_NAME(init_task_union)+8192
	.long __KERNEL_DS

/* This is the default interrupt "handler" :-) */
int_msg:
	.asciz "Unknown interrupt\n"
	ALIGN
ignore_int:
	cld
	pushl %eax
	pushl %ecx
	pushl %edx
	pushl %es
	pushl %ds
	movl $(__KERNEL_DS),%eax
	movl %ax,%ds
	movl %ax,%es
	pushl $int_msg
	call SYMBOL_NAME(printk)
	popl %eax
	popl %ds
	popl %es
	popl %edx
	popl %ecx
	popl %eax
	iret

/*
 * The interrupt descriptor table has room for 256 idt's,
 * the global descriptor table is dependent on the number
 * of tasks we can have..
 */
#define IDT_ENTRIES	256
#define GDT_ENTRIES	(12+2*NR_TASKS)


.globl SYMBOL_NAME(idt)
.globl SYMBOL_NAME(gdt)

	ALIGN
	.word 0
idt_descr:
	.word IDT_ENTRIES*8-1		# idt contains 256 entries
SYMBOL_NAME(idt):
	.long SYMBOL_NAME(idt_table)

	.word 0
gdt_descr:
	.word GDT_ENTRIES*8-1
SYMBOL_NAME(gdt):
	.long SYMBOL_NAME(gdt_table)

/*
 * This is initialized to create a identity-mapping at 0-4M (for bootup
 * purposes) and another mapping of the 0-4M area at virtual address
 * PAGE_OFFSET.
 */
.org 0x1000
ENTRY(swapper_pg_dir)
	.long 0x00102007
	.fill __USER_PGD_PTRS-1,4,0
	/* default: 767 entries */
	.long 0x00102007
	/* default: 255 entries */
	.fill __KERNEL_PGD_PTRS-1,4,0

/*
 * The page tables are initialized to only 4MB here - the final page
 * tables are set up later depending on memory size. The "007" at the
 * end doesn't mean with right to kill, but PRESENT+RW+USER
 */
.org 0x2000
ENTRY(pg0)
	.long 0x000007,0x001007,0x002007,0x003007,0x004007,0x005007,0x006007,0x007007
	.long 0x008007,0x009007,0x00a007,0x00b007,0x00c007,0x00d007,0x00e007,0x00f007
	.long 0x010007,0x011007,0x012007,0x013007,0x014007,0x015007,0x016007,0x017007
	.long 0x018007,0x019007,0x01a007,0x01b007,0x01c007,0x01d007,0x01e007,0x01f007
	.long 0x020007,0x021007,0x022007,0x023007,0x024007,0x025007,0x026007,0x027007
	.long 0x028007,0x029007,0x02a007,0x02b007,0x02c007,0x02d007,0x02e007,0x02f007
	.long 0x030007,0x031007,0x032007,0x033007,0x034007,0x035007,0x036007,0x037007
	.long 0x038007,0x039007,0x03a007,0x03b007,0x03c007,0x03d007,0x03e007,0x03f007
	.long 0x040007,0x041007,0x042007,0x043007,0x044007,0x045007,0x046007,0x047007
	.long 0x048007,0x049007,0x04a007,0x04b007,0x04c007,0x04d007,0x04e007,0x04f007
	.long 0x050007,0x051007,0x052007,0x053007,0x054007,0x055007,0x056007,0x057007
	.long 0x058007,0x059007,0x05a007,0x05b007,0x05c007,0x05d007,0x05e007,0x05f007
	.long 0x060007,0x061007,0x062007,0x063007,0x064007,0x065007,0x066007,0x067007
	.long 0x068007,0x069007,0x06a007,0x06b007,0x06c007,0x06d007,0x06e007,0x06f007
	.long 0x070007,0x071007,0x072007,0x073007,0x074007,0x075007,0x076007,0x077007
	.long 0x078007,0x079007,0x07a007,0x07b007,0x07c007,0x07d007,0x07e007,0x07f007
	.long 0x080007,0x081007,0x082007,0x083007,0x084007,0x085007,0x086007,0x087007
	.long 0x088007,0x089007,0x08a007,0x08b007,0x08c007,0x08d007,0x08e007,0x08f007
	.long 0x090007,0x091007,0x092007,0x093007,0x094007,0x095007,0x096007,0x097007
	.long 0x098007,0x099007,0x09a007,0x09b007,0x09c007,0x09d007,0x09e007,0x09f007
	.long 0x0a0007,0x0a1007,0x0a2007,0x0a3007,0x0a4007,0x0a5007,0x0a6007,0x0a7007
	.long 0x0a8007,0x0a9007,0x0aa007,0x0ab007,0x0ac007,0x0ad007,0x0ae007,0x0af007
	.long 0x0b0007,0x0b1007,0x0b2007,0x0b3007,0x0b4007,0x0b5007,0x0b6007,0x0b7007
	.long 0x0b8007,0x0b9007,0x0ba007,0x0bb007,0x0bc007,0x0bd007,0x0be007,0x0bf007
	.long 0x0c0007,0x0c1007,0x0c2007,0x0c3007,0x0c4007,0x0c5007,0x0c6007,0x0c7007
	.long 0x0c8007,0x0c9007,0x0ca007,0x0cb007,0x0cc007,0x0cd007,0x0ce007,0x0cf007
	.long 0x0d0007,0x0d1007,0x0d2007,0x0d3007,0x0d4007,0x0d5007,0x0d6007,0x0d7007
	.long 0x0d8007,0x0d9007,0x0da007,0x0db007,0x0dc007,0x0dd007,0x0de007,0x0df007
	.long 0x0e0007,0x0e1007,0x0e2007,0x0e3007,0x0e4007,0x0e5007,0x0e6007,0x0e7007
	.long 0x0e8007,0x0e9007,0x0ea007,0x0eb007,0x0ec007,0x0ed007,0x0ee007,0x0ef007
	.long 0x0f0007,0x0f1007,0x0f2007,0x0f3007,0x0f4007,0x0f5007,0x0f6007,0x0f7007
	.long 0x0f8007,0x0f9007,0x0fa007,0x0fb007,0x0fc007,0x0fd007,0x0fe007,0x0ff007
	.long 0x100007,0x101007,0x102007,0x103007,0x104007,0x105007,0x106007,0x107007
	.long 0x108007,0x109007,0x10a007,0x10b007,0x10c007,0x10d007,0x10e007,0x10f007
	.long 0x110007,0x111007,0x112007,0x113007,0x114007,0x115007,0x116007,0x117007
	.long 0x118007,0x119007,0x11a007,0x11b007,0x11c007,0x11d007,0x11e007,0x11f007
	.long 0x120007,0x121007,0x122007,0x123007,0x124007,0x125007,0x126007,0x127007
	.long 0x128007,0x129007,0x12a007,0x12b007,0x12c007,0x12d007,0x12e007,0x12f007
	.long 0x130007,0x131007,0x132007,0x133007,0x134007,0x135007,0x136007,0x137007
	.long 0x138007,0x139007,0x13a007,0x13b007,0x13c007,0x13d007,0x13e007,0x13f007
	.long 0x140007,0x141007,0x142007,0x143007,0x144007,0x145007,0x146007,0x147007
	.long 0x148007,0x149007,0x14a007,0x14b007,0x14c007,0x14d007,0x14e007,0x14f007
	.long 0x150007,0x151007,0x152007,0x153007,0x154007,0x155007,0x156007,0x157007
	.long 0x158007,0x159007,0x15a007,0x15b007,0x15c007,0x15d007,0x15e007,0x15f007
	.long 0x160007,0x161007,0x162007,0x163007,0x164007,0x165007,0x166007,0x167007
	.long 0x168007,0x169007,0x16a007,0x16b007,0x16c007,0x16d007,0x16e007,0x16f007
	.long 0x170007,0x171007,0x172007,0x173007,0x174007,0x175007,0x176007,0x177007
	.long 0x178007,0x179007,0x17a007,0x17b007,0x17c007,0x17d007,0x17e007,0x17f007
	.long 0x180007,0x181007,0x182007,0x183007,0x184007,0x185007,0x186007,0x187007
	.long 0x188007,0x189007,0x18a007,0x18b007,0x18c007,0x18d007,0x18e007,0x18f007
	.long 0x190007,0x191007,0x192007,0x193007,0x194007,0x195007,0x196007,0x197007
	.long 0x198007,0x199007,0x19a007,0x19b007,0x19c007,0x19d007,0x19e007,0x19f007
	.long 0x1a0007,0x1a1007,0x1a2007,0x1a3007,0x1a4007,0x1a5007,0x1a6007,0x1a7007
	.long 0x1a8007,0x1a9007,0x1aa007,0x1ab007,0x1ac007,0x1ad007,0x1ae007,0x1af007
	.long 0x1b0007,0x1b1007,0x1b2007,0x1b3007,0x1b4007,0x1b5007,0x1b6007,0x1b7007
	.long 0x1b8007,0x1b9007,0x1ba007,0x1bb007,0x1bc007,0x1bd007,0x1be007,0x1bf007
	.long 0x1c0007,0x1c1007,0x1c2007,0x1c3007,0x1c4007,0x1c5007,0x1c6007,0x1c7007
	.long 0x1c8007,0x1c9007,0x1ca007,0x1cb007,0x1cc007,0x1cd007,0x1ce007,0x1cf007
	.long 0x1d0007,0x1d1007,0x1d2007,0x1d3007,0x1d4007,0x1d5007,0x1d6007,0x1d7007
	.long 0x1d8007,0x1d9007,0x1da007,0x1db007,0x1dc007,0x1dd007,0x1de007,0x1df007
	.long 0x1e0007,0x1e1007,0x1e2007,0x1e3007,0x1e4007,0x1e5007,0x1e6007,0x1e7007
	.long 0x1e8007,0x1e9007,0x1ea007,0x1eb007,0x1ec007,0x1ed007,0x1ee007,0x1ef007
	.long 0x1f0007,0x1f1007,0x1f2007,0x1f3007,0x1f4007,0x1f5007,0x1f6007,0x1f7007
	.long 0x1f8007,0x1f9007,0x1fa007,0x1fb007,0x1fc007,0x1fd007,0x1fe007,0x1ff007
	.long 0x200007,0x201007,0x202007,0x203007,0x204007,0x205007,0x206007,0x207007
	.long 0x208007,0x209007,0x20a007,0x20b007,0x20c007,0x20d007,0x20e007,0x20f007
	.long 0x210007,0x211007,0x212007,0x213007,0x214007,0x215007,0x216007,0x217007
	.long 0x218007,0x219007,0x21a007,0x21b007,0x21c007,0x21d007,0x21e007,0x21f007
	.long 0x220007,0x221007,0x222007,0x223007,0x224007,0x225007,0x226007,0x227007
	.long 0x228007,0x229007,0x22a007,0x22b007,0x22c007,0x22d007,0x22e007,0x22f007
	.long 0x230007,0x231007,0x232007,0x233007,0x234007,0x235007,0x236007,0x237007
	.long 0x238007,0x239007,0x23a007,0x23b007,0x23c007,0x23d007,0x23e007,0x23f007
	.long 0x240007,0x241007,0x242007,0x243007,0x244007,0x245007,0x246007,0x247007
	.long 0x248007,0x249007,0x24a007,0x24b007,0x24c007,0x24d007,0x24e007,0x24f007
	.long 0x250007,0x251007,0x252007,0x253007,0x254007,0x255007,0x256007,0x257007
	.long 0x258007,0x259007,0x25a007,0x25b007,0x25c007,0x25d007,0x25e007,0x25f007
	.long 0x260007,0x261007,0x262007,0x263007,0x264007,0x265007,0x266007,0x267007
	.long 0x268007,0x269007,0x26a007,0x26b007,0x26c007,0x26d007,0x26e007,0x26f007
	.long 0x270007,0x271007,0x272007,0x273007,0x274007,0x275007,0x276007,0x277007
	.long 0x278007,0x279007,0x27a007,0x27b007,0x27c007,0x27d007,0x27e007,0x27f007
	.long 0x280007,0x281007,0x282007,0x283007,0x284007,0x285007,0x286007,0x287007
	.long 0x288007,0x289007,0x28a007,0x28b007,0x28c007,0x28d007,0x28e007,0x28f007
	.long 0x290007,0x291007,0x292007,0x293007,0x294007,0x295007,0x296007,0x297007
	.long 0x298007,0x299007,0x29a007,0x29b007,0x29c007,0x29d007,0x29e007,0x29f007
	.long 0x2a0007,0x2a1007,0x2a2007,0x2a3007,0x2a4007,0x2a5007,0x2a6007,0x2a7007
	.long 0x2a8007,0x2a9007,0x2aa007,0x2ab007,0x2ac007,0x2ad007,0x2ae007,0x2af007
	.long 0x2b0007,0x2b1007,0x2b2007,0x2b3007,0x2b4007,0x2b5007,0x2b6007,0x2b7007
	.long 0x2b8007,0x2b9007,0x2ba007,0x2bb007,0x2bc007,0x2bd007,0x2be007,0x2bf007
	.long 0x2c0007,0x2c1007,0x2c2007,0x2c3007,0x2c4007,0x2c5007,0x2c6007,0x2c7007
	.long 0x2c8007,0x2c9007,0x2ca007,0x2cb007,0x2cc007,0x2cd007,0x2ce007,0x2cf007
	.long 0x2d0007,0x2d1007,0x2d2007,0x2d3007,0x2d4007,0x2d5007,0x2d6007,0x2d7007
	.long 0x2d8007,0x2d9007,0x2da007,0x2db007,0x2dc007,0x2dd007,0x2de007,0x2df007
	.long 0x2e0007,0x2e1007,0x2e2007,0x2e3007,0x2e4007,0x2e5007,0x2e6007,0x2e7007
	.long 0x2e8007,0x2e9007,0x2ea007,0x2eb007,0x2ec007,0x2ed007,0x2ee007,0x2ef007
	.long 0x2f0007,0x2f1007,0x2f2007,0x2f3007,0x2f4007,0x2f5007,0x2f6007,0x2f7007
	.long 0x2f8007,0x2f9007,0x2fa007,0x2fb007,0x2fc007,0x2fd007,0x2fe007,0x2ff007
	.long 0x300007,0x301007,0x302007,0x303007,0x304007,0x305007,0x306007,0x307007
	.long 0x308007,0x309007,0x30a007,0x30b007,0x30c007,0x30d007,0x30e007,0x30f007
	.long 0x310007,0x311007,0x312007,0x313007,0x314007,0x315007,0x316007,0x317007
	.long 0x318007,0x319007,0x31a007,0x31b007,0x31c007,0x31d007,0x31e007,0x31f007
	.long 0x320007,0x321007,0x322007,0x323007,0x324007,0x325007,0x326007,0x327007
	.long 0x328007,0x329007,0x32a007,0x32b007,0x32c007,0x32d007,0x32e007,0x32f007
	.long 0x330007,0x331007,0x332007,0x333007,0x334007,0x335007,0x336007,0x337007
	.long 0x338007,0x339007,0x33a007,0x33b007,0x33c007,0x33d007,0x33e007,0x33f007
	.long 0x340007,0x341007,0x342007,0x343007,0x344007,0x345007,0x346007,0x347007
	.long 0x348007,0x349007,0x34a007,0x34b007,0x34c007,0x34d007,0x34e007,0x34f007
	.long 0x350007,0x351007,0x352007,0x353007,0x354007,0x355007,0x356007,0x357007
	.long 0x358007,0x359007,0x35a007,0x35b007,0x35c007,0x35d007,0x35e007,0x35f007
	.long 0x360007,0x361007,0x362007,0x363007,0x364007,0x365007,0x366007,0x367007
	.long 0x368007,0x369007,0x36a007,0x36b007,0x36c007,0x36d007,0x36e007,0x36f007
	.long 0x370007,0x371007,0x372007,0x373007,0x374007,0x375007,0x376007,0x377007
	.long 0x378007,0x379007,0x37a007,0x37b007,0x37c007,0x37d007,0x37e007,0x37f007
	.long 0x380007,0x381007,0x382007,0x383007,0x384007,0x385007,0x386007,0x387007
	.long 0x388007,0x389007,0x38a007,0x38b007,0x38c007,0x38d007,0x38e007,0x38f007
	.long 0x390007,0x391007,0x392007,0x393007,0x394007,0x395007,0x396007,0x397007
	.long 0x398007,0x399007,0x39a007,0x39b007,0x39c007,0x39d007,0x39e007,0x39f007
	.long 0x3a0007,0x3a1007,0x3a2007,0x3a3007,0x3a4007,0x3a5007,0x3a6007,0x3a7007
	.long 0x3a8007,0x3a9007,0x3aa007,0x3ab007,0x3ac007,0x3ad007,0x3ae007,0x3af007
	.long 0x3b0007,0x3b1007,0x3b2007,0x3b3007,0x3b4007,0x3b5007,0x3b6007,0x3b7007
	.long 0x3b8007,0x3b9007,0x3ba007,0x3bb007,0x3bc007,0x3bd007,0x3be007,0x3bf007
	.long 0x3c0007,0x3c1007,0x3c2007,0x3c3007,0x3c4007,0x3c5007,0x3c6007,0x3c7007
	.long 0x3c8007,0x3c9007,0x3ca007,0x3cb007,0x3cc007,0x3cd007,0x3ce007,0x3cf007
	.long 0x3d0007,0x3d1007,0x3d2007,0x3d3007,0x3d4007,0x3d5007,0x3d6007,0x3d7007
	.long 0x3d8007,0x3d9007,0x3da007,0x3db007,0x3dc007,0x3dd007,0x3de007,0x3df007
	.long 0x3e0007,0x3e1007,0x3e2007,0x3e3007,0x3e4007,0x3e5007,0x3e6007,0x3e7007
	.long 0x3e8007,0x3e9007,0x3ea007,0x3eb007,0x3ec007,0x3ed007,0x3ee007,0x3ef007
	.long 0x3f0007,0x3f1007,0x3f2007,0x3f3007,0x3f4007,0x3f5007,0x3f6007,0x3f7007
	.long 0x3f8007,0x3f9007,0x3fa007,0x3fb007,0x3fc007,0x3fd007,0x3fe007,0x3ff007

.org 0x3000
ENTRY(empty_bad_page)

.org 0x4000
ENTRY(empty_bad_page_table)

.org 0x5000
ENTRY(empty_zero_page)

.org 0x6000
ENTRY(this_must_match_init_task)

/*
 * This starts the data section. Note that the above is all
 * in the text section because it has alignment requirements
 * that we cannot fulfill any other way.
 */
.data

ALIGN
/* 256 quadwords - 2048 bytes of idt */
ENTRY(idt_table)
	.fill 256,8,0		# idt is uninitialized

/*
 * This contains up to 8192 quadwords depending on NR_TASKS - 64kB of
 * gdt entries.  Ugh. 
 *
 * NOTE! Make sure the gdt descriptor in head.S matches this if you
 * change anything.
 */
ENTRY(gdt_table)
	.quad 0x0000000000000000	/* NULL descriptor */
	.quad 0x0000000000000000	/* not used */
	.quad 0x00cf9a000000ffff	/* 0x10 kernel 4GB code at 0x00000000 */
	.quad 0x00cf92000000ffff	/* 0x18 kernel 4GB data at 0x00000000 */
	.quad 0x00cffa000000ffff	/* 0x23 user   4GB code at 0x00000000 */
	.quad 0x00cff2000000ffff	/* 0x2b user   4GB data at 0x00000000 */
	.quad 0x0000000000000000	/* not used */
	.quad 0x0000000000000000	/* not used */
	.quad 0x00c0920000000000	/* 0x40 APM set up for bad BIOS's */
	.quad 0x00c09a0000000000	/* 0x48 APM CS    code */
	.quad 0x00809a0000000000	/* 0x50 APM CS 16 code (16 bit) */
	.quad 0x00c0920000000000	/* 0x58 APM DS    data */
	.fill 2*NR_TASKS,8,0		/* space for LDT's and TSS's etc */

/*
 * This is to aid debugging, the various locking macros will be putting
 * code fragments here.  When an oops occurs we'd rather know that it's
 * inside the .text.lock section rather than as some offset from whatever
 * function happens to be last in the .text segment.
 */
.section .text.lock
ENTRY(stext_lock)
