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 ;; 00000905 FF D0 call rax
177 mov ecx, [ebp+10h] ; Pass Hob Start in RCX
179 mov eax, [ebp+28h] ; Get the function pointer for
180 ; DxeCoreEntryPoint into EAX
182 ;; 00000905 FF D0 call rax
187 ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
191 _ActivateLongMode endp
195 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
196 dd OFFSET GDT_BASE ; (GDT base gets set above)
198 ;-----------------------------------------------------------------------------;
199 ; global descriptor table (GDT)
200 ;-----------------------------------------------------------------------------;
207 NULL_SEL equ $-GDT_BASE ; Selector [0]
212 db 0 ; limit 19:16, flags
215 ; linear data segment descriptor
216 LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
217 dw 0FFFFh ; limit 0xFFFFF
220 db 092h ; present, ring 0, data, expand-up, writable
221 db 0CFh ; page-granular, 32-bit
224 ; linear code segment descriptor
225 LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
226 dw 0FFFFh ; limit 0xFFFFF
229 db 09Fh ; present, ring 0, data, expand-up, writable
230 db 0CFh ; page-granular, 32-bit
233 ; system data segment descriptor
234 SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
235 dw 0FFFFh ; limit 0xFFFFF
238 db 093h ; present, ring 0, data, expand-up, writable
239 db 0CFh ; page-granular, 32-bit
242 ; system code segment descriptor
243 SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
244 dw 0FFFFh ; limit 0xFFFFF
247 db 09Ah ; present, ring 0, data, expand-up, writable
248 db 0CFh ; page-granular, 32-bit
251 ; spare segment descriptor
252 SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
256 db 0 ; present, ring 0, data, expand-up, writable
257 db 0 ; page-granular, 32-bit
261 ; system data segment descriptor
263 SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
264 dw 0FFFFh ; limit 0xFFFFF
267 db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
268 db 0CFh ; G | D | L | AVL | Segment [19..16]
272 ; system code segment descriptor
274 SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
275 dw 0FFFFh ; limit 0xFFFFF
278 db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
279 db 0AFh ; G | D | L | AVL | Segment [19..16]
282 ; spare segment descriptor
283 SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
287 db 0 ; present, ring 0, data, expand-up, writable
288 db 0 ; page-granular, 32-bit
295 ;------------------------------------------------------------------------------
296 ; Generic IDT Vector Handlers for the Host. They are all the same so they
297 ; will compress really well.
299 ; By knowing the return address for Vector 00 you can can calculate the
300 ; vector number by looking at the call CommonInterruptEntry return address.
301 ; (return address - AsmIdtVector00Base)/8 == IDT index
303 ;------------------------------------------------------------------------------
305 _AsmIdtVector00 PROC NEAR PUBLIC
306 call CommonInterruptEntry
308 AsmIdtVector00Base PROC NEAR PUBLIC
312 call CommonInterruptEntry
316 call CommonInterruptEntry
320 call CommonInterruptEntry
324 call CommonInterruptEntry
328 call CommonInterruptEntry
332 call CommonInterruptEntry
336 call CommonInterruptEntry
340 call CommonInterruptEntry
344 call CommonInterruptEntry
348 call CommonInterruptEntry
352 call CommonInterruptEntry
356 call CommonInterruptEntry
360 call CommonInterruptEntry
364 call CommonInterruptEntry
368 call CommonInterruptEntry
372 call CommonInterruptEntry
376 call CommonInterruptEntry
380 call CommonInterruptEntry
384 call CommonInterruptEntry
388 call CommonInterruptEntry
392 call CommonInterruptEntry
396 call CommonInterruptEntry
400 call CommonInterruptEntry
404 call CommonInterruptEntry
408 call CommonInterruptEntry
412 call CommonInterruptEntry
416 call CommonInterruptEntry
420 call CommonInterruptEntry
424 call CommonInterruptEntry
428 call CommonInterruptEntry
432 call CommonInterruptEntry
436 call CommonInterruptEntry
440 call CommonInterruptEntry
444 call CommonInterruptEntry
448 call CommonInterruptEntry
452 call CommonInterruptEntry
456 call CommonInterruptEntry
460 call CommonInterruptEntry
464 call CommonInterruptEntry
468 call CommonInterruptEntry
472 call CommonInterruptEntry
476 call CommonInterruptEntry
480 call CommonInterruptEntry
484 call CommonInterruptEntry
488 call CommonInterruptEntry
492 call CommonInterruptEntry
496 call CommonInterruptEntry
500 call CommonInterruptEntry
504 call CommonInterruptEntry
508 call CommonInterruptEntry
512 call CommonInterruptEntry
516 call CommonInterruptEntry
520 call CommonInterruptEntry
524 call CommonInterruptEntry
528 call CommonInterruptEntry
532 call CommonInterruptEntry
536 call CommonInterruptEntry
540 call CommonInterruptEntry
544 call CommonInterruptEntry
548 call CommonInterruptEntry
552 call CommonInterruptEntry
556 call CommonInterruptEntry
560 call CommonInterruptEntry
564 call CommonInterruptEntry
568 call CommonInterruptEntry
572 call CommonInterruptEntry
576 call CommonInterruptEntry
580 call CommonInterruptEntry
584 call CommonInterruptEntry
588 call CommonInterruptEntry
592 call CommonInterruptEntry
596 call CommonInterruptEntry
600 call CommonInterruptEntry
604 call CommonInterruptEntry
608 call CommonInterruptEntry
612 call CommonInterruptEntry
616 call CommonInterruptEntry
620 call CommonInterruptEntry
624 call CommonInterruptEntry
628 call CommonInterruptEntry
632 call CommonInterruptEntry
636 call CommonInterruptEntry
640 call CommonInterruptEntry
644 call CommonInterruptEntry
648 call CommonInterruptEntry
652 call CommonInterruptEntry
656 call CommonInterruptEntry
660 call CommonInterruptEntry
664 call CommonInterruptEntry
668 call CommonInterruptEntry
672 call CommonInterruptEntry
676 call CommonInterruptEntry
680 call CommonInterruptEntry
684 call CommonInterruptEntry
688 call CommonInterruptEntry
692 call CommonInterruptEntry
696 call CommonInterruptEntry
700 call CommonInterruptEntry
704 call CommonInterruptEntry
708 call CommonInterruptEntry
712 call CommonInterruptEntry
716 call CommonInterruptEntry
720 call CommonInterruptEntry
724 call CommonInterruptEntry
728 call CommonInterruptEntry
732 call CommonInterruptEntry
736 call CommonInterruptEntry
740 call CommonInterruptEntry
744 call CommonInterruptEntry
748 call CommonInterruptEntry
752 call CommonInterruptEntry
756 call CommonInterruptEntry
760 call CommonInterruptEntry
764 call CommonInterruptEntry
768 call CommonInterruptEntry
772 call CommonInterruptEntry
776 call CommonInterruptEntry
780 call CommonInterruptEntry
784 call CommonInterruptEntry
788 call CommonInterruptEntry
792 call CommonInterruptEntry
796 call CommonInterruptEntry
800 call CommonInterruptEntry
804 call CommonInterruptEntry
808 call CommonInterruptEntry
812 call CommonInterruptEntry
816 call CommonInterruptEntry
820 call CommonInterruptEntry
824 call CommonInterruptEntry
828 call CommonInterruptEntry
832 call CommonInterruptEntry
836 call CommonInterruptEntry
840 call CommonInterruptEntry
844 call CommonInterruptEntry
848 call CommonInterruptEntry
852 call CommonInterruptEntry
856 call CommonInterruptEntry
860 call CommonInterruptEntry
864 call CommonInterruptEntry
868 call CommonInterruptEntry
872 call CommonInterruptEntry
876 call CommonInterruptEntry
880 call CommonInterruptEntry
884 call CommonInterruptEntry
888 call CommonInterruptEntry
892 call CommonInterruptEntry
896 call CommonInterruptEntry
900 call CommonInterruptEntry
904 call CommonInterruptEntry
908 call CommonInterruptEntry
912 call CommonInterruptEntry
916 call CommonInterruptEntry
920 call CommonInterruptEntry
924 call CommonInterruptEntry
928 call CommonInterruptEntry
932 call CommonInterruptEntry
936 call CommonInterruptEntry
940 call CommonInterruptEntry
944 call CommonInterruptEntry
948 call CommonInterruptEntry
952 call CommonInterruptEntry
956 call CommonInterruptEntry
960 call CommonInterruptEntry
964 call CommonInterruptEntry
968 call CommonInterruptEntry
972 call CommonInterruptEntry
976 call CommonInterruptEntry
980 call CommonInterruptEntry
984 call CommonInterruptEntry
988 call CommonInterruptEntry
992 call CommonInterruptEntry
996 call CommonInterruptEntry
1000 call CommonInterruptEntry
1004 call CommonInterruptEntry
1008 call CommonInterruptEntry
1012 call CommonInterruptEntry
1016 call CommonInterruptEntry
1020 call CommonInterruptEntry
1024 call CommonInterruptEntry
1028 call CommonInterruptEntry
1032 call CommonInterruptEntry
1036 call CommonInterruptEntry
1040 call CommonInterruptEntry
1044 call CommonInterruptEntry
1048 call CommonInterruptEntry
1052 call CommonInterruptEntry
1056 call CommonInterruptEntry
1060 call CommonInterruptEntry
1064 call CommonInterruptEntry
1068 call CommonInterruptEntry
1072 call CommonInterruptEntry
1076 call CommonInterruptEntry
1080 call CommonInterruptEntry
1084 call CommonInterruptEntry
1088 call CommonInterruptEntry
1092 call CommonInterruptEntry
1096 call CommonInterruptEntry
1100 call CommonInterruptEntry
1104 call CommonInterruptEntry
1108 call CommonInterruptEntry
1112 call CommonInterruptEntry
1116 call CommonInterruptEntry
1120 call CommonInterruptEntry
1124 call CommonInterruptEntry
1128 call CommonInterruptEntry
1132 call CommonInterruptEntry
1136 call CommonInterruptEntry
1140 call CommonInterruptEntry
1144 call CommonInterruptEntry
1148 call CommonInterruptEntry
1152 call CommonInterruptEntry
1156 call CommonInterruptEntry
1160 call CommonInterruptEntry
1164 call CommonInterruptEntry
1168 call CommonInterruptEntry
1172 call CommonInterruptEntry
1176 call CommonInterruptEntry
1180 call CommonInterruptEntry
1184 call CommonInterruptEntry
1188 call CommonInterruptEntry
1192 call CommonInterruptEntry
1196 call CommonInterruptEntry
1200 call CommonInterruptEntry
1204 call CommonInterruptEntry
1208 call CommonInterruptEntry
1212 call CommonInterruptEntry
1216 call CommonInterruptEntry
1220 call CommonInterruptEntry
1224 call CommonInterruptEntry
1228 call CommonInterruptEntry
1232 call CommonInterruptEntry
1236 call CommonInterruptEntry
1240 call CommonInterruptEntry
1244 call CommonInterruptEntry
1248 call CommonInterruptEntry
1252 call CommonInterruptEntry
1256 call CommonInterruptEntry
1260 call CommonInterruptEntry
1264 call CommonInterruptEntry
1268 call CommonInterruptEntry
1272 call CommonInterruptEntry
1276 call CommonInterruptEntry
1280 call CommonInterruptEntry
1284 call CommonInterruptEntry
1288 call CommonInterruptEntry
1292 call CommonInterruptEntry
1296 call CommonInterruptEntry
1300 call CommonInterruptEntry
1304 call CommonInterruptEntry
1308 call CommonInterruptEntry
1312 call CommonInterruptEntry
1316 call CommonInterruptEntry
1320 call CommonInterruptEntry
1324 call CommonInterruptEntry
1328 call CommonInterruptEntry
1332 AsmIdtVector00Base ENDP
1335 ;---------------------------------------;
1336 ; CommonInterruptEntry ;
1337 ;---------------------------------------;
1338 ; The follow algorithm is used for the common interrupt routine.
1339 ; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition
1342 CommonInterruptEntry PROC NEAR PUBLIC
1347 CommonInterruptEntry ENDP