blob: d81bcc6f8f4cad9a66790f2b63c3d199790d3a05 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
Simon Glass463fac22014-10-10 08:21:55 -06002/*
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
Simon Glass463fac22014-10-10 08:21:55 -06007 */
8
Simon Glass463fac22014-10-10 08:21:55 -06009#include <asm/msr-index.h>
10#include <asm/processor-flags.h>
11
12.code32
Simon Glass74c27372020-12-23 08:11:27 -070013.section .text_call64
Simon Glass463fac22014-10-10 08:21:55 -060014.globl cpu_call64
15cpu_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
76code64:
77lret_target:
78 pop %eax /* target */
79 mov %eax, %eax /* Clear bits 63:32 */
80 jmp *%eax /* Jump to the 64-bit target */
81
Bin Meng17b7b602019-01-31 08:22:13 -080082.globl call64_stub_size
83call64_stub_size:
84 .long . - cpu_call64
85
Simon Glass463fac22014-10-10 08:21:55 -060086 .data
Simon Glass1e32ede2017-01-16 07:04:15 -070087 .align 16
88 .globl gdt64
89gdt64:
Simon Glass463fac22014-10-10 08:21:55 -060090gdt:
Simon Glassf2d1a112015-07-31 09:31:30 -060091 .word gdt_end - gdt - 1
92 .long gdt /* Fixed up by code above */
Simon Glass463fac22014-10-10 08:21:55 -060093 .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 */
99gdt_end: