Home | History | Annotate | Download | only in i386
      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 	.data
     83 	.align	16
     84 	.globl	gdt64
     85 gdt64:
     86 gdt:
     87 	.word	gdt_end - gdt - 1
     88 	.long	gdt			/* Fixed up by code above */
     89 	.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 */
     95 gdt_end:
     96