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