| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * | 
|  | 3 | *	Trampoline.S	Derived from Setup.S by Linus Torvalds | 
|  | 4 | * | 
|  | 5 | *	4 Jan 1997 Michael Chastain: changed to gnu as. | 
|  | 6 | * | 
|  | 7 | *	Entry: CS:IP point to the start of our code, we are | 
|  | 8 | *	in real mode with no stack, but the rest of the | 
|  | 9 | *	trampoline page to make our stack and everything else | 
|  | 10 | *	is a mystery. | 
|  | 11 | * | 
|  | 12 | *	In fact we don't actually need a stack so we don't | 
|  | 13 | *	set one up. | 
|  | 14 | * | 
|  | 15 | *	On entry to trampoline_data, the processor is in real mode | 
|  | 16 | *	with 16-bit addressing and 16-bit data.  CS has some value | 
|  | 17 | *	and IP is zero.  Thus, data addresses need to be absolute | 
|  | 18 | *	(no relocation) and are taken with regard to r_base. | 
|  | 19 | * | 
|  | 20 | *	If you work on this file, check the object module with objdump | 
|  | 21 | *	--full-contents --reloc to make sure there are no relocation | 
|  | 22 | *	entries. For the GDT entry we do hand relocation in smpboot.c | 
|  | 23 | *	because of 64bit linker limitations. | 
|  | 24 | */ | 
|  | 25 |  | 
|  | 26 | #include <linux/linkage.h> | 
|  | 27 | #include <asm/segment.h> | 
|  | 28 | #include <asm/page.h> | 
|  | 29 |  | 
|  | 30 | .data | 
|  | 31 |  | 
|  | 32 | .code16 | 
|  | 33 |  | 
|  | 34 | ENTRY(trampoline_data) | 
|  | 35 | r_base = . | 
|  | 36 | wbinvd | 
|  | 37 | mov	%cs, %ax	# Code and data in the same place | 
|  | 38 | mov	%ax, %ds | 
|  | 39 |  | 
|  | 40 | cli			# We should be safe anyway | 
|  | 41 |  | 
|  | 42 | movl	$0xA5A5A5A5, trampoline_data - r_base | 
|  | 43 | # write marker for master knows we're running | 
|  | 44 |  | 
| Vivek Goyal | 983d5db | 2006-01-12 03:35:20 +0100 | [diff] [blame] | 45 | /* | 
|  | 46 | * GDT tables in non default location kernel can be beyond 16MB and | 
|  | 47 | * lgdt will not be able to load the address as in real mode default | 
|  | 48 | * operand size is 16bit. Use lgdtl instead to force operand size | 
|  | 49 | * to 32 bit. | 
|  | 50 | */ | 
|  | 51 |  | 
|  | 52 | lidtl	idt_48 - r_base	# load idt with 0, 0 | 
|  | 53 | lgdtl	gdt_48 - r_base	# load gdt with whatever is appropriate | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 |  | 
|  | 55 | xor	%ax, %ax | 
|  | 56 | inc	%ax		# protected mode (PE) bit | 
|  | 57 | lmsw	%ax		# into protected mode | 
|  | 58 | # flaush prefetch and jump to startup_32 in arch/x86_64/kernel/head.S | 
|  | 59 | ljmpl	$__KERNEL32_CS, $(startup_32-__START_KERNEL_map) | 
|  | 60 |  | 
|  | 61 | # Careful these need to be in the same 64K segment as the above; | 
|  | 62 | idt_48: | 
|  | 63 | .word	0			# idt limit = 0 | 
|  | 64 | .word	0, 0			# idt base = 0L | 
|  | 65 |  | 
|  | 66 | gdt_48: | 
| Eric W. Biederman | 29a6c25 | 2006-09-26 10:52:32 +0200 | [diff] [blame^] | 67 | .short	GDT_ENTRIES*8 - 1	# gdt limit | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 68 | .long	cpu_gdt_table-__START_KERNEL_map | 
|  | 69 |  | 
|  | 70 | .globl trampoline_end | 
|  | 71 | trampoline_end: |