1 TITLE LongMode.asm: Assembly code for the entering long mode
3 ;------------------------------------------------------------------------------
5 ;* Copyright (c) 2006, Intel Corporation
6 ;* All rights reserved. This program and the accompanying materials
7 ;* are licensed and made available under the terms and conditions of the BSD License
8 ;* which accompanies this distribution. The full text of the license may be found at
9 ;* http://opensource.org/licenses/bsd-license.php
11 ;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 ;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 ;* Transition from 32-bit protected mode EFI environment into x64
19 ;* 64-bit bit long mode.
21 ;------------------------------------------------------------------------------
27 ; Create the exception handler code in IA32 C code
35 _LoadGo64Gdt PROC Near Public
44 ; Reload the selectors
46 ; Make the Selectors 64-bit ready
48 mov edi, OFFSET gdtr ; Load GDT register
49 mov ax,cs ; Get the selector data from our code image
51 lgdt FWORD PTR es:[edi] ; and update the GDTR
54 db 0eah ; Far Jump Offset:Selector to reload CS
55 dd OFFSET DataSelectorRld; Offset is ensuing instruction boundary
56 dw LINEAR_CODE_SEL ; Selector is our code selector, 10h
58 mov ax, SYS_DATA_SEL ; Update the Base for the new selectors, too
73 ; IN EFI_PHYSICAL_ADDRESS PageTables,
74 ; IN EFI_PHYSICAL_ADDRESS HobStart,
75 ; IN EFI_PHYSICAL_ADDRESS Stack,
76 ; IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint,
77 ; IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
80 ; Input: [ebp][0h] = Original ebp
81 ; [ebp][4h] = Return address
82 ; [ebp][8h] = PageTables
83 ; [ebp][10h] = HobStart
85 ; [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer)
86 ; [ebp][28h] = CodeEntryPoint2 <--- Call this second
89 _ActivateLongMode PROC Near Public
94 ; Use CPUID to determine if the processor supports long mode.
96 mov eax, 80000000h ; Extended-function code 8000000h.
97 cpuid ; Is largest extended function
98 cmp eax, 80000000h ; any function > 80000000h?
99 jbe no_long_mode ; If not, no long mode.
100 mov eax, 80000001h ; Extended-function code 8000001h.
101 cpuid ; Now EDX = extended-features flags.
102 bt edx, 29 ; Test if long mode is supported.
103 jnc no_long_mode ; Exit if not supported.
106 ; Enable the 64-bit page-translation-table entries by
107 ; setting CR4.PAE=1 (this is _required_ before activating
108 ; long mode). Paging is not enabled until after long mode
116 ; Get the long-mode page tables, and initialize the
117 ; 64-bit CR3 (page-table base address) to point to the base
118 ; of the PML4 page table. The PML4 page table must be located
119 ; below 4 Gbytes because only 32 bits of CR3 are loaded when
120 ; the processor is not in 64-bit mode.
122 mov eax, [ebp+8h] ; Get Page Tables
123 mov cr3, eax ; Initialize CR3 with PML4 base.
126 ; Enable long mode (set EFER.LME=1).
128 mov ecx, 0c0000080h ; EFER MSR number.
130 bts eax, 8 ; Set LME=1.
134 ; Enable paging to activate long mode (set CR0.PG=1)
138 mov eax, cr0 ; Read CR0.
139 bts eax, 31 ; Set PG=1.
140 mov cr0, eax ; Write CR0.
145 ; This is the next instruction after enabling paging. Jump to long mode
148 db 0eah ; Far Jump Offset:Selector to reload CS
149 dd OFFSET in_long_mode; Offset is ensuing instruction boundary
150 dw SYS_CODE64_SEL ; Selector is our code selector, 10h
152 mov ax, SYS_DATA64_SEL
160 ; We're in long mode, so marshall the arguments to call the
161 ; passed in function pointers
163 ; [ebp][10h] = HobStart
165 ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
166 ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second
169 mov ebx, [ebp+18h] ; Setup the stack
171 mov esp, ebx ; On a new stack now
174 mov ecx, [ebp+10h] ; Pass Hob Start in RCX
176 mov eax, [ebp+20h] ; Get the function pointer for
177 ; PpisNeededByDxeIplEntryPoint into EAX
179 ;; 00000905 FF D0 call rax
184 mov ecx, [ebp+10h] ; Pass Hob Start in RCX
186 mov eax, [ebp+28h] ; Get the function pointer for
187 ; DxeCoreEntryPoint into EAX
189 ;; 00000905 FF D0 call rax
194 ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
198 _ActivateLongMode endp
202 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
203 dd OFFSET GDT_BASE ; (GDT base gets set above)
205 ;-----------------------------------------------------------------------------;
206 ; global descriptor table (GDT)
207 ;-----------------------------------------------------------------------------;
214 NULL_SEL equ $-GDT_BASE ; Selector [0]
219 db 0 ; limit 19:16, flags
222 ; linear data segment descriptor
223 LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
224 dw 0FFFFh ; limit 0xFFFFF
227 db 092h ; present, ring 0, data, expand-up, writable
228 db 0CFh ; page-granular, 32-bit
231 ; linear code segment descriptor
232 LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
233 dw 0FFFFh ; limit 0xFFFFF
236 db 09Fh ; present, ring 0, data, expand-up, writable
237 db 0CFh ; page-granular, 32-bit
240 ; system data segment descriptor
241 SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
242 dw 0FFFFh ; limit 0xFFFFF
245 db 093h ; present, ring 0, data, expand-up, writable
246 db 0CFh ; page-granular, 32-bit
249 ; system code segment descriptor
250 SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
251 dw 0FFFFh ; limit 0xFFFFF
254 db 09Ah ; present, ring 0, data, expand-up, writable
255 db 0CFh ; page-granular, 32-bit
258 ; spare segment descriptor
259 SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
263 db 0 ; present, ring 0, data, expand-up, writable
264 db 0 ; page-granular, 32-bit
268 ; system data segment descriptor
270 SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
271 dw 0FFFFh ; limit 0xFFFFF
274 db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
275 db 0CFh ; G | D | L | AVL | Segment [19..16]
279 ; system code segment descriptor
281 SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
282 dw 0FFFFh ; limit 0xFFFFF
285 db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
286 db 0AFh ; G | D | L | AVL | Segment [19..16]
289 ; spare segment descriptor
290 SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
294 db 0 ; present, ring 0, data, expand-up, writable
295 db 0 ; page-granular, 32-bit
302 ;------------------------------------------------------------------------------
303 ; Generic IDT Vector Handlers for the Host. They are all the same so they
304 ; will compress really well.
306 ; By knowing the return address for Vector 00 you can can calculate the
307 ; vector number by looking at the call CommonInterruptEntry return address.
308 ; (return address - AsmIdtVector00Base)/8 == IDT index
310 ;------------------------------------------------------------------------------
312 _AsmIdtVector00 PROC NEAR PUBLIC
313 call CommonInterruptEntry
315 AsmIdtVector00Base PROC NEAR PUBLIC
319 call CommonInterruptEntry
323 call CommonInterruptEntry
327 call CommonInterruptEntry
331 call CommonInterruptEntry
335 call CommonInterruptEntry
339 call CommonInterruptEntry
343 call CommonInterruptEntry
347 call CommonInterruptEntry
351 call CommonInterruptEntry
355 call CommonInterruptEntry
359 call CommonInterruptEntry
363 call CommonInterruptEntry
367 call CommonInterruptEntry
371 call CommonInterruptEntry
375 call CommonInterruptEntry
379 call CommonInterruptEntry
383 call CommonInterruptEntry
387 call CommonInterruptEntry
391 call CommonInterruptEntry
395 call CommonInterruptEntry
399 call CommonInterruptEntry
403 call CommonInterruptEntry
407 call CommonInterruptEntry
411 call CommonInterruptEntry
415 call CommonInterruptEntry
419 call CommonInterruptEntry
423 call CommonInterruptEntry
427 call CommonInterruptEntry
431 call CommonInterruptEntry
435 call CommonInterruptEntry
439 call CommonInterruptEntry
443 call CommonInterruptEntry
447 call CommonInterruptEntry
451 call CommonInterruptEntry
455 call CommonInterruptEntry
459 call CommonInterruptEntry
463 call CommonInterruptEntry
467 call CommonInterruptEntry
471 call CommonInterruptEntry
475 call CommonInterruptEntry
479 call CommonInterruptEntry
483 call CommonInterruptEntry
487 call CommonInterruptEntry
491 call CommonInterruptEntry
495 call CommonInterruptEntry
499 call CommonInterruptEntry
503 call CommonInterruptEntry
507 call CommonInterruptEntry
511 call CommonInterruptEntry
515 call CommonInterruptEntry
519 call CommonInterruptEntry
523 call CommonInterruptEntry
527 call CommonInterruptEntry
531 call CommonInterruptEntry
535 call CommonInterruptEntry
539 call CommonInterruptEntry
543 call CommonInterruptEntry
547 call CommonInterruptEntry
551 call CommonInterruptEntry
555 call CommonInterruptEntry
559 call CommonInterruptEntry
563 call CommonInterruptEntry
567 call CommonInterruptEntry
571 call CommonInterruptEntry
575 call CommonInterruptEntry
579 call CommonInterruptEntry
583 call CommonInterruptEntry
587 call CommonInterruptEntry
591 call CommonInterruptEntry
595 call CommonInterruptEntry
599 call CommonInterruptEntry
603 call CommonInterruptEntry
607 call CommonInterruptEntry
611 call CommonInterruptEntry
615 call CommonInterruptEntry
619 call CommonInterruptEntry
623 call CommonInterruptEntry
627 call CommonInterruptEntry
631 call CommonInterruptEntry
635 call CommonInterruptEntry
639 call CommonInterruptEntry
643 call CommonInterruptEntry
647 call CommonInterruptEntry
651 call CommonInterruptEntry
655 call CommonInterruptEntry
659 call CommonInterruptEntry
663 call CommonInterruptEntry
667 call CommonInterruptEntry
671 call CommonInterruptEntry
675 call CommonInterruptEntry
679 call CommonInterruptEntry
683 call CommonInterruptEntry
687 call CommonInterruptEntry
691 call CommonInterruptEntry
695 call CommonInterruptEntry
699 call CommonInterruptEntry
703 call CommonInterruptEntry
707 call CommonInterruptEntry
711 call CommonInterruptEntry
715 call CommonInterruptEntry
719 call CommonInterruptEntry
723 call CommonInterruptEntry
727 call CommonInterruptEntry
731 call CommonInterruptEntry
735 call CommonInterruptEntry
739 call CommonInterruptEntry
743 call CommonInterruptEntry
747 call CommonInterruptEntry
751 call CommonInterruptEntry
755 call CommonInterruptEntry
759 call CommonInterruptEntry
763 call CommonInterruptEntry
767 call CommonInterruptEntry
771 call CommonInterruptEntry
775 call CommonInterruptEntry
779 call CommonInterruptEntry
783 call CommonInterruptEntry
787 call CommonInterruptEntry
791 call CommonInterruptEntry
795 call CommonInterruptEntry
799 call CommonInterruptEntry
803 call CommonInterruptEntry
807 call CommonInterruptEntry
811 call CommonInterruptEntry
815 call CommonInterruptEntry
819 call CommonInterruptEntry
823 call CommonInterruptEntry
827 call CommonInterruptEntry
831 call CommonInterruptEntry
835 call CommonInterruptEntry
839 call CommonInterruptEntry
843 call CommonInterruptEntry
847 call CommonInterruptEntry
851 call CommonInterruptEntry
855 call CommonInterruptEntry
859 call CommonInterruptEntry
863 call CommonInterruptEntry
867 call CommonInterruptEntry
871 call CommonInterruptEntry
875 call CommonInterruptEntry
879 call CommonInterruptEntry
883 call CommonInterruptEntry
887 call CommonInterruptEntry
891 call CommonInterruptEntry
895 call CommonInterruptEntry
899 call CommonInterruptEntry
903 call CommonInterruptEntry
907 call CommonInterruptEntry
911 call CommonInterruptEntry
915 call CommonInterruptEntry
919 call CommonInterruptEntry
923 call CommonInterruptEntry
927 call CommonInterruptEntry
931 call CommonInterruptEntry
935 call CommonInterruptEntry
939 call CommonInterruptEntry
943 call CommonInterruptEntry
947 call CommonInterruptEntry
951 call CommonInterruptEntry
955 call CommonInterruptEntry
959 call CommonInterruptEntry
963 call CommonInterruptEntry
967 call CommonInterruptEntry
971 call CommonInterruptEntry
975 call CommonInterruptEntry
979 call CommonInterruptEntry
983 call CommonInterruptEntry
987 call CommonInterruptEntry
991 call CommonInterruptEntry
995 call CommonInterruptEntry
999 call CommonInterruptEntry
1003 call CommonInterruptEntry
1007 call CommonInterruptEntry
1011 call CommonInterruptEntry
1015 call CommonInterruptEntry
1019 call CommonInterruptEntry
1023 call CommonInterruptEntry
1027 call CommonInterruptEntry
1031 call CommonInterruptEntry
1035 call CommonInterruptEntry
1039 call CommonInterruptEntry
1043 call CommonInterruptEntry
1047 call CommonInterruptEntry
1051 call CommonInterruptEntry
1055 call CommonInterruptEntry
1059 call CommonInterruptEntry
1063 call CommonInterruptEntry
1067 call CommonInterruptEntry
1071 call CommonInterruptEntry
1075 call CommonInterruptEntry
1079 call CommonInterruptEntry
1083 call CommonInterruptEntry
1087 call CommonInterruptEntry
1091 call CommonInterruptEntry
1095 call CommonInterruptEntry
1099 call CommonInterruptEntry
1103 call CommonInterruptEntry
1107 call CommonInterruptEntry
1111 call CommonInterruptEntry
1115 call CommonInterruptEntry
1119 call CommonInterruptEntry
1123 call CommonInterruptEntry
1127 call CommonInterruptEntry
1131 call CommonInterruptEntry
1135 call CommonInterruptEntry
1139 call CommonInterruptEntry
1143 call CommonInterruptEntry
1147 call CommonInterruptEntry
1151 call CommonInterruptEntry
1155 call CommonInterruptEntry
1159 call CommonInterruptEntry
1163 call CommonInterruptEntry
1167 call CommonInterruptEntry
1171 call CommonInterruptEntry
1175 call CommonInterruptEntry
1179 call CommonInterruptEntry
1183 call CommonInterruptEntry
1187 call CommonInterruptEntry
1191 call CommonInterruptEntry
1195 call CommonInterruptEntry
1199 call CommonInterruptEntry
1203 call CommonInterruptEntry
1207 call CommonInterruptEntry
1211 call CommonInterruptEntry
1215 call CommonInterruptEntry
1219 call CommonInterruptEntry
1223 call CommonInterruptEntry
1227 call CommonInterruptEntry
1231 call CommonInterruptEntry
1235 call CommonInterruptEntry
1239 call CommonInterruptEntry
1243 call CommonInterruptEntry
1247 call CommonInterruptEntry
1251 call CommonInterruptEntry
1255 call CommonInterruptEntry
1259 call CommonInterruptEntry
1263 call CommonInterruptEntry
1267 call CommonInterruptEntry
1271 call CommonInterruptEntry
1275 call CommonInterruptEntry
1279 call CommonInterruptEntry
1283 call CommonInterruptEntry
1287 call CommonInterruptEntry
1291 call CommonInterruptEntry
1295 call CommonInterruptEntry
1299 call CommonInterruptEntry
1303 call CommonInterruptEntry
1307 call CommonInterruptEntry
1311 call CommonInterruptEntry
1315 call CommonInterruptEntry
1319 call CommonInterruptEntry
1323 call CommonInterruptEntry
1327 call CommonInterruptEntry
1331 call CommonInterruptEntry
1335 call CommonInterruptEntry
1339 AsmIdtVector00Base ENDP
1342 ;---------------------------------------;
1343 ; CommonInterruptEntry ;
1344 ;---------------------------------------;
1345 ; The follow algorithm is used for the common interrupt routine.
1346 ; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition
1349 CommonInterruptEntry PROC NEAR PUBLIC
1354 CommonInterruptEntry ENDP