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