uboot/arch/x86/cpu/call64.S
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2014 Google, Inc
   3 * Copyright (C) 1991, 1992, 1993  Linus Torvalds
   4 *
   5 * Parts of this copied from Linux arch/x86/boot/compressed/head_64.S
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#include <asm/global_data.h>
  11#include <asm/msr-index.h>
  12#include <asm/processor-flags.h>
  13
  14.code32
  15.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
  29        /* Load new GDT with the 64bit segments using 32bit descriptor */
  30        leal    gdt, %eax
  31        movl    %eax, gdt+2
  32        lgdt    gdt
  33
  34        /* 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
  48        /* After gdt is loaded */
  49        xorl    %eax, %eax
  50        lldt    %ax
  51        movl    $0x20, %eax
  52        ltr     %ax
  53
  54        /*
  55         * Setup for the jump to 64bit mode
  56         *
  57         * When the jump is performed we will be in long mode but
  58         * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
  59         * (and in turn EFER.LMA = 1). To jump into 64bit mode we use
  60         * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
  61         * We place all of the values on our mini stack so lret can
  62         * used to perform that far jump. See the gdt below.
  63         */
  64        pop     %esi                    /* setup_base */
  65
  66        pushl   $0x10
  67        leal    lret_target, %eax
  68        pushl   %eax
  69
  70        /* Enter paged protected Mode, activating Long Mode */
  71        movl    $(X86_CR0_PG | X86_CR0_PE), %eax
  72        movl    %eax, %cr0
  73
  74        /* Jump from 32bit compatibility mode into 64bit mode. */
  75        lret
  76
  77code64:
  78lret_target:
  79        pop     %eax                    /* target */
  80        mov     %eax, %eax              /* Clear bits 63:32 */
  81        jmp     *%eax                   /* Jump to the 64-bit target */
  82
  83        .data
  84gdt:
  85        .word   gdt_end - gdt - 1
  86        .long   gdt                     /* Fixed up by code above */
  87        .word   0
  88        .quad   0x0000000000000000      /* NULL descriptor */
  89        .quad   0x00af9a000000ffff      /* __KERNEL_CS */
  90        .quad   0x00cf92000000ffff      /* __KERNEL_DS */
  91        .quad   0x0080890000000000      /* TS descriptor */
  92        .quad   0x0000000000000000      /* TS continued */
  93gdt_end:
  94