blob: a9d3f16a6ad11cc015009d3549faa6e9448f76fb [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
Simon Glass355dae22025-03-15 14:25:39 +000025 pushl $0 /* top 64-bits of target */
Simon Glass463fac22014-10-10 08:21:55 -060026 push %ecx /* arg2 = target */
27 push %edx /* arg1 = setup_base */
28 mov %eax, %ebx
29
Simon Glass46faeea2025-03-15 14:25:37 +000030 # disable paging
31 movl %cr0, %eax
32 andl $~X86_CR0_PG, %eax
33 movl %eax, %cr0
34
Simon Glass463fac22014-10-10 08:21:55 -060035 /* Enable PAE mode */
Simon Glass355dae22025-03-15 14:25:39 +000036 movl %cr4, %eax
37 orl $X86_CR4_PAE, %eax
Simon Glass463fac22014-10-10 08:21:55 -060038 movl %eax, %cr4
39
40 /* Enable the boot page tables */
41 leal (%ebx), %eax
42 movl %eax, %cr3
43
44 /* Enable Long mode in EFER (Extended Feature Enable Register) */
45 movl $MSR_EFER, %ecx
46 rdmsr
47 btsl $_EFER_LME, %eax
48 wrmsr
49
Simon Glass463fac22014-10-10 08:21:55 -060050 /*
51 * Setup for the jump to 64bit mode
52 *
53 * When the jump is performed we will be in long mode but
54 * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
55 * (and in turn EFER.LMA = 1). To jump into 64bit mode we use
56 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
57 * We place all of the values on our mini stack so lret can
58 * used to perform that far jump. See the gdt below.
59 */
60 pop %esi /* setup_base */
61
Simon Glass463fac22014-10-10 08:21:55 -060062 /* Enter paged protected Mode, activating Long Mode */
Simon Glass46faeea2025-03-15 14:25:37 +000063 movl %cr0, %eax
64 orl $X86_CR0_PG, %eax
Simon Glass463fac22014-10-10 08:21:55 -060065 movl %eax, %cr0
66
67 /* Jump from 32bit compatibility mode into 64bit mode. */
Simon Glass355dae22025-03-15 14:25:39 +000068 ljmp $(X86_GDT_ENTRY_64BIT_CS * X86_GDT_ENTRY_SIZE), $lret_target
Simon Glass463fac22014-10-10 08:21:55 -060069
Simon Glass355dae22025-03-15 14:25:39 +000070.code64
Simon Glass463fac22014-10-10 08:21:55 -060071lret_target:
Simon Glass355dae22025-03-15 14:25:39 +000072 pop %rax /* target */
73 jmp *%rax /* Jump to the 64-bit target */
Simon Glass463fac22014-10-10 08:21:55 -060074
Bin Meng17b7b602019-01-31 08:22:13 -080075.globl call64_stub_size
76call64_stub_size:
77 .long . - cpu_call64
78
Simon Glass463fac22014-10-10 08:21:55 -060079 .data
Simon Glass1e32ede2017-01-16 07:04:15 -070080 .align 16
81 .globl gdt64
82gdt64:
Simon Glass463fac22014-10-10 08:21:55 -060083gdt:
Simon Glassf2d1a112015-07-31 09:31:30 -060084 .word gdt_end - gdt - 1
85 .long gdt /* Fixed up by code above */
Simon Glass463fac22014-10-10 08:21:55 -060086 .word 0
87 .quad 0x0000000000000000 /* NULL descriptor */
88 .quad 0x00af9a000000ffff /* __KERNEL_CS */
89 .quad 0x00cf92000000ffff /* __KERNEL_DS */
90 .quad 0x0080890000000000 /* TS descriptor */
91 .quad 0x0000000000000000 /* TS continued */
92gdt_end: