diff options
author | Simon Glass <sjg@chromium.org> | 2017-01-16 07:04:19 -0700 |
---|---|---|
committer | Bin Meng <bmeng.cn@gmail.com> | 2017-02-07 13:07:33 +0800 |
commit | 8cfc966c777ae0effaeea40a96d62034b2f86b91 (patch) | |
tree | 7905e0e6c58ce4e475a3a5641e317bf2ab7b77fc /arch/x86/cpu/i386 | |
parent | 337705833c8f73560af8f4c163ed6b0d9e5440af (diff) | |
download | u-boot-imx-8cfc966c777ae0effaeea40a96d62034b2f86b91.zip u-boot-imx-8cfc966c777ae0effaeea40a96d62034b2f86b91.tar.gz u-boot-imx-8cfc966c777ae0effaeea40a96d62034b2f86b91.tar.bz2 |
x86: Move call64 to the i386 directory
This code is only used in 32-bit mode. Move it so that it does not get
built with 64-bit U-Boot.
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch/x86/cpu/i386')
-rw-r--r-- | arch/x86/cpu/i386/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/cpu/i386/call64.S | 96 |
2 files changed, 97 insertions, 0 deletions
diff --git a/arch/x86/cpu/i386/Makefile b/arch/x86/cpu/i386/Makefile index d336495..2547bba 100644 --- a/arch/x86/cpu/i386/Makefile +++ b/arch/x86/cpu/i386/Makefile @@ -3,5 +3,6 @@ # Written by Simon Glass <sjg@chromium.org> # +obj-y += call64.o obj-y += cpu.o obj-y += interrupt.o diff --git a/arch/x86/cpu/i386/call64.S b/arch/x86/cpu/i386/call64.S new file mode 100644 index 0000000..970c461 --- /dev/null +++ b/arch/x86/cpu/i386/call64.S @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2014 Google, Inc + * Copyright (C) 1991, 1992, 1993 Linus Torvalds + * + * Parts of this copied from Linux arch/x86/boot/compressed/head_64.S + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/global_data.h> +#include <asm/msr-index.h> +#include <asm/processor-flags.h> + +.code32 +.globl cpu_call64 +cpu_call64: + /* + * cpu_call64(ulong pgtable, ulong setup_base, ulong target) + * + * eax - pgtable + * edx - setup_base + * ecx - target + */ + cli + push %ecx /* arg2 = target */ + push %edx /* arg1 = setup_base */ + mov %eax, %ebx + + /* Load new GDT with the 64bit segments using 32bit descriptor */ + leal gdt, %eax + movl %eax, gdt+2 + lgdt gdt + + /* Enable PAE mode */ + movl $(X86_CR4_PAE), %eax + movl %eax, %cr4 + + /* Enable the boot page tables */ + leal (%ebx), %eax + movl %eax, %cr3 + + /* Enable Long mode in EFER (Extended Feature Enable Register) */ + movl $MSR_EFER, %ecx + rdmsr + btsl $_EFER_LME, %eax + wrmsr + + /* After gdt is loaded */ + xorl %eax, %eax + lldt %ax + movl $0x20, %eax + ltr %ax + + /* + * Setup for the jump to 64bit mode + * + * When the jump is performed we will be in long mode but + * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1 + * (and in turn EFER.LMA = 1). To jump into 64bit mode we use + * the new gdt/idt that has __KERNEL_CS with CS.L = 1. + * We place all of the values on our mini stack so lret can + * used to perform that far jump. See the gdt below. + */ + pop %esi /* setup_base */ + + pushl $0x10 + leal lret_target, %eax + pushl %eax + + /* Enter paged protected Mode, activating Long Mode */ + movl $(X86_CR0_PG | X86_CR0_PE), %eax + movl %eax, %cr0 + + /* Jump from 32bit compatibility mode into 64bit mode. */ + lret + +code64: +lret_target: + pop %eax /* target */ + mov %eax, %eax /* Clear bits 63:32 */ + jmp *%eax /* Jump to the 64-bit target */ + + .data + .align 16 + .globl gdt64 +gdt64: +gdt: + .word gdt_end - gdt - 1 + .long gdt /* Fixed up by code above */ + .word 0 + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x00af9a000000ffff /* __KERNEL_CS */ + .quad 0x00cf92000000ffff /* __KERNEL_DS */ + .quad 0x0080890000000000 /* TS descriptor */ + .quad 0x0000000000000000 /* TS continued */ +gdt_end: |