• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/x86/kernel/
1/*
2 *
3 *	Trampoline.S	Derived from Setup.S by Linus Torvalds
4 *
5 *	4 Jan 1997 Michael Chastain: changed to gnu as.
6 *	15 Sept 2005 Eric Biederman: 64bit PIC support
7 *
8 *	Entry: CS:IP point to the start of our code, we are
9 *	in real mode with no stack, but the rest of the
10 *	trampoline page to make our stack and everything else
11 *	is a mystery.
12 *
13 *	On entry to trampoline_data, the processor is in real mode
14 *	with 16-bit addressing and 16-bit data.  CS has some value
15 *	and IP is zero.  Thus, data addresses need to be absolute
16 *	(no relocation) and are taken with regard to r_base.
17 *
18 *	With the addition of trampoline_level4_pgt this code can
19 *	now enter a 64bit kernel that lives at arbitrary 64bit
20 *	physical addresses.
21 *
22 *	If you work on this file, check the object module with objdump
23 *	--full-contents --reloc to make sure there are no relocation
24 *	entries.
25 */
26
27#include <linux/linkage.h>
28#include <linux/init.h>
29#include <asm/pgtable_types.h>
30#include <asm/page_types.h>
31#include <asm/msr.h>
32#include <asm/segment.h>
33#include <asm/processor-flags.h>
34
35#ifdef CONFIG_ACPI_SLEEP
36.section .rodata, "a", @progbits
37#else
38/* We can free up the trampoline after bootup if cpu hotplug is not supported. */
39__CPUINITRODATA
40#endif
41.code16
42
43ENTRY(trampoline_data)
44r_base = .
45	cli			# We should be safe anyway
46	wbinvd
47	mov	%cs, %ax	# Code and data in the same place
48	mov	%ax, %ds
49	mov	%ax, %es
50	mov	%ax, %ss
51
52
53	movl	$0xA5A5A5A5, trampoline_data - r_base
54				# write marker for master knows we're running
55
56					# Setup stack
57	movw	$(trampoline_stack_end - r_base), %sp
58
59	call	verify_cpu		# Verify the cpu supports long mode
60	testl   %eax, %eax		# Check for return code
61	jnz	no_longmode
62
63	mov	%cs, %ax
64	movzx	%ax, %esi		# Find the 32bit trampoline location
65	shll	$4, %esi
66
67					# Fixup the vectors
68	addl	%esi, startup_32_vector - r_base
69	addl	%esi, startup_64_vector - r_base
70	addl	%esi, tgdt + 2 - r_base	# Fixup the gdt pointer
71
72	/*
73	 * GDT tables in non default location kernel can be beyond 16MB and
74	 * lgdt will not be able to load the address as in real mode default
75	 * operand size is 16bit. Use lgdtl instead to force operand size
76	 * to 32 bit.
77	 */
78
79	lidtl	tidt - r_base	# load idt with 0, 0
80	lgdtl	tgdt - r_base	# load gdt with whatever is appropriate
81
82	mov	$X86_CR0_PE, %ax	# protected mode (PE) bit
83	lmsw	%ax			# into protected mode
84
85	# flush prefetch and jump to startup_32
86	ljmpl	*(startup_32_vector - r_base)
87
88	.code32
89	.balign 4
90startup_32:
91	movl	$__KERNEL_DS, %eax	# Initialize the %ds segment register
92	movl	%eax, %ds
93
94	movl	$X86_CR4_PAE, %eax
95	movl	%eax, %cr4		# Enable PAE mode
96
97					# Setup trampoline 4 level pagetables
98	leal	(trampoline_level4_pgt - r_base)(%esi), %eax
99	movl	%eax, %cr3
100
101	movl	$MSR_EFER, %ecx
102	movl	$(1 << _EFER_LME), %eax	# Enable Long Mode
103	xorl	%edx, %edx
104	wrmsr
105
106	# Enable paging and in turn activate Long Mode
107	# Enable protected mode
108	movl	$(X86_CR0_PG | X86_CR0_PE), %eax
109	movl	%eax, %cr0
110
111	/*
112	 * At this point we're in long mode but in 32bit compatibility mode
113	 * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
114	 * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use
115	 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
116	 */
117	ljmp	*(startup_64_vector - r_base)(%esi)
118
119	.code64
120	.balign 4
121startup_64:
122	# Now jump into the kernel using virtual addresses
123	movq	$secondary_startup_64, %rax
124	jmp	*%rax
125
126	.code16
127no_longmode:
128	hlt
129	jmp no_longmode
130#include "verify_cpu_64.S"
131
132	# Careful these need to be in the same 64K segment as the above;
133tidt:
134	.word	0			# idt limit = 0
135	.word	0, 0			# idt base = 0L
136
137	# Duplicate the global descriptor table
138	# so the kernel can live anywhere
139	.balign 4
140tgdt:
141	.short	tgdt_end - tgdt		# gdt limit
142	.long	tgdt - r_base
143	.short 0
144	.quad	0x00cf9b000000ffff	# __KERNEL32_CS
145	.quad	0x00af9b000000ffff	# __KERNEL_CS
146	.quad	0x00cf93000000ffff	# __KERNEL_DS
147tgdt_end:
148
149	.balign 4
150startup_32_vector:
151	.long	startup_32 - r_base
152	.word	__KERNEL32_CS, 0
153
154	.balign 4
155startup_64_vector:
156	.long	startup_64 - r_base
157	.word	__KERNEL_CS, 0
158
159trampoline_stack:
160	.org 0x1000
161trampoline_stack_end:
162ENTRY(trampoline_level4_pgt)
163	.quad	level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
164	.fill	510,8,0
165	.quad	level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
166
167ENTRY(trampoline_end)
168