trampoline_64.S revision 48927bbb97c7d4cf343c05827ab9ac30c60678cb
148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen/*
248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *
348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	Trampoline.S	Derived from Setup.S by Linus Torvalds
448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *
548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	4 Jan 1997 Michael Chastain: changed to gnu as.
648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	15 Sept 2005 Eric Biederman: 64bit PIC support
748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *
848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	Entry: CS:IP point to the start of our code, we are
948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	in real mode with no stack, but the rest of the
1048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	trampoline page to make our stack and everything else
1148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	is a mystery.
1248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *
1348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	On entry to trampoline_data, the processor is in real mode
1448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	with 16-bit addressing and 16-bit data.  CS has some value
1548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	and IP is zero.  Thus, data addresses need to be absolute
1648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	(no relocation) and are taken with regard to r_base.
1748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *
1848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	With the addition of trampoline_level4_pgt this code can
1948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	now enter a 64bit kernel that lives at arbitrary 64bit
2048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	physical addresses.
2148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *
2248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	If you work on this file, check the object module with objdump
2348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	--full-contents --reloc to make sure there are no relocation
2448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen *	entries.
2548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen */
2648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
2748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include <linux/linkage.h>
2848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include <linux/init.h>
2948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include <asm/pgtable_types.h>
3048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include <asm/page_types.h>
3148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include <asm/msr.h>
3248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include <asm/segment.h>
3348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include <asm/processor-flags.h>
3448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
3548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.text
3648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.balign PAGE_SIZE
3748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.code16
3848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
3948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko SakkinenENTRY(trampoline_data)
4048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	cli			# We should be safe anyway
4148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	wbinvd
4248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
4348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.byte	0xea		# ljmpw
4448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.word	1f		# Offset
4548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.word	real_mode_seg	# Segment
4648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen1:
4748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	mov	%cs, %ax	# Code and data in the same place
4848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	mov	%ax, %ds
4948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	mov	%ax, %es
5048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	mov	%ax, %ss
5148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
5248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	$0xA5A5A5A5, trampoline_status
5348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# write marker for master knows we're running
5448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
5548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# Setup stack
5648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movw	$trampoline_stack_end, %sp
5748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
5848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	call	verify_cpu		# Verify the cpu supports long mode
5948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	testl   %eax, %eax		# Check for return code
6048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	jnz	no_longmode
6148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
6248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	/*
6348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * GDT tables in non default location kernel can be beyond 16MB and
6448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * lgdt will not be able to load the address as in real mode default
6548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * operand size is 16bit. Use lgdtl instead to force operand size
6648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * to 32 bit.
6748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 */
6848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
6948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	lidtl	tidt	# load idt with 0, 0
7048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	lgdtl	tgdt	# load gdt with whatever is appropriate
7148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
7248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	mov	$X86_CR0_PE, %ax	# protected mode (PE) bit
7348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	lmsw	%ax			# into protected mode
7448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
7548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# flush prefetch and jump to startup_32
7648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	ljmpl	*(startup_32_vector)
7748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
7848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinenno_longmode:
7948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	hlt
8048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	jmp no_longmode
8148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen#include "../kernel/verify_cpu.S"
8248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
8348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.code32
8448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.balign 4
8548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko SakkinenENTRY(startup_32)
8648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	$__KERNEL_DS, %eax	# Initialize the %ds segment register
8748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	%eax, %ds
8848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
8948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	$X86_CR4_PAE, %eax
9048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	%eax, %cr4		# Enable PAE mode
9148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
9248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	pa_startup_64_smp, %esi
9348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	pa_startup_64_smp_high, %edi
9448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
9548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen					# Setup trampoline 4 level pagetables
9648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	leal	pa_trampoline_level4_pgt, %eax
9748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	%eax, %cr3
9848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
9948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	$MSR_EFER, %ecx
10048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	$(1 << _EFER_LME), %eax	# Enable Long Mode
10148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	xorl	%edx, %edx
10248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	wrmsr
10348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
10448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# Enable paging and in turn activate Long Mode
10548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# Enable protected mode
10648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	$(X86_CR0_PG | X86_CR0_PE), %eax
10748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	%eax, %cr0
10848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
10948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	/*
11048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * At this point we're in long mode but in 32bit compatibility mode
11148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
11248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use
11348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
11448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	 */
11548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	ljmpl	*(pa_startup_64_vector)
11648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
11748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.code64
11848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.balign 4
11948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko SakkinenENTRY(startup_64)
12048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# Now jump into the kernel using virtual addresses
12148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	movl	%edi, %eax
12248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	shlq	$32, %rax
12348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	addl	%esi, %eax
12448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	jmp	*%rax
12548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
12648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# Careful these need to be in the same 64K segment as the above;
12748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinentidt:
12848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.word	0			# idt limit = 0
12948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.word	0, 0			# idt base = 0L
13048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
13148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# Duplicate the global descriptor table
13248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	# so the kernel can live anywhere
13348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.balign 4
13448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.globl tgdt
13548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinentgdt:
13648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.short	tgdt_end - tgdt		# gdt limit
13748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.long	pa_tgdt
13848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.short	0
13948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.quad	0x00cf9b000000ffff	# __KERNEL32_CS
14048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.quad	0x00af9b000000ffff	# __KERNEL_CS
14148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.quad	0x00cf93000000ffff	# __KERNEL_DS
14248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinentgdt_end:
14348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
14448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.balign 4
14548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinenstartup_32_vector:
14648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.long	pa_startup_32
14748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.word	__KERNEL32_CS, 0
14848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
14948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.balign 4
15048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.globl startup_64_vector
15148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinenstartup_64_vector:
15248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.long	pa_startup_64
15348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.word	__KERNEL_CS, 0
15448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
15548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.data
15648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
15748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.balign 4
15848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko SakkinenENTRY(trampoline_status)
15948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.long	0
16048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
16148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinentrampoline_stack:
16248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.org 0x1000
16348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinentrampoline_stack_end:
16448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
16548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.globl	level3_ident_pgt
16648927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.globl	level3_kernel_pgt
16748927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko SakkinenENTRY(trampoline_level4_pgt)
16848927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	level3_ident_pgt:	.quad	0
16948927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.fill 510,8,0
17048927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	level3_kernel_pgt:	.quad	0
17148927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen
17248927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.globl	startup_64_smp
17348927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinen	.globl	startup_64_smp_high
17448927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinenstartup_64_smp:		.long 0
17548927bbb97c7d4cf343c05827ab9ac30c60678cbJarkko Sakkinenstartup_64_smp_high:	.long 0
176