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