blob: c722acbd31084750cb0d94eada2f11229f31d994 [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>
Simon Glasse00a0332025-03-15 14:25:38 +000010#include <asm/processor.h>
Simon Glass463fac22014-10-10 08:21:55 -060011#include <asm/processor-flags.h>
12
13.code32
Sam Edwards7cc2ef92025-03-15 15:18:05 -070014.section .text_call64, "ax"
Simon Glass463fac22014-10-10 08:21:55 -060015.globl cpu_call64
16cpu_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
Simon Glass46faeea2025-03-15 14:25:37 +000029 # disable paging
30 movl %cr0, %eax
31 andl $~X86_CR0_PG, %eax
32 movl %eax, %cr0
33
Simon Glass463fac22014-10-10 08:21:55 -060034 /* 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
Simon Glass463fac22014-10-10 08:21:55 -060048 /*
49 * Setup for the jump to 64bit mode
50 *
51 * When the jump is performed we will be in long mode but
52 * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
53 * (and in turn EFER.LMA = 1). To jump into 64bit mode we use
54 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
55 * We place all of the values on our mini stack so lret can
56 * used to perform that far jump. See the gdt below.
57 */
58 pop %esi /* setup_base */
59
Simon Glasse00a0332025-03-15 14:25:38 +000060 pushl $(X86_GDT_ENTRY_64BIT_CS * X86_GDT_ENTRY_SIZE)
Simon Glass463fac22014-10-10 08:21:55 -060061 leal lret_target, %eax
62 pushl %eax
63
64 /* Enter paged protected Mode, activating Long Mode */
Simon Glass46faeea2025-03-15 14:25:37 +000065 movl %cr0, %eax
66 orl $X86_CR0_PG, %eax
Simon Glass463fac22014-10-10 08:21:55 -060067 movl %eax, %cr0
68
69 /* Jump from 32bit compatibility mode into 64bit mode. */
70 lret
71
72code64:
73lret_target:
74 pop %eax /* target */
75 mov %eax, %eax /* Clear bits 63:32 */
76 jmp *%eax /* Jump to the 64-bit target */
77
Bin Meng17b7b602019-01-31 08:22:13 -080078.globl call64_stub_size
79call64_stub_size:
80 .long . - cpu_call64
81
Simon Glass463fac22014-10-10 08:21:55 -060082 .data
Simon Glass1e32ede2017-01-16 07:04:15 -070083 .align 16
84 .globl gdt64
85gdt64:
Simon Glass463fac22014-10-10 08:21:55 -060086gdt:
Simon Glassf2d1a112015-07-31 09:31:30 -060087 .word gdt_end - gdt - 1
88 .long gdt /* Fixed up by code above */
Simon Glass463fac22014-10-10 08:21:55 -060089 .word 0
90 .quad 0x0000000000000000 /* NULL descriptor */
91 .quad 0x00af9a000000ffff /* __KERNEL_CS */
92 .quad 0x00cf92000000ffff /* __KERNEL_DS */
93 .quad 0x0080890000000000 /* TS descriptor */
94 .quad 0x0000000000000000 /* TS continued */
95gdt_end: