]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/x86/cpu/call64.S
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / x86 / cpu / call64.S
1 /*
2  * (C) Copyright 2014 Google, Inc
3  * Copyright (C) 1991, 1992, 1993  Linus Torvalds
4  *
5  * Parts of this copied from Linux arch/x86/boot/compressed/head_64.S
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <asm/global_data.h>
11 #include <asm/msr-index.h>
12 #include <asm/processor-flags.h>
13
14 .code32
15 .globl cpu_call64
16 cpu_call64:
17         /*
18          * cpu_call64(ulong pgtable, ulong setup_base, ulong target)
19          *
20          * eax - pgtable
21          * edx - setup_base
22          * ecx - target
23          */
24         cli
25         push    %ecx            /* arg2 = target */
26         push    %edx            /* arg1 = setup_base */
27         mov     %eax, %ebx
28
29         /* Load new GDT with the 64bit segments using 32bit descriptor */
30         leal    gdt, %eax
31         movl    %eax, gdt+2
32         lgdt    gdt
33
34         /* Enable PAE mode */
35         movl    $(X86_CR4_PAE), %eax
36         movl    %eax, %cr4
37
38         /* Enable the boot page tables */
39         leal    (%ebx), %eax
40         movl    %eax, %cr3
41
42         /* Enable Long mode in EFER (Extended Feature Enable Register) */
43         movl    $MSR_EFER, %ecx
44         rdmsr
45         btsl    $_EFER_LME, %eax
46         wrmsr
47
48         /* After gdt is loaded */
49         xorl    %eax, %eax
50         lldt    %ax
51         movl    $0x20, %eax
52         ltr     %ax
53
54         /*
55          * Setup for the jump to 64bit mode
56          *
57          * When the jump is performed we will be in long mode but
58          * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
59          * (and in turn EFER.LMA = 1). To jump into 64bit mode we use
60          * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
61          * We place all of the values on our mini stack so lret can
62          * used to perform that far jump. See the gdt below.
63          */
64         pop     %esi                    /* setup_base */
65
66         pushl   $0x10
67         leal    lret_target, %eax
68         pushl   %eax
69
70         /* Enter paged protected Mode, activating Long Mode */
71         movl    $(X86_CR0_PG | X86_CR0_PE), %eax
72         movl    %eax, %cr0
73
74         /* Jump from 32bit compatibility mode into 64bit mode. */
75         lret
76
77 code64:
78 lret_target:
79         pop     %eax                    /* target */
80         mov     %eax, %eax              /* Clear bits 63:32 */
81         jmp     *%eax                   /* Jump to the 64-bit target */
82
83         .data
84 gdt:
85         .word   gdt_end - gdt
86         .long   gdt
87         .word   0
88         .quad   0x0000000000000000      /* NULL descriptor */
89         .quad   0x00af9a000000ffff      /* __KERNEL_CS */
90         .quad   0x00cf92000000ffff      /* __KERNEL_DS */
91         .quad   0x0080890000000000      /* TS descriptor */
92         .quad   0x0000000000000000      /* TS continued */
93 gdt_end: