Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
5.0 KiB

  1. ;++
  2. ;
  3. ;Copyright (c) 2000 Microsoft Corporation
  4. ;
  5. ;Module Name:
  6. ;
  7. ; amd64s.asm
  8. ;
  9. ;Abstract:
  10. ;
  11. ; Contains routines to aid in detecting and enabling Amd64 long mode.
  12. ;
  13. ;Author:
  14. ;
  15. ; Forrest Foltz (forrestf) 04-20-00
  16. ;
  17. ;
  18. ;Revision History:
  19. ;
  20. ;--
  21. .586p
  22. .xlist
  23. include ks386.inc
  24. .list
  25. extrn _BlAmd64GdtDescriptor:QWORD
  26. extrn _BlAmd64IdtDescriptor:QWORD
  27. extrn _BlAmd64IdleStack64:QWORD
  28. extrn _BlAmd64TopLevelPte:QWORD
  29. extrn _BlAmd64KernelEntry:QWORD
  30. extrn _BlAmd64LoaderParameterBlock:QWORD
  31. extrn _BlAmd64_MSR_EFER:DWORD
  32. extrn _BlAmd64_MSR_EFER_Flags:DWORD
  33. extrn _BlAmd64_MSR_GS_BASE:DWORD
  34. extrn _BlAmd64_KGDT64_SYS_TSS:WORD
  35. extrn _BlAmd32GdtDescriptor:QWORD
  36. OP64 macro
  37. db 048h
  38. endm
  39. ;
  40. ; LOADREG loads the 64-bit contents of a memory location specified by
  41. ; a 32-bit immediate address.
  42. ;
  43. ; The resultant 64-bit address is zero-extended, as a result this macro
  44. ; only works with addresses < 2^32.
  45. ;
  46. ; This macro also assumes that esi is zero.
  47. ;
  48. LDREG64 macro reg, address
  49. OP64
  50. mov reg, ds:[esi + offset address]
  51. endm
  52. _TEXT SEGMENT PARA PUBLIC 'CODE'
  53. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  54. EFLAGS_ID equ 200000h
  55. ;++
  56. ;
  57. ; BOOLEAN
  58. ; BlIsAmd64Supported (
  59. ; VOID
  60. ; )
  61. ;
  62. ; Routine Description:
  63. ;
  64. ; This rouine determines whether the current processor supports AMD64
  65. ; mode, a.k.a. "long mode".
  66. ;
  67. ; Arguments:
  68. ;
  69. ; None.
  70. ;
  71. ; Return value:
  72. ;
  73. ; 0 if long mode is not supported, non-zero otherwise.
  74. ;
  75. ;--
  76. public _BlIsAmd64Supported@0
  77. _BlIsAmd64Supported@0 proc
  78. ;
  79. ; First determine whether the CPUID instruction is supported. If
  80. ; the EFLAGS_ID bit "sticks" when popped into the flags
  81. ; register then the CPUID instruction is available.
  82. ;
  83. mov ecx, EFLAGS_ID
  84. pushfd
  85. pop eax ; eax == flags
  86. xor ecx, eax ; ecx == flags ^ EFLAGS_ID
  87. push ecx
  88. popfd ; load new flags
  89. pushfd
  90. pop ecx ; ecx == result of flag load
  91. xor eax, ecx ; Q: did the EFLAGS_ID bit stick?
  92. jz done ; N: CPUID is not available
  93. ;
  94. ; We can use the CPUID instruction. Detect whether this is an
  95. ; AMD processor and if so whether long mode is supported.
  96. ;
  97. push ebx ; CPUID steps on eax, ebx, ecx, edx
  98. xor eax, eax ; eax = 0
  99. cpuid
  100. xor eax, eax ; Assume no long mode
  101. cmp ebx, 'htuA' ; Q: ebx == 'Auth' ?
  102. jne nolong ; N: no long mode
  103. ;
  104. ; We have an AMD processor, now determine whether long mode is
  105. ; available.
  106. ;
  107. mov eax, 80000001h
  108. xor edx, edx
  109. cpuid
  110. bt edx, 29 ; Q: Bit 29 is long mode bit, is it set?
  111. sbb eax, eax ; Yes (eax != 0) if carry set, else eax == 0
  112. nolong: pop ebx
  113. done: ret
  114. _BlIsAmd64Supported@0 endp
  115. ;++
  116. ;
  117. ; VOID
  118. ; BlAmd64SwitchToLongMode (
  119. ; VOID
  120. ; )
  121. ;
  122. ; Routine Description:
  123. ;
  124. ; Arguments:
  125. ;
  126. ; None.
  127. ;
  128. ; Return value:
  129. ;
  130. ; None.
  131. ;
  132. ;--
  133. public _BlAmd64SwitchToLongMode@0
  134. _BlAmd64SwitchToLongMode@0 proc
  135. cli
  136. ;
  137. ; Disable paging
  138. ;
  139. mov eax, cr0
  140. and eax, NOT CR0_PG
  141. mov cr0, eax
  142. jmp $+2
  143. ;
  144. ; Enable XMM and physical address extensions (paging still off)
  145. ;
  146. mov eax, cr4
  147. or eax, CR4_PAE OR CR4_FXSR OR CR4_XMMEXCPT
  148. mov cr4, eax
  149. ;
  150. ; Reference the four-level paging structure. This must exist
  151. ; below 4G physical (in fact it is somewhere in the low 32MB)
  152. ;
  153. mov eax, DWORD PTR [_BlAmd64TopLevelPte]
  154. and eax, 0FFFFF000h
  155. mov cr3, eax
  156. ;
  157. ; Set Long Mode enable and enable syscall
  158. ;
  159. mov ecx, [_BlAmd64_MSR_EFER]
  160. rdmsr
  161. or eax, [_BlAmd64_MSR_EFER_Flags]
  162. wrmsr
  163. ;
  164. ; Turn paging on
  165. ;
  166. mov eax, cr0
  167. or eax, CR0_PG
  168. mov cr0, eax
  169. jmp $+2
  170. ;
  171. ; Load the new global descriptor table. Note that because we're
  172. ; not in long mode (current code selector indicates compatibility
  173. ; mode), only a 32-bit base is loaded here.
  174. ;
  175. lgdt fword ptr _BlAmd32GdtDescriptor
  176. ;
  177. ; Far jump to the 64-bit code segment.
  178. ;
  179. db 0eah
  180. dd start64
  181. ;
  182. ; The following selector is set in amd64.c, BlAmd64BuildAmd64GDT, and
  183. ; is included as part of the far jump instruction.
  184. ;
  185. public _BlAmd64_KGDT64_R0_CODE
  186. _BlAmd64_KGDT64_R0_CODE:
  187. dw ?
  188. start64:
  189. ;
  190. ; Zero rsi so that the LDREG64 macros work
  191. ;
  192. OP64
  193. sub esi, esi
  194. ;
  195. ; Running in long mode now. Execute another lgdt, this one
  196. ; referencing the 64-bit mapping of the gdt.
  197. ;
  198. ; Note that an esi-relative address is used to avoid RIP-relative
  199. ; addressing.
  200. ;
  201. lgdt fword ptr ds:[esi + offset _BlAmd64GdtDescriptor]
  202. ;
  203. ; Load the new interrupt descriptor table
  204. ;
  205. lidt fword ptr ds:[esi + offset _BlAmd64IdtDescriptor]
  206. ;
  207. ; Switch stacks to the 64-bit idle stack
  208. ;
  209. LDREG64 esp, _BlAmd64IdleStack64
  210. ;
  211. ; Set the current TSS
  212. ;
  213. LDREG64 eax, _BlAmd64_KGDT64_SYS_TSS
  214. ltr ax
  215. ;
  216. ; Set ss to the kernel-mode SS value (0)
  217. ;
  218. sub eax, eax
  219. mov ss, ax
  220. ;
  221. ; Allocate space on the stack for a parameter target area and jump
  222. ; to the kernel entrypoint.
  223. ;
  224. OP64
  225. sub esp, 16
  226. LDREG64 ecx, _BlAmd64LoaderParameterBlock
  227. LDREG64 eax, _BlAmd64KernelEntry
  228. call eax
  229. _BlAmd64SwitchToLongMode@0 endp
  230. _TEXT ends