call64.S 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. #include <asm/global_data.h>
  10. #include <asm/msr-index.h>
  11. #include <asm/processor-flags.h>
  12. .code32
  13. .globl cpu_call64
  14. cpu_call64:
  15. /*
  16. * cpu_call64(ulong pgtable, ulong setup_base, ulong target)
  17. *
  18. * eax - pgtable
  19. * edx - setup_base
  20. * ecx - target
  21. */
  22. cli
  23. push %ecx /* arg2 = target */
  24. push %edx /* arg1 = setup_base */
  25. mov %eax, %ebx
  26. /* Load new GDT with the 64bit segments using 32bit descriptor */
  27. leal gdt, %eax
  28. movl %eax, gdt+2
  29. lgdt gdt
  30. /* Enable PAE mode */
  31. movl $(X86_CR4_PAE), %eax
  32. movl %eax, %cr4
  33. /* Enable the boot page tables */
  34. leal (%ebx), %eax
  35. movl %eax, %cr3
  36. /* Enable Long mode in EFER (Extended Feature Enable Register) */
  37. movl $MSR_EFER, %ecx
  38. rdmsr
  39. btsl $_EFER_LME, %eax
  40. wrmsr
  41. /* After gdt is loaded */
  42. xorl %eax, %eax
  43. lldt %ax
  44. movl $0x20, %eax
  45. ltr %ax
  46. /*
  47. * Setup for the jump to 64bit mode
  48. *
  49. * When the jump is performed we will be in long mode but
  50. * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
  51. * (and in turn EFER.LMA = 1). To jump into 64bit mode we use
  52. * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
  53. * We place all of the values on our mini stack so lret can
  54. * used to perform that far jump. See the gdt below.
  55. */
  56. pop %esi /* setup_base */
  57. pushl $0x10
  58. leal lret_target, %eax
  59. pushl %eax
  60. /* Enter paged protected Mode, activating Long Mode */
  61. movl $(X86_CR0_PG | X86_CR0_PE), %eax
  62. movl %eax, %cr0
  63. /* Jump from 32bit compatibility mode into 64bit mode. */
  64. lret
  65. code64:
  66. lret_target:
  67. pop %eax /* target */
  68. mov %eax, %eax /* Clear bits 63:32 */
  69. jmp *%eax /* Jump to the 64-bit target */
  70. .data
  71. gdt:
  72. .word gdt_end - gdt
  73. .long gdt
  74. .word 0
  75. .quad 0x0000000000000000 /* NULL descriptor */
  76. .quad 0x00af9a000000ffff /* __KERNEL_CS */
  77. .quad 0x00cf92000000ffff /* __KERNEL_DS */
  78. .quad 0x0080890000000000 /* TS descriptor */
  79. .quad 0x0000000000000000 /* TS continued */
  80. gdt_end: